Learn Python with Talk Python's 270 hours of courses

pytest tips and tricks for better testing

Episode #407, published Sat, Mar 18, 2023, recorded Mon, Feb 27, 2023

If you're like most people, the simplicity and easy of getting started is a big part of pytest's appeal. But beneath that simplicity, there is a lot of power and depth. We have Brian Okken on this episode to dive into his latest pytest tips and tricks for beginners and power users.

Watch this episode on YouTube
Play on YouTube
Watch the live stream version

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 find pytest 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

  1. 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 with test_, and include a simple assert. This simplicity quickly scales to sophisticated testing without piling on extra boilerplate.
  2. 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.
  3. 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.
  4. 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.
  5. 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 like skip, skipif, and xfail 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)
  6. 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(): ...
  7. 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.
  8. 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.
  9. 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.
  10. 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.

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:

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

pytest tips and tricks article: pythontest.com
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

Talk Python's Mastodon Michael Kennedy's Mastodon