Explore the login page for unexpected behavior
Preconditions (2)
✅ Expected Result: The login page should handle all inputs gracefully, show correct error messages for invalid inputs, not crash or freeze, and allow keyboard navigation.
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.keys import Keys import unittest class LoginPage: def __init__(self, driver): self.driver = driver self.email_input = (By.ID, 'email') self.password_input = (By.ID, 'password') self.login_button = (By.ID, 'loginBtn') self.error_message = (By.ID, 'errorMsg') def open(self, url): self.driver.get(url) def enter_email(self, email): self.driver.find_element(*self.email_input).clear() self.driver.find_element(*self.email_input).send_keys(email) def enter_password(self, password): self.driver.find_element(*self.password_input).clear() self.driver.find_element(*self.password_input).send_keys(password) def click_login(self): self.driver.find_element(*self.login_button).click() def get_error_message(self): try: return WebDriverWait(self.driver, 5).until( EC.visibility_of_element_located(self.error_message) ).text except: return '' class TestLoginExploratory(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(5) self.login_page = LoginPage(self.driver) self.login_page.open('https://example.com/login') def test_invalid_email_format(self): self.login_page.enter_email('invalid-email') self.login_page.enter_password('Password123') self.login_page.click_login() error = self.login_page.get_error_message() self.assertIn('invalid email', error.lower()) def test_empty_fields(self): self.login_page.enter_email('') self.login_page.enter_password('') self.login_page.click_login() error = self.login_page.get_error_message() self.assertIn('required', error.lower()) def test_long_input_strings(self): long_string = 'a'*500 self.login_page.enter_email(long_string + '@test.com') self.login_page.enter_password(long_string) self.login_page.click_login() error = self.login_page.get_error_message() self.assertTrue(error != '' or True) # Accept error or no crash def test_multiple_quick_clicks(self): self.login_page.enter_email('user@test.com') self.login_page.enter_password('Password123') for _ in range(5): self.login_page.click_login() # Check page still responsive by checking login button enabled login_btn = self.driver.find_element(*self.login_page.login_button) self.assertTrue(login_btn.is_enabled()) def test_keyboard_navigation(self): email_elem = self.driver.find_element(*self.login_page.email_input) email_elem.send_keys('user@test.com') email_elem.send_keys(Keys.TAB) active = self.driver.switch_to.active_element self.assertEqual(active.get_attribute('id'), 'password') active.send_keys('Password123') active.send_keys(Keys.TAB) active = self.driver.switch_to.active_element self.assertEqual(active.get_attribute('id'), 'loginBtn') active.send_keys(Keys.ENTER) # Wait for possible error or success WebDriverWait(self.driver, 5).until( EC.presence_of_element_located(self.login_page.error_message) ) def tearDown(self): self.driver.quit() if __name__ == '__main__': unittest.main()
This script uses Selenium with Python's unittest framework to automate exploratory testing of a login page.
The LoginPage class follows the Page Object Model pattern to keep locators and actions organized.
Each test method covers a different exploratory scenario from the manual test case steps:
Explicit waits ensure the test waits for error messages to appear before asserting.
Assertions check for expected error messages or UI states to confirm correct behavior.
Finally, the browser is closed after tests to clean up.
Now add data-driven testing with 3 different invalid email inputs to verify error messages.
exploratory testing?Pass the test and this pattern moves unknown