Parameterize with test data in Selenium Python - Build an Automation Script
import unittest 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') self.logout_button = (By.ID, 'logoutBtn') def open(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)).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() def logout(self): WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable(self.logout_button)).click() class TestLogin(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome() cls.driver.maximize_window() cls.login_page = LoginPage(cls.driver) @classmethod def tearDownClass(cls): cls.driver.quit() def setUp(self): self.login_page.open() def test_login_with_multiple_credentials(self): test_data = [ ('user1@example.com', 'Password1!'), ('user2@example.com', 'Password2!'), ('user3@example.com', 'Password3!') ] for email, password in test_data: with self.subTest(email=email): self.login_page.login(email, password) WebDriverWait(self.driver, 10).until(EC.url_to_be('https://example.com/dashboard')) current_url = self.driver.current_url self.assertEqual(current_url, 'https://example.com/dashboard', f'Login failed for {email}') self.login_page.logout() if __name__ == '__main__': unittest.main()
This script uses the Selenium WebDriver with Python's unittest framework to automate login tests with multiple user credentials.
LoginPage class: Encapsulates the login page elements and actions. This follows the Page Object Model to keep code organized.
TestLogin class: Contains the test case. It opens the login page before each test and closes the browser after all tests.
Parameterization: The test_login_with_multiple_credentials method loops over a list of email/password pairs. Each pair is tested separately using subTest for clear reporting.
Assertions: After login, the test waits explicitly for the URL to change to the dashboard URL and asserts it matches exactly.
Cleanup: After each login, the test logs out to reset the state for the next iteration.
This approach ensures the test is maintainable, clear, and reliable.
Now add data-driven testing with 3 different inputs using unittest's parameterized library or pytest parametrize.
Practice
@pytest.mark.parametrize in Selenium Python tests?Solution
Step 1: Understand the decorator's role
@pytest.mark.parametrizeallows running one test function multiple times with different sets of input data.Step 2: Compare with other options
Skipping tests, running in parallel, or generating reports are different pytest features, not related to parameterization.Final Answer:
To run the same test function multiple times with different input data -> Option CQuick Check:
Parameterize = run test with many inputs [OK]
- Confusing parameterize with skipping tests
- Thinking it runs tests in parallel
- Assuming it generates reports
("user1", "pass1") and ("user2", "pass2") in pytest?Solution
Step 1: Recall correct decorator syntax
The correct syntax uses@pytest.mark.parametrizewith a string of parameter names and a list of tuples for values.Step 2: Identify correct option
@pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) matches the correct syntax exactly. Other options have wrong method names or argument formats.Final Answer:
@pytest.mark.parametrize('username, password', [('user1', 'pass1'), ('user2', 'pass2')]) -> Option BQuick Check:
Parametrize('params', [tuples]) = correct syntax [OK]
- Misspelling 'parametrize' as 'parametrized' or 'parametrize'
- Passing parameters as separate lists instead of tuples
- Using wrong decorator name
import pytest
@pytest.mark.parametrize('num, expected', [(1, 2), (3, 4)])
def test_increment(num, expected):
assert num + 1 == expectedSolution
Step 1: Analyze each test case
For (1, 2): 1 + 1 = 2, assertion passes. For (3, 4): 3 + 1 = 4, assertion passes.Step 2: Determine overall result
Since both assertions pass, both tests pass successfully.Final Answer:
Both tests pass -> Option DQuick Check:
num+1 == expected for all inputs [OK]
- Assuming one test fails without checking values
- Confusing expected values with actual calculation
- Ignoring that both inputs are tested
import pytest
@pytest.mark.parametrize('username, password')
def test_login(username, password):
assert username != '' and password != ''Solution
Step 1: Check decorator usage
The decorator@pytest.mark.parametrizerequires two arguments: parameter names and a list of values. Here, the list of values is missing.Step 2: Verify other parts
Function parameters match decorator names, assertion logic is valid, and pytest is imported correctly.Final Answer:
Missing list of parameter values in @pytest.mark.parametrize decorator -> Option AQuick Check:
Parametrize needs names and values [OK]
- Forgetting the list of test data tuples
- Mismatching parameter names and function arguments
- Incorrect assertion logic
Solution
Step 1: Understand parameterization with Selenium
Parameterization with@pytest.mark.parametrizeallows running the test multiple times with different data, opening the browser fresh each time ensures test isolation.Step 2: Evaluate other options
Writing separate tests duplicates code, looping inside one test loses pytest reporting benefits, and opening browser only once risks test interference.Final Answer:
Use @pytest.mark.parametrize to pass username and password, then inside the test open the browser, enter credentials, and assert login success -> Option AQuick Check:
Parametrize + fresh browser per test = best practice [OK]
- Opening browser once for all tests causing state issues
- Not using parameterize and duplicating test code
- Using loops inside tests instead of parameterize
Ready to prove it?
Pass the test and this pattern moves unknown
