Django TDD Patterns: A Visual Field Guide
- Track:
- Testing, Quality Assurance, Security
- Type:
- Poster
- Level:
- intermediate
- Duration:
- 60 minutes
Abstract
Most Django testing tutorials stop at "write a test, make it pass, refactor." But real-world Django applications have complex model relationships, permission systems, third-party API integrations, and asynchronous task chains that demand more sophisticated testing strategies. After delivering a hands-on TDD workshop at DjangoCon US 2023 and applying these patterns across multiple production Django codebases, I've identified a set of recurring testing patterns and anti-patterns that significantly impact both test reliability and developer productivity.
This poster presents a visual field guide to practical TDD patterns in Django, organized as a decision-tree poster that developers can reference when writing tests for their own projects.
Section 1 — The Factory Pattern Taxonomy. A visual decision tree for choosing the right factory_boy strategy based on your model structure. When to use SubFactory vs. RelatedFactory vs. LazyAttribute for foreign keys, how to handle circular relationships without creating test data explosions, and the create vs. build vs. build_batch decision that controls whether you hit the database. Annotated with faker provider selection for generating realistic test data that keeps test failure messages readable.
Section 2 — Testing Permission Layers Without Drowning in Fixtures. Django apps often have three or more permission layers: model-level, view-level, and object-level (via packages like django-guardian or row-level security). This section shows a visual matrix for structuring permission tests: one axis for user roles, one for resources, and a clear pattern for generating all combinations using parameterized tests with pytest.mark.parametrize and factory traits. Instead of writing 30 separate test functions, you write one parameterized test with a role-resource matrix.
Section 3 — The Mock Boundary Diagram. A flowchart showing where to place mocking boundaries in a Django request lifecycle. The poster illustrates the difference between mocking at the view level, the service layer, and the adapter/client level — and why mocking too deep creates brittle tests while mocking too shallow creates slow ones. Includes a decision rule: "Mock at the boundary where your code meets code you don't own."
Section 4 — Common Anti-Patterns and Fixes. A visual rogues' gallery of the five most common Django testing anti-patterns with before/after code comparisons: test database leaks from missing TransactionTestCase, over-mocking that tests implementation instead of behavior, fixture files that nobody can maintain, test ordering dependencies, and the "God factory" that creates half the database for every test.
Visitors will gain a practical decision framework for structuring Django tests, rather than just knowledge of individual testing tools. The patterns are tool-agnostic at their core (though examples use pytest-django, factory_boy, and faker) and apply to any Django project.