0
0
Testing Fundamentalstesting~15 mins

Exploratory testing in Testing Fundamentals - Build an Automation Script

Choose your learning style9 modes available
Explore the login page for unexpected behavior
Preconditions (2)
Step 1: Open the login page URL in the browser
Step 2: Try entering valid email and password and click Login
Step 3: Try entering invalid email format and click Login
Step 4: Try leaving email and password empty and click Login
Step 5: Try entering very long strings in email and password fields
Step 6: Try clicking Login multiple times quickly
Step 7: Try using keyboard only to navigate and submit the form
Step 8: Observe any error messages, page behavior, or crashes
✅ 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.
Automation Requirements - Selenium with Python
Assertions Needed:
Verify error message is shown for invalid email format
Verify error message is shown when fields are empty
Verify login button is disabled or handled when clicked multiple times
Verify page does not crash or freeze after inputs
Verify keyboard navigation works for input fields and login button
Best Practices:
Use explicit waits to wait for elements and messages
Use Page Object Model to organize page interactions
Use assertions to verify expected messages and states
Avoid hardcoded sleeps, use waits instead
Use meaningful locators like IDs or names
Automated Solution
Testing Fundamentals
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:

  • Invalid email format triggers an error message.
  • Empty fields show required field errors.
  • Long input strings do not crash the page.
  • Clicking login multiple times quickly does not freeze or disable the button.
  • Keyboard navigation works correctly through inputs and login button.

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.

Common Mistakes - 5 Pitfalls
Using hardcoded sleep instead of explicit waits
Using brittle XPath locators that break easily
Not clearing input fields before typing
Not verifying error messages or UI feedback
Mixing different test frameworks or APIs in one script
Bonus Challenge

Now add data-driven testing with 3 different invalid email inputs to verify error messages.

Show Hint