Module 8 · Python for SDETs
Data-driven
tests
One test body, many cases — from a table, a JSON file, or a CSV
parametrize
JSON & CSV
readable ids
data ≠ logic
Separate the cases from the code
One test body, a table of cases
a list of cases
→
@parametrize over it
→
N independent, labeled tests
🧩Add a row, get a test — the body never changes. Each case runs (and fails) independently, so one bad input doesn't hide the rest.
Data from a JSON file
tests/data/login_cases.json
[
"password": "customer123", "expected": 200 },
"password": "x", "expected": 401 }
]
CASES = json.loads(
(Path(__file__).parent / "data"
/ "login_cases.json").read_text()
)
@pytest.mark.parametrize("case", CASES)
def test_login(case): …
📂Load at module level — parametrize runs at import, so the data must exist by then. (JSON file = no // comments.)
CSV: every value is a string
# tests/data/categories.csv
category,present
electronics,true
nonexistent,false
rows = csv.DictReader(f)
present = row["present"] == "true"
🔤csv.DictReader yields one dict per row, but every value is a string — so "false" is truthy!
🔁Convert types yourself: compare == "true", or wrap in int(...) — the reader won't do it for you.
Give each case a readable name
No ids — opaque
test_login[case0]
test_login[case1]
test_login[case2]
ids from the data
ids=[f"{c['email']}->{c['expected']}"
for c in CASES]
🧮
Cases as
data
One body, many rows — from JSON or CSV, each named so failures point at the case
🧪
Practice
A login matrix from JSON: valid→200, wrong→401, empty→400
🔤
CSV types
Read categories.csv and remember to convert the strings
➡️
Module 9
Reporting & suite structure — HTML reports, markers, folders