Introduction

Part 1, Chapter 1


Writing tests is essential, but writing effective tests is challenging. Many developers struggle with tests that break on every refactor, provide false confidence with high code coverage but low actual value, or become so cumbersome to maintain that they slow down development rather than speed it up.

This course takes a practical, patterns-based approach to testing Python applications. You'll learn proven techniques that make tests resilient to refactoring, easy to write and maintain, and valuable in catching real bugs -- all while working seamlessly with AI coding tools.

What You'll Learn

By the end of this course, you'll be able to:

  1. Test behavior rather than implementation to make tests resistant to refactoring
  2. Use the factory fixtures pattern with pytest to write readable, maintainable tests
  3. Determine whether a test provides real value or just inflates coverage metrics
  4. Apply contract testing to validate I/O operations (databases, APIs, caching, blob storage)
  5. Use mocking effectively without creating brittle tests
  6. Leverage triangulation to solve problems incrementally
  7. Apply pytest parametrization to write tight, comprehensive test suites
  8. Use FastAPI dependency injection overrides to speed up test execution
  9. Implement snapshot testing for seamless API testing
  10. Apply property-based testing for data-heavy and machine learning code
  11. Use the humble object pattern to test hard-to-test code
  12. Structure code to be inherently testable
  13. Configure AI agents to write and maintain high-quality tests

How to Use This Course

This course is structured in two main parts:

  1. The first part covers core general testing techniques and patterns. Each technique includes examples and guidance on when to apply it and how it's relevant for AI-assisted development. It's a foundation for everything that's coming in the second part.
  2. The second part covers use-case specific techniques and how to apply them against real-world examples, like data storage and syncing to thid-party systems. Not every technique will be applicable to every project -- some are more valuable in FastAPI or non-web projects, while others are applicable everywhere. It ends with ready-to-use Claude and Cursor files that will help you steer your agents to write better tests.

The full example project is available in a GitHub repository. You can request access by contacting the email address found in the final chapter.

Tools, Frameworks, and Services

The course uses several development tools. Feel free to swap them for alternatives that better suit your needs.

pytest

pytest is a framework that makes it easy to write Python tests. It provides a simple, readable syntax and powerful features like fixtures, parametrization, and plugins.

Compared to the standard library's unittest, pytest:

  1. Requires less boilerplate code, making test suites more readable
  2. Uses the plain assert statement instead of assertSomething methods
  3. Updates more frequently
  4. Provides a sophisticated fixture system
  5. Has a large ecosystem of plugins

You can replace it with:

  • unittest
  • nose2

Poetry

Poetry is a tool for Python packaging and dependency management. It handles virtual environments, dependency resolution, and package publishing.

You can replace it with:

  • uv
  • pip + twine
  • pipenv + twine

FastAPI

FastAPI is a modern, high-performance web framework for building APIs with Python. It provides automatic API documentation, type checking, and dependency injection out of the box.

You can replace it with:

  • Flask
  • Django
  • Pyramid

Docker

Docker is a container platform used to streamline application development and deployment workflows across various environments. It packages application code, dependencies, and system tools into lightweight containers that can be moved from development to production quickly and easily.




Mark as Completed