Parametrization in Pytest
Use the same code over and over
Parametrization in Pytest allows you to run the same test function multiple times with different inputs. Instead of writing separate test functions for each set of data, you can define a single test and provide various argument sets using the @pytest.mark.parametrize decorator. This approach is especially useful for testing functions that need to handle a variety of inputs, edge cases, or data types.
Why Use Parametrization?
- Code Reusability: Write one test function and reuse it for multiple test cases.
- Efficiency: Reduce boilerplate code and make your test suite easier to maintain.
- Clarity: Clearly define the inputs and expected outputs for each test case.
- Comprehensive Testing: Easily test a wide range of scenarios without extra effort.
Code Example
This code will check to see if various internal sites are up and running. I ran similar code in the past. This was done so that I could see if there are any issues before the morning standup.
If I didn't use parametrization here, there would be multiple test cases which could cause overhead issues if changes needed to be done.
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.common.exceptions import WebDriverException
# List of websites to test
WEBSITES = [
"https://www.company.com",
"https://qa1.company.com",
"https://qa2.company.com",
"https://stage.company.com"
]
@pytest.fixture
def chrome_driver():
"""Fixture to set up and tear down Chrome WebDriver"""
# Set up Chrome options
chrome_options = Options()
chrome_options.add_argument("--headless") # Run in headless mode
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
# Initialize driver
driver = webdriver.Chrome(options=chrome_options)
driver.set_page_load_timeout(30) # Set timeout to 30 seconds
yield driver
# Teardown
driver.quit()
@pytest.mark.parametrize("website", WEBSITES)
def test_website_is_up(chrome_driver, website):
"""
Test if a website loads successfully by checking:
1. Page loads without timeout
2. HTTP status is 200 (implicitly checked via successful load)
3. Page title is not empty
"""
try:
# Attempt to load the website
chrome_driver.get(website)
# Check if page title exists and is not empty
title = chrome_driver.title
assert title, f"Website {website} loaded but has no title"
# Optional: Check if body element exists
body = chrome_driver.find_element(By.TAG_NAME, "body")
assert body is not None, f"Website {website} has no body content"
print(f"? {website} is up and running (Title: {title})")
except WebDriverException as e:
pytest.fail(f"Website {website} failed to load: {str(e)}")
except AssertionError as e:
pytest.fail(f"Website {website} loaded but content check failed: {str(e)}")
if __name__ == "__main__":
pytest.main(["-v"])