Bird
Raised Fist0
Selenium Pythontesting~15 mins

Parameterized tests in Selenium Python - Build an Automation Script

Choose your learning style10 modes available
Verify login functionality with multiple user credentials
Preconditions (5)
Step 1: Open the login page URL.
Step 2: Enter the email address from the test data into the email input field with id 'email'.
Step 3: Enter the password from the test data into the password input field with id 'password'.
Step 4: Click the login button with id 'loginBtn'.
Step 5: Wait for the page to load and verify the URL is 'https://example.com/dashboard'.
Step 6: Log out to return to the login page before the next test iteration.
✅ Expected Result: For each set of credentials, the user is successfully logged in and redirected to the dashboard page.
Automation Requirements - pytest with Selenium WebDriver
Assertions Needed:
Verify the current URL after login matches 'https://example.com/dashboard'.
Best Practices:
Use pytest parameterize decorator to run the test with multiple data sets.
Use explicit waits to wait for page elements or URL changes.
Use Page Object Model to separate page interactions from test logic.
Close the browser after all tests complete.
Automated Solution
Selenium Python
import pytest
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

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')

    def load(self):
        self.driver.get('https://example.com/login')

    def login(self, email, password):
        WebDriverWait(self.driver, 10).until(
            EC.visibility_of_element_located(self.email_input)
        )
        self.driver.find_element(*self.email_input).clear()
        self.driver.find_element(*self.email_input).send_keys(email)
        self.driver.find_element(*self.password_input).clear()
        self.driver.find_element(*self.password_input).send_keys(password)
        self.driver.find_element(*self.login_button).click()

class DashboardPage:
    def __init__(self, driver):
        self.driver = driver

    def is_loaded(self):
        return WebDriverWait(self.driver, 10).until(
            EC.url_to_be('https://example.com/dashboard')
        )

@pytest.fixture(scope='module')
def driver():
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

@pytest.mark.parametrize('email,password', [
    ('user1@example.com', 'Password1!'),
    ('user2@example.com', 'Password2!'),
    ('user3@example.com', 'Password3!')
])
def test_login(driver, email, password):
    login_page = LoginPage(driver)
    dashboard_page = DashboardPage(driver)

    login_page.load()
    login_page.login(email, password)

    assert dashboard_page.is_loaded(), f"Login failed for {email}"

    # Log out to prepare for next test iteration
    driver.get('https://example.com/logout')

This test script uses pytest with Selenium WebDriver to automate login tests with multiple user credentials.

The LoginPage class encapsulates the login page elements and actions, following the Page Object Model pattern for cleaner code.

The DashboardPage class checks if the dashboard page is loaded by waiting for the URL to be the expected dashboard URL.

The driver fixture initializes the Chrome browser once per test module and closes it after all tests finish.

The @pytest.mark.parametrize decorator runs the test_login function three times with different email and password pairs.

Explicit waits ensure the test waits for elements to be visible or URL to change before proceeding, avoiding flaky tests.

After each login test, the script navigates to the logout URL to reset the session for the next test.

Common Mistakes - 4 Pitfalls
{'mistake': 'Hardcoding test data inside the test function instead of using parameterization', 'why_bad': 'This makes tests less flexible and requires code changes to add more test data.', 'correct_approach': "Use pytest's @pytest.mark.parametrize decorator to supply multiple data sets cleanly."}
Using implicit waits or time.sleep() instead of explicit waits
Not closing the browser after tests
Mixing locators or using brittle XPath selectors
Bonus Challenge

Now add data-driven testing with 3 different invalid login inputs and verify error messages appear.

Show Hint

Practice

(1/5)
1. What is the main benefit of using @pytest.mark.parametrize in Selenium Python tests?
easy
A. It allows running the same test with multiple sets of data easily.
B. It speeds up the browser loading time.
C. It automatically finds locators on the page.
D. It generates test reports without extra code.

Solution

  1. Step 1: Understand the purpose of parameterized tests

    Parameterized tests run the same test logic multiple times with different input data sets.
  2. Step 2: Identify what @pytest.mark.parametrize does

    This decorator allows easy setup of multiple data inputs for one test function, reducing repeated code.
  3. Final Answer:

    It allows running the same test with multiple sets of data easily. -> Option A
  4. Quick Check:

    Parameterized tests = multiple data sets [OK]
Hint: Think: same test, many inputs, less code [OK]
Common Mistakes:
  • Confusing parameterization with browser speed optimization
  • Thinking it auto-finds locators
  • Assuming it auto-generates reports
2. Which of the following is the correct syntax to parameterize a test function with two parameters username and password using pytest?
easy
A. @pytest.mark.param('username', 'password', [('user1', 'pass1'), ('user2', 'pass2')])
B. @pytest.parametrize(['username', 'password'], [('user1', 'pass1'), ('user2', 'pass2')])
C. @pytest.mark.parametrize(('username', 'password'), ['user1', 'pass1', 'user2', 'pass2'])
D. @pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')])

Solution

  1. Step 1: Recall pytest parameterize syntax

    The correct syntax uses @pytest.mark.parametrize with a string of comma-separated parameter names and a list of tuples for values.
  2. Step 2: Compare options

    @pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) matches the correct syntax exactly. Others have wrong decorator names or wrong argument formats.
  3. Final Answer:

    @pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) -> Option D
  4. Quick Check:

    Correct decorator and tuple list = @pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) [OK]
Hint: Remember: mark.parametrize with string params and list of tuples [OK]
Common Mistakes:
  • Misspelling 'parametrize' as 'parametrize' or 'param'
  • Using list instead of tuple for parameter values
  • Passing parameters as list instead of string
3. What will be the output when running this parameterized test snippet?
import pytest

@pytest.mark.parametrize('num, expected', [(1, 2), (2, 3), (3, 4)])
def test_increment(num, expected):
    assert num + 1 == expected
medium
A. Syntax error due to wrong decorator usage.
B. All tests fail due to assertion errors.
C. All tests pass successfully.
D. Only the first test passes, others fail.

Solution

  1. Step 1: Analyze the test logic and parameters

    Each tuple provides num and expected. The test asserts num + 1 == expected. For (1,2), 1+1=2; for (2,3), 2+1=3; for (3,4), 3+1=4.
  2. Step 2: Check if assertions hold for all cases

    All assertions are true, so all tests pass.
  3. Final Answer:

    All tests pass successfully. -> Option C
  4. Quick Check:

    num + 1 equals expected for all [OK]
Hint: Check each input-output pair matches assertion [OK]
Common Mistakes:
  • Assuming some tests fail without checking values
  • Confusing parameter order
  • Thinking decorator syntax is wrong
4. Identify the error in this parameterized test code:
import pytest

@pytest.mark.parametrize('input, expected')
def test_double(input, expected):
    assert input * 2 == expected

@pytest.mark.parametrize('input, expected', [(2, 4), (3, 6)])
medium
A. Wrong assertion operator used.
B. Missing data list for parameterize decorator on test_double.
C. Parameters names should be a list, not a string.
D. Test function name is invalid.

Solution

  1. Step 1: Check the decorator usage on test_double

    The decorator @pytest.mark.parametrize('input, expected') is missing the second argument: the list of data tuples.
  2. Step 2: Verify other parts

    Assertion and function name are correct. Parameter names as string is valid syntax.
  3. Final Answer:

    Missing data list for parameterize decorator on test_double. -> Option B
  4. Quick Check:

    Decorator needs data list argument [OK]
Hint: Always provide data list with parametrize decorator [OK]
Common Mistakes:
  • Forgetting the data list argument
  • Using list instead of string for parameter names (which is allowed but less common)
  • Misreading assertion syntax
5. You want to test a login form with multiple username and password pairs using Selenium and pytest parameterization. Which approach correctly combines parameterized tests with Selenium WebDriver to test login functionality?
hard
A. Use @pytest.mark.parametrize to pass username and password, then inside the test open the browser, fill fields, submit, and assert login success.
B. Write separate test functions for each username and password pair without parameterization.
C. Use parameterization only for URLs, not for form inputs like username and password.
D. Use @pytest.mark.parametrize but do not open the browser inside the test function.

Solution

  1. Step 1: Understand parameterized test purpose in Selenium context

    Parameterized tests allow running the same test logic with different input data, such as username and password pairs.
  2. Step 2: Combine parameterization with Selenium actions

    Inside the test function, open the browser, fill the login form with parameters, submit, and check results. This is the correct approach.
  3. Final Answer:

    Use @pytest.mark.parametrize to pass username and password, then inside the test open the browser, fill fields, submit, and assert login success. -> Option A
  4. Quick Check:

    Parameterize inputs + Selenium actions inside test [OK]
Hint: Parameterize inputs, then automate browser steps inside test [OK]
Common Mistakes:
  • Writing separate tests instead of parameterizing
  • Not opening browser inside test function
  • Limiting parameterization to URLs only
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