Parameterized tests in Selenium Python - Build an Automation Script
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.
Now add data-driven testing with 3 different invalid login inputs and verify error messages appear.
Practice
@pytest.mark.parametrize in Selenium Python tests?Solution
Step 1: Understand the purpose of parameterized tests
Parameterized tests run the same test logic multiple times with different input data sets.Step 2: Identify what
This decorator allows easy setup of multiple data inputs for one test function, reducing repeated code.@pytest.mark.parametrizedoesFinal Answer:
It allows running the same test with multiple sets of data easily. -> Option AQuick Check:
Parameterized tests = multiple data sets [OK]
- Confusing parameterization with browser speed optimization
- Thinking it auto-finds locators
- Assuming it auto-generates reports
username and password using pytest?Solution
Step 1: Recall pytest parameterize syntax
The correct syntax uses@pytest.mark.parametrizewith a string of comma-separated parameter names and a list of tuples for values.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.Final Answer:
@pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) -> Option DQuick Check:
Correct decorator and tuple list = @pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) [OK]
- Misspelling 'parametrize' as 'parametrize' or 'param'
- Using list instead of tuple for parameter values
- Passing parameters as list instead of string
import pytest
@pytest.mark.parametrize('num, expected', [(1, 2), (2, 3), (3, 4)])
def test_increment(num, expected):
assert num + 1 == expectedSolution
Step 1: Analyze the test logic and parameters
Each tuple providesnumandexpected. The test assertsnum + 1 == expected. For (1,2), 1+1=2; for (2,3), 2+1=3; for (3,4), 3+1=4.Step 2: Check if assertions hold for all cases
All assertions are true, so all tests pass.Final Answer:
All tests pass successfully. -> Option CQuick Check:
num + 1 equals expected for all [OK]
- Assuming some tests fail without checking values
- Confusing parameter order
- Thinking decorator syntax is wrong
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)])Solution
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.Step 2: Verify other parts
Assertion and function name are correct. Parameter names as string is valid syntax.Final Answer:
Missing data list for parameterize decorator on test_double. -> Option BQuick Check:
Decorator needs data list argument [OK]
- Forgetting the data list argument
- Using list instead of string for parameter names (which is allowed but less common)
- Misreading assertion syntax
Solution
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.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.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 AQuick Check:
Parameterize inputs + Selenium actions inside test [OK]
- Writing separate tests instead of parameterizing
- Not opening browser inside test function
- Limiting parameterization to URLs only
Ready to prove it?
Pass the test and this pattern moves unknown
