pytest tips and tricks for better testing
Episode Deep Dive
Guests introduction and background
Brian Okken is a seasoned Python developer with a strong background in embedded systems. He hosts the podcast “Test and Code” and is a co-host on “Python Bytes” alongside Michael Kennedy. Brian is well-known in the Python community for his expertise on software testing, especially pytest, and has authored both a popular pytest book as well as created a video course on the topic.
What to Know If You’re New to Python
If you’re fairly new to Python and want to get more out of this conversation, here are a few tips:
- Understand Python’s built-in
assert
statement for writing test conditions (you don’t need a special assertion library). - Know that Python’s standard library includes
unittest
but many findpytest
more convenient and powerful for day-to-day testing. - Learn Python’s basic code organization principles (modules, packages, and imports) as it helps you structure your tests effectively.
- Gaining some familiarity with the command line (or terminal) will help you run
pytest
, collect tests, and interpret output more smoothly.
Key points and takeaways
- Foundational Simplicity of pytest
Pytest is often praised for its easy getting-started experience: just name a file
test_something.py
, write a function starting withtest_
, and include a simpleassert
. This simplicity quickly scales to sophisticated testing without piling on extra boilerplate.- Tools mentioned:
- Multiple Asserts vs. Parameterization
Deciding whether to use one vs. multiple asserts can be nuanced. Sometimes a single test with many asserts is enough, but for clarity and better failure isolation, parameterizing multiple test scenarios often leads to cleaner reporting and more maintainable test suites.
- Links and tools:
- Arranging Tests via Directory Structure
A dedicated
tests/
directory is common. However, how you slice up your tests—by subsystem, by feature, or by behavior—depends on your team’s workflow and the size of your project. A consistent approach makes pinpointing and running specific tests easier.- Tools and resources:
- Fixtures for Reuse and Clarity
Pytest fixtures let you separate setup/teardown logic from your test code. You can store fixtures in a
conftest.py
file and let pytest handle the scoping and lifetime of shared resources (like database connections or test data). Yield-based fixtures also handle cleanup steps automatically.- Mentioned fixtures:
@pytest.fixture
- TempPath / TempPathFactory
- Monkeypatch
- Capsys
- Mentioned fixtures:
- Markers for Targeted Test Runs
You can tag or “mark” tests to categorize them (e.g.,
@pytest.mark.slow
), then run or skip them as needed using pytest’s-m
argument. Built-in markers likeskip
,skipif
, andxfail
help manage cross-platform differences or temporarily broken tests without removing them.- Notable markers:
@pytest.mark.skip
@pytest.mark.skipif
@pytest.mark.xfail(strict=True)
- Notable markers:
- Writing Clear, Descriptive Test Names
Longer, descriptive test function names are good because no external code depends on them. A detailed name acts as in-code documentation, guiding future readers (and future you) when debugging or exploring test failures.
- Example:
def test_returns_200_and_includes_title_for_homepage(): ...
- Example:
- Thinking in Terms of Behavior vs. Unit Tests
Brian emphasized writing tests that validate real user or system behaviors, rather than overly isolating tiny, method-by-method checks. Comprehensive tests often reveal more bugs and can reduce the overhead of writing large numbers of small, narrow tests.
- Links and concepts:
- Behavior-driven testing overview
- “Arrange-Act-Assert” or “Given-When-Then” structuring
- Links and concepts:
- Hypothesis for Advanced Test Generation
While the show focused on builtin pytest features, Hypothesis was mentioned as a powerful way to auto-generate test inputs. It systematically pushes corner cases that you might not even think of, often uncovering hidden bugs.
- Link:
- Don’t Overcomplicate Test Code Strive for readability over “cleverness.” If you find your own test suite too convoluted to debug, it defeats the purpose. Brian recommends gradually introducing advanced features like fixtures or parameterization, so the entire team stays in sync and your tests remain maintainable.
- Leveraging pytest Plugins
pytest’s plugin system (often distributed as Python packages named
pytest-something
) allows you to share fixture code and add advanced capabilities. Whether you’re testing an embedded system or a large-scale web app, you can keep your test logic modular and reusable.
- Popular links:
Interesting quotes and stories
- Brian Okken on Embedded Testing: “All of my love for Python and pytest really came out of my embedded world. It’s not just for testing Python code; you can test C++ or hardware if you can connect to it from Python.”
- On Pairing Clarity with Simplicity: “Don’t design a system so complex that you’re not smart enough to debug it.”
Key definitions and terms
- Fixture: A reusable function that sets up some system state (e.g., a database) before a test and can tear it down afterward using
yield
. - Marker: A pytest concept for tagging or categorizing tests (e.g.,
@pytest.mark.slow
) that can be selectively included or excluded at run time. - Xfail: A mechanism to mark tests as “expected to fail.” Often used when a known bug exists but you don’t want it to break the entire suite continuously.
- Parametrization: The act of running one test function with multiple sets of inputs, automatically generating multiple “sub-tests.”
Learning resources
Here are some resources for going deeper into testing with pytest and Python:
- Getting started with pytest: Brian’s short and focused course on pytest fundamentals, covering fixtures, parametrization, markers, and more.
- Brian’s website, pythontest.com: More articles and updates on pytest tips and testing best practices.
- Hypothesis docs: Official documentation for property-based testing in Python.
- pytest official docs: The main reference for all pytest features and configurations.
Overall takeaway
Pytest offers developers a powerful yet accessible way to write clean, maintainable tests—covering everything from straightforward unit checks to full behavior tests of complex systems. By thoughtfully leveraging fixtures, markers, and parameterization, you can keep your test suite both organized and approachable. As Brian Okken emphasizes, the true power of pytest lies in its simplicity that grows with your needs, enabling you to spend more time understanding your software’s quality and less time wrestling with boilerplate or debugging cryptic test code.
Links from the show
Getting started with pytest Course: training.talkpython.fm
pytest book: pythontest.com
Python Bytes podcast: pythonbytes.fm
Brian on Mastodon: @brianokken@fosstodon.org
Hypothesis: readthedocs.io
Hypothesis: Reproducability: readthedocs.io
Get More Done with the DRY Principle: zapier.com
"The Key" Keyboard: stackoverflow.blog
pytest plugins: docs.pytest.org
Watch this episode on YouTube: youtube.com
Episode transcripts: talkpython.fm
--- Stay in touch with us ---
Subscribe to Talk Python on YouTube: youtube.com
Talk Python on Bluesky: @talkpython.fm at bsky.app
Talk Python on Mastodon: talkpython
Michael on Bluesky: @mkennedy.codes at bsky.app
Michael on Mastodon: mkennedy