Bird
Raised Fist0
Testing Fundamentalstesting~15 mins

Exploratory testing in Testing Fundamentals - Build an Automation Script

Choose your learning style10 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

Practice

(1/5)
1. What is the main goal of exploratory testing?
easy
A. To find bugs by freely exploring the software
B. To write detailed test scripts before testing
C. To automate all test cases
D. To test only the user interface

Solution

  1. Step 1: Understand exploratory testing purpose

    Exploratory testing means testing without fixed scripts, exploring freely to find bugs.
  2. Step 2: Compare options with definition

    Only To find bugs by freely exploring the software matches this idea; others describe scripted or automated testing.
  3. Final Answer:

    To find bugs by freely exploring the software -> Option A
  4. Quick Check:

    Exploratory testing = find bugs freely [OK]
Hint: Exploratory means exploring freely to find bugs [OK]
Common Mistakes:
  • Confusing exploratory with scripted testing
  • Thinking exploratory is only automation
  • Believing it tests only UI
2. Which of the following is a correct practice during exploratory testing?
easy
A. Following a strict test script without deviation
B. Avoiding any note-taking during testing
C. Only testing features that have detailed requirements
D. Using creativity to try different actions in the software

Solution

  1. Step 1: Identify exploratory testing practices

    Exploratory testing encourages creativity and trying different actions freely.
  2. Step 2: Evaluate each option

    Using creativity to try different actions in the software fits this; others restrict testing or avoid useful habits like note-taking.
  3. Final Answer:

    Using creativity to try different actions in the software -> Option D
  4. Quick Check:

    Creativity = exploratory testing [OK]
Hint: Creativity and freedom are key in exploratory testing [OK]
Common Mistakes:
  • Thinking exploratory testing requires strict scripts
  • Ignoring features without detailed requirements
  • Not taking notes during testing
3. During exploratory testing, a tester tries to log in with invalid credentials multiple times. What is the expected outcome?
medium
A. The system crashes immediately
B. The system allows login without error
C. The system blocks login and shows an error message
D. The system logs in with default admin access

Solution

  1. Step 1: Understand login behavior with invalid credentials

    Systems usually block login attempts with wrong credentials and show error messages.
  2. Step 2: Match expected behavior with options

    The system blocks login and shows an error message matches expected behavior; others describe incorrect or unsafe outcomes.
  3. Final Answer:

    The system blocks login and shows an error message -> Option C
  4. Quick Check:

    Invalid login = error message [OK]
Hint: Invalid login should show error, not allow access [OK]
Common Mistakes:
  • Assuming system crashes on invalid login
  • Thinking invalid login grants admin access
  • Believing system ignores invalid attempts
4. A tester performing exploratory testing notices the app crashes when clicking a button, but the crash is not reproducible every time. What should the tester do?
medium
A. Report the crash with detailed steps and environment info
B. Assume the crash is caused by user error and do nothing
C. Ignore it since it is not consistent
D. Restart the app and continue testing without reporting

Solution

  1. Step 1: Understand handling intermittent crashes in exploratory testing

    Even if a crash is not consistent, it should be reported with details to help developers.
  2. Step 2: Evaluate options for best practice

    Report the crash with detailed steps and environment info is correct; ignoring or assuming user error is bad practice.
  3. Final Answer:

    Report the crash with detailed steps and environment info -> Option A
  4. Quick Check:

    Report all crashes with details [OK]
Hint: Always report crashes with details, even if intermittent [OK]
Common Mistakes:
  • Ignoring intermittent bugs
  • Assuming user error without evidence
  • Not providing environment info in reports
5. You are doing exploratory testing on a new app with unclear requirements. Which approach best helps you find important bugs quickly?
hard
A. Randomly click everywhere without any plan
B. Use your knowledge to explore critical areas and take notes
C. Focus only on features with written requirements
D. Wait for developers to provide test cases

Solution

  1. Step 1: Identify best exploratory testing approach with unclear requirements

    Exploratory testing works best by using tester's knowledge to explore important areas thoughtfully.
  2. Step 2: Compare options for effectiveness

    Use your knowledge to explore critical areas and take notes uses knowledge and notes, which is best; random clicking or waiting wastes time.
  3. Final Answer:

    Use your knowledge to explore critical areas and take notes -> Option B
  4. Quick Check:

    Knowledge + notes = effective exploratory testing [OK]
Hint: Explore smartly using knowledge and notes, not random clicks [OK]
Common Mistakes:
  • Testing only documented features
  • Clicking randomly without focus
  • Waiting passively for test cases
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard