SlideShare a Scribd company logo
Multiply your Testing E ectiveness with
Parameterized Testing
Brian Okken
@brianokken
Code and markdown for slides
github.com/okken/presentation_parametrization
Slides on slideshare slideshare.net/testandcode
1 / 25
Work
Podcasts
Book
Brian Okken
2 / 25
Outline
Value of Tests
Parametrize vs Parameterize
Examples:
without Parametrization
Function Parametrization
Fixture Parametrization
pytest_generate_tests()
Choosing a Technique
Combining Techniques
Resources
3 / 25
Value of Tests
Automated tests give us confidence. What does confidence look like?
4 / 25
Value of Tests
Automated tests give us confidence. What does confidence look like?
A passing test suite means:
I didn't break anything that used to work.
Future changes won’t break current features.
The code is ready for users.
I can refactor until I'm proud of the code.
Code reviews can focus on team understanding and ownership.
Only works if:
New features are tested with new tests.
Tests are easy and fast to write.
5 / 25
Parametrize vs Parameterize
parameter + ize
parameterize (US)
parametrize (UK)
pytest uses parametrize, the UK spelling.
I've tried to get them to change it.
They don't want to.
I've gotten over it.
6 / 25
Something to Test
triangles.py:
def triangle_type(a, b, c):
"""
Given three angles,
return 'obtuse', 'acute', 'right', or 'invalid'.
"""
angles = (a, b, c)
if (sum(angles) == 180 and
all([0 < a < 180 for a in angles])):
if any([a > 90 for a in angles]):
return "obtuse"
if all([a < 90 for a in angles]):
return "acute"
if 90 in angles:
return "right"
return "invalid"
Obtuse , Acute , Right
7 / 25
without Parametrization
test_1_without_param.py:
from triangle import triangle_type
def test_obtuse():
assert triangle_type(100, 40, 40) == "obtuse"
def test_acute():
assert triangle_type(60, 60, 60) == "acute"
def test_right():
assert triangle_type(90, 60, 30) == "right"
def test_invalid():
assert triangle_type(0, 0, 0) == "invalid"
Obtuse , Acute , Right
8 / 25
Function Parametrization
test_2_func_param.py:
import pytest
from triangle import triangle_type
many_triangles = [
(100, 40, 40, "obtuse"),
( 60, 60, 60, "acute"),
( 90, 60, 30, "right"),
( 0, 0, 0, "invalid"),
]
@pytest.mark.parametrize('a, b, c, expected', many_triangles)
def test_type(a, b, c, expected):
assert triangle_type(a, b, c) == expected
9 / 25
output without
(venv) $ pytest -v test_1_without_param.py
===================== test session starts ======================
collected 4 items
test_1_without_param.py::test_obtuse PASSED [ 25%]
test_1_without_param.py::test_acute PASSED [ 50%]
test_1_without_param.py::test_right PASSED [ 75%]
test_1_without_param.py::test_invalid PASSED [100%]
====================== 4 passed in 0.02s =======================
10 / 25
output with
(venv) $ pytest -v test_2_func_param.py
===================== test session starts ======================
collected 4 items
test_2_func_param.py::test_type[100-40-40-obtuse] PASSED [ 25%]
test_2_func_param.py::test_type[60-60-60-acute] PASSED [ 50%]
test_2_func_param.py::test_type[90-60-30-right] PASSED [ 75%]
test_2_func_param.py::test_type[0-0-0-invalid] PASSED [100%]
====================== 4 passed in 0.02s =======================
11 / 25
You can still run just one
(venv) $ pytest -v 'test_2_func_param.py::test_type[0-0-0-invalid]'
===================== test session starts ======================
collected 1 item
test_2_func_param.py::test_type[0-0-0-invalid] PASSED [100%]
====================== 1 passed in 0.02s =======================
This uses the node id.
12 / 25
or more
(venv) $ pytest -v -k 60 test_2_func_param.py
===================== test session starts ======================
collected 4 items / 2 deselected / 2 selected
test_2_func_param.py::test_type[60-60-60-acute] PASSED [ 50%]
test_2_func_param.py::test_type[90-60-30-right] PASSED [100%]
=============== 2 passed, 2 deselected in 0.02s ================
An example with -k to pick all tests with 60 degree angles.
13 / 25
Once again, this is Function Parametrization
test_2_func_param.py:
import pytest
from triangle import triangle_type
many_triangles = [
(100, 40, 40, "obtuse"),
( 60, 60, 60, "acute"),
( 90, 60, 30, "right"),
( 0, 0, 0, "invalid"),
]
@pytest.mark.parametrize('a, b, c, expected', many_triangles)
def test_type(a, b, c, expected):
assert triangle_type(a, b, c) == expected
14 / 25
Fixture Parametrization
test_3_fixture_param.py:
import pytest
from triangle import triangle_type
many_triangles = [
(100, 40, 40, "obtuse"),
( 60, 60, 60, "acute"),
( 90, 60, 30, "right"),
( 0, 0, 0, "invalid"),
]
@pytest.fixture(params=many_triangles)
def a_triangle(request):
return request.param
def test_type(a_triangle):
a, b, c, expected = a_triangle
assert triangle_type(a, b, c) == expected
15 / 25
output
(venv) $ pytest -v test_3_fixture_param.py
======================= test session starts =======================
collected 4 items
test_3_fixture_param.py::test_type[a_triangle0] PASSED [ 25%]
test_3_fixture_param.py::test_type[a_triangle1] PASSED [ 50%]
test_3_fixture_param.py::test_type[a_triangle2] PASSED [ 75%]
test_3_fixture_param.py::test_type[a_triangle3] PASSED [100%]
======================== 4 passed in 0.02s ========================
16 / 25
adding an id function
test_4_fixture_param.py:
import pytest
from triangle import triangle_type
many_triangles = [
(100, 40, 40, "obtuse"),
( 60, 60, 60, "acute"),
( 90, 60, 30, "right"),
( 0, 0, 0, "invalid"),
]
def idfn(a_triangle):
a, b, c, expected = a_triangle
return f'{a}_{b}_{c}_{expected}'
@pytest.fixture(params=many_triangles, ids=idfn)
def a_triangle(request):
return request.param
def test_type(a_triangle):
a, b, c, expected = a_triangle
assert triangle_type(a, b, c) == expected
17 / 25
output
(venv) $ pytest -v test_4_fixture_param.py
======================= test session starts =======================
collected 4 items
test_4_fixture_param.py::test_type[100_40_40_obtuse] PASSED [ 25%]
test_4_fixture_param.py::test_type[60_60_60_acute] PASSED [ 50%]
test_4_fixture_param.py::test_type[90_60_30_right] PASSED [ 75%]
test_4_fixture_param.py::test_type[0_0_0_invalid] PASSED [100%]
======================== 4 passed in 0.02s ========================
18 / 25
pytest_generate_tests()
test_5_gen.py:
from triangle import triangle_type
many_triangles = [
(100, 40, 40, "obtuse"),
( 60, 60, 60, "acute"),
( 90, 60, 30, "right"),
( 0, 0, 0, "invalid"),
]
def idfn(a_triangle):
a, b, c, expected = a_triangle
return f'{a}_{b}_{c}_{expected}'
def pytest_generate_tests(metafunc):
if "a_triangle" in metafunc.fixturenames:
metafunc.parametrize("a_triangle",
many_triangles,
ids=idfn)
def test_type(a_triangle):
a, b, c, expected = a_triangle
assert triangle_type(a, b, c) == expected
19 / 25
output
(venv) $ pytest -v test_5_gen.py
=================== test session starts ====================
platform darwin -- Python 3.7.3, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- /Users/o
cachedir: .pytest_cache
rootdir: /Users/okken/projects/presentation_parametrization/code
collected 4 items
test_5_gen.py::test_type[100_40_40_obtuse] PASSED [ 25%]
test_5_gen.py::test_type[60_60_60_acute] PASSED [ 50%]
test_5_gen.py::test_type[90_60_30_right] PASSED [ 75%]
test_5_gen.py::test_type[0_0_0_invalid] PASSED [100%]
==================== 4 passed in 0.03s =====================
20 / 25
Choosing a Technique
Guidelines
1. function parametrization
use this if you can
2. fixture parametrization
if doing work to set up each fixture value
if cycling through pre-conditions
if running multiple test against the same set of "setup states"
3. pytest_generate_tests()
if you need to build up the list at runtime
if list is based on passed in parameters or external resources
for sparse matrix sets
21 / 25
more test cases
test_6_more.py:
...
triangles = [
( 1, 1, 178, "obtuse"), # big angles
( 91, 44, 45, "obtuse"), # just over 90
(0.01, 0.01, 179.98, "obtuse"), # decimals
(90, 60, 30, "right"), # check 90 for each angle
(10, 90, 80, "right"),
(85, 5, 90, "right"),
(89, 89, 2, "acute"), # just under 90
(60, 60, 60, "acute"),
(0, 0, 0, "invalid"), # zeros
(61, 60, 60, "invalid"), # sum > 180
(90, 91, -1, "invalid"), # negative numbers
]
@pytest.mark.parametrize('a, b, c, expected', triangles)
def test_type(a, b, c, expected):
assert triangle_type(a, b, c) == expected
22 / 25
Combining Techniques
You can have multiple parametrizations for a test function.
can have multiple @pytest.mark.parametrize() decorators on a test
function.
can parameterize multipe fixtures per test
can use pytest_generate_tests() to parametrize multiple parameters
can use a combination of techniques
can blow up into lots and lots of test cases very fast
23 / 25
Not covered, intentionally
Use with caution.
indirect
Have a list of parameters defined at the test function that gets passed
to a fixture.
Kind of a hybrid between function and fixture parametrization.
subtests
Sort of related, but not really.
You can check multiple things within a test.
If you care about test case counts, pass, fail, etc, then don't use
subtests.
24 / 25
Python Testing with pytest
The fastest way to get super productive
with pytest
pytest docs on
parametrization, in general
function parametrization
fixture parametrization
pytest_generate_tests
podcasts
Test & Code
Python Bytes
Talk Python
slack community: Test & Code Slack
Twitter: @brianokken, @testandcode
This code, and markdown for slides, on github
Presentation is at slideshare.net/testandcode
Resources
25 / 25

More Related Content

ODP
From typing the test to testing the type
PDF
pytest로 파이썬 코드 테스트하기
PDF
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
PDF
Software Testing Metrics
KEY
Testing My Patience
KEY
Django’s nasal passage
PPTX
Clean tests good tests
ODP
Testing in Laravel
From typing the test to testing the type
pytest로 파이썬 코드 테스트하기
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Software Testing Metrics
Testing My Patience
Django’s nasal passage
Clean tests good tests
Testing in Laravel

What's hot (12)

KEY
PHPUnit testing to Zend_Test
PDF
Beginning PHPUnit
PPTX
Unit Testing Presentation
PDF
Python testing using mock and pytest
PDF
Building Testable PHP Applications
PPTX
Test in action week 2
PDF
Unit testing PHP apps with PHPUnit
PDF
Pytest: escreva menos, teste mais
PDF
4. Метапрограмиране
PPTX
javascript function & closure
PDF
Testing Code and Assuring Quality
PDF
What NOT to test in your project
PHPUnit testing to Zend_Test
Beginning PHPUnit
Unit Testing Presentation
Python testing using mock and pytest
Building Testable PHP Applications
Test in action week 2
Unit testing PHP apps with PHPUnit
Pytest: escreva menos, teste mais
4. Метапрограмиране
javascript function & closure
Testing Code and Assuring Quality
What NOT to test in your project
Ad

Similar to Parametrized testing, v2 (20)

PDF
PyCon Siberia 2016. Не доверяйте тестам!
PPTX
wk5ppt2_Iris
PDF
Introduction to testing
PPTX
Testers guide to unit testing
PDF
Practical Generative Testing Patterns
PPTX
Pro Java Fx – Developing Enterprise Applications
PDF
How to fake_properly
PDF
Testing in those hard to reach places
 
PDF
Implementing and analyzing online experiments
PDF
How to write clean tests
PPTX
Test in action week 4
PDF
Next Level Testing
PDF
MT_01_unittest_python.pdf
KEY
How To Test Everything
PDF
Auto testing!
PPTX
Nalinee java
PDF
CMIS 102 HANDS-ON LAB WEEK 6 OVERVIEW THIS HANDS-ON LAB ALLOWS YOU TO FOLLOW ...
PDF
Token Testing Slides
PPTX
C programming
PDF
Developer Joy - How great teams get s%*t done
PyCon Siberia 2016. Не доверяйте тестам!
wk5ppt2_Iris
Introduction to testing
Testers guide to unit testing
Practical Generative Testing Patterns
Pro Java Fx – Developing Enterprise Applications
How to fake_properly
Testing in those hard to reach places
 
Implementing and analyzing online experiments
How to write clean tests
Test in action week 4
Next Level Testing
MT_01_unittest_python.pdf
How To Test Everything
Auto testing!
Nalinee java
CMIS 102 HANDS-ON LAB WEEK 6 OVERVIEW THIS HANDS-ON LAB ALLOWS YOU TO FOLLOW ...
Token Testing Slides
C programming
Developer Joy - How great teams get s%*t done
Ad

Recently uploaded (20)

PDF
iTop VPN Crack Latest Version Full Key 2025
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
Nekopoi APK 2025 free lastest update
PDF
Cost to Outsource Software Development in 2025
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Complete Guide to Website Development in Malaysia for SMEs
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
PPTX
history of c programming in notes for students .pptx
PDF
Download FL Studio Crack Latest version 2025 ?
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
iTop VPN Crack Latest Version Full Key 2025
wealthsignaloriginal-com-DS-text-... (1).pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
Nekopoi APK 2025 free lastest update
Cost to Outsource Software Development in 2025
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Complete Guide to Website Development in Malaysia for SMEs
Navsoft: AI-Powered Business Solutions & Custom Software Development
Computer Software and OS of computer science of grade 11.pptx
CHAPTER 2 - PM Management and IT Context
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
history of c programming in notes for students .pptx
Download FL Studio Crack Latest version 2025 ?
Reimagine Home Health with the Power of Agentic AI​
Design an Analysis of Algorithms II-SECS-1021-03
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Salesforce Agentforce AI Implementation.pdf
Operating system designcfffgfgggggggvggggggggg

Parametrized testing, v2

  • 1. Multiply your Testing E ectiveness with Parameterized Testing Brian Okken @brianokken Code and markdown for slides github.com/okken/presentation_parametrization Slides on slideshare slideshare.net/testandcode 1 / 25
  • 3. Outline Value of Tests Parametrize vs Parameterize Examples: without Parametrization Function Parametrization Fixture Parametrization pytest_generate_tests() Choosing a Technique Combining Techniques Resources 3 / 25
  • 4. Value of Tests Automated tests give us confidence. What does confidence look like? 4 / 25
  • 5. Value of Tests Automated tests give us confidence. What does confidence look like? A passing test suite means: I didn't break anything that used to work. Future changes won’t break current features. The code is ready for users. I can refactor until I'm proud of the code. Code reviews can focus on team understanding and ownership. Only works if: New features are tested with new tests. Tests are easy and fast to write. 5 / 25
  • 6. Parametrize vs Parameterize parameter + ize parameterize (US) parametrize (UK) pytest uses parametrize, the UK spelling. I've tried to get them to change it. They don't want to. I've gotten over it. 6 / 25
  • 7. Something to Test triangles.py: def triangle_type(a, b, c): """ Given three angles, return 'obtuse', 'acute', 'right', or 'invalid'. """ angles = (a, b, c) if (sum(angles) == 180 and all([0 < a < 180 for a in angles])): if any([a > 90 for a in angles]): return "obtuse" if all([a < 90 for a in angles]): return "acute" if 90 in angles: return "right" return "invalid" Obtuse , Acute , Right 7 / 25
  • 8. without Parametrization test_1_without_param.py: from triangle import triangle_type def test_obtuse(): assert triangle_type(100, 40, 40) == "obtuse" def test_acute(): assert triangle_type(60, 60, 60) == "acute" def test_right(): assert triangle_type(90, 60, 30) == "right" def test_invalid(): assert triangle_type(0, 0, 0) == "invalid" Obtuse , Acute , Right 8 / 25
  • 9. Function Parametrization test_2_func_param.py: import pytest from triangle import triangle_type many_triangles = [ (100, 40, 40, "obtuse"), ( 60, 60, 60, "acute"), ( 90, 60, 30, "right"), ( 0, 0, 0, "invalid"), ] @pytest.mark.parametrize('a, b, c, expected', many_triangles) def test_type(a, b, c, expected): assert triangle_type(a, b, c) == expected 9 / 25
  • 10. output without (venv) $ pytest -v test_1_without_param.py ===================== test session starts ====================== collected 4 items test_1_without_param.py::test_obtuse PASSED [ 25%] test_1_without_param.py::test_acute PASSED [ 50%] test_1_without_param.py::test_right PASSED [ 75%] test_1_without_param.py::test_invalid PASSED [100%] ====================== 4 passed in 0.02s ======================= 10 / 25
  • 11. output with (venv) $ pytest -v test_2_func_param.py ===================== test session starts ====================== collected 4 items test_2_func_param.py::test_type[100-40-40-obtuse] PASSED [ 25%] test_2_func_param.py::test_type[60-60-60-acute] PASSED [ 50%] test_2_func_param.py::test_type[90-60-30-right] PASSED [ 75%] test_2_func_param.py::test_type[0-0-0-invalid] PASSED [100%] ====================== 4 passed in 0.02s ======================= 11 / 25
  • 12. You can still run just one (venv) $ pytest -v 'test_2_func_param.py::test_type[0-0-0-invalid]' ===================== test session starts ====================== collected 1 item test_2_func_param.py::test_type[0-0-0-invalid] PASSED [100%] ====================== 1 passed in 0.02s ======================= This uses the node id. 12 / 25
  • 13. or more (venv) $ pytest -v -k 60 test_2_func_param.py ===================== test session starts ====================== collected 4 items / 2 deselected / 2 selected test_2_func_param.py::test_type[60-60-60-acute] PASSED [ 50%] test_2_func_param.py::test_type[90-60-30-right] PASSED [100%] =============== 2 passed, 2 deselected in 0.02s ================ An example with -k to pick all tests with 60 degree angles. 13 / 25
  • 14. Once again, this is Function Parametrization test_2_func_param.py: import pytest from triangle import triangle_type many_triangles = [ (100, 40, 40, "obtuse"), ( 60, 60, 60, "acute"), ( 90, 60, 30, "right"), ( 0, 0, 0, "invalid"), ] @pytest.mark.parametrize('a, b, c, expected', many_triangles) def test_type(a, b, c, expected): assert triangle_type(a, b, c) == expected 14 / 25
  • 15. Fixture Parametrization test_3_fixture_param.py: import pytest from triangle import triangle_type many_triangles = [ (100, 40, 40, "obtuse"), ( 60, 60, 60, "acute"), ( 90, 60, 30, "right"), ( 0, 0, 0, "invalid"), ] @pytest.fixture(params=many_triangles) def a_triangle(request): return request.param def test_type(a_triangle): a, b, c, expected = a_triangle assert triangle_type(a, b, c) == expected 15 / 25
  • 16. output (venv) $ pytest -v test_3_fixture_param.py ======================= test session starts ======================= collected 4 items test_3_fixture_param.py::test_type[a_triangle0] PASSED [ 25%] test_3_fixture_param.py::test_type[a_triangle1] PASSED [ 50%] test_3_fixture_param.py::test_type[a_triangle2] PASSED [ 75%] test_3_fixture_param.py::test_type[a_triangle3] PASSED [100%] ======================== 4 passed in 0.02s ======================== 16 / 25
  • 17. adding an id function test_4_fixture_param.py: import pytest from triangle import triangle_type many_triangles = [ (100, 40, 40, "obtuse"), ( 60, 60, 60, "acute"), ( 90, 60, 30, "right"), ( 0, 0, 0, "invalid"), ] def idfn(a_triangle): a, b, c, expected = a_triangle return f'{a}_{b}_{c}_{expected}' @pytest.fixture(params=many_triangles, ids=idfn) def a_triangle(request): return request.param def test_type(a_triangle): a, b, c, expected = a_triangle assert triangle_type(a, b, c) == expected 17 / 25
  • 18. output (venv) $ pytest -v test_4_fixture_param.py ======================= test session starts ======================= collected 4 items test_4_fixture_param.py::test_type[100_40_40_obtuse] PASSED [ 25%] test_4_fixture_param.py::test_type[60_60_60_acute] PASSED [ 50%] test_4_fixture_param.py::test_type[90_60_30_right] PASSED [ 75%] test_4_fixture_param.py::test_type[0_0_0_invalid] PASSED [100%] ======================== 4 passed in 0.02s ======================== 18 / 25
  • 19. pytest_generate_tests() test_5_gen.py: from triangle import triangle_type many_triangles = [ (100, 40, 40, "obtuse"), ( 60, 60, 60, "acute"), ( 90, 60, 30, "right"), ( 0, 0, 0, "invalid"), ] def idfn(a_triangle): a, b, c, expected = a_triangle return f'{a}_{b}_{c}_{expected}' def pytest_generate_tests(metafunc): if "a_triangle" in metafunc.fixturenames: metafunc.parametrize("a_triangle", many_triangles, ids=idfn) def test_type(a_triangle): a, b, c, expected = a_triangle assert triangle_type(a, b, c) == expected 19 / 25
  • 20. output (venv) $ pytest -v test_5_gen.py =================== test session starts ==================== platform darwin -- Python 3.7.3, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- /Users/o cachedir: .pytest_cache rootdir: /Users/okken/projects/presentation_parametrization/code collected 4 items test_5_gen.py::test_type[100_40_40_obtuse] PASSED [ 25%] test_5_gen.py::test_type[60_60_60_acute] PASSED [ 50%] test_5_gen.py::test_type[90_60_30_right] PASSED [ 75%] test_5_gen.py::test_type[0_0_0_invalid] PASSED [100%] ==================== 4 passed in 0.03s ===================== 20 / 25
  • 21. Choosing a Technique Guidelines 1. function parametrization use this if you can 2. fixture parametrization if doing work to set up each fixture value if cycling through pre-conditions if running multiple test against the same set of "setup states" 3. pytest_generate_tests() if you need to build up the list at runtime if list is based on passed in parameters or external resources for sparse matrix sets 21 / 25
  • 22. more test cases test_6_more.py: ... triangles = [ ( 1, 1, 178, "obtuse"), # big angles ( 91, 44, 45, "obtuse"), # just over 90 (0.01, 0.01, 179.98, "obtuse"), # decimals (90, 60, 30, "right"), # check 90 for each angle (10, 90, 80, "right"), (85, 5, 90, "right"), (89, 89, 2, "acute"), # just under 90 (60, 60, 60, "acute"), (0, 0, 0, "invalid"), # zeros (61, 60, 60, "invalid"), # sum > 180 (90, 91, -1, "invalid"), # negative numbers ] @pytest.mark.parametrize('a, b, c, expected', triangles) def test_type(a, b, c, expected): assert triangle_type(a, b, c) == expected 22 / 25
  • 23. Combining Techniques You can have multiple parametrizations for a test function. can have multiple @pytest.mark.parametrize() decorators on a test function. can parameterize multipe fixtures per test can use pytest_generate_tests() to parametrize multiple parameters can use a combination of techniques can blow up into lots and lots of test cases very fast 23 / 25
  • 24. Not covered, intentionally Use with caution. indirect Have a list of parameters defined at the test function that gets passed to a fixture. Kind of a hybrid between function and fixture parametrization. subtests Sort of related, but not really. You can check multiple things within a test. If you care about test case counts, pass, fail, etc, then don't use subtests. 24 / 25
  • 25. Python Testing with pytest The fastest way to get super productive with pytest pytest docs on parametrization, in general function parametrization fixture parametrization pytest_generate_tests podcasts Test & Code Python Bytes Talk Python slack community: Test & Code Slack Twitter: @brianokken, @testandcode This code, and markdown for slides, on github Presentation is at slideshare.net/testandcode Resources 25 / 25