EUROPYTHON 2026 · KRAKÓW POSTER SESSION · EXHIBIT HALL · WED 15 JULY FIELD NOTES

Django TDD Patterns — A Visual Field Guide

Kuldeep Pisda — Django & growth consultant · creator of django-rls · DjangoCon US tutorials 2022–24 · kdpisda.in

01The Factory Pattern Taxonomy

SITUATION REACH FOR WHY
Test never touches the DBbuild() / build_batch()In-memory, no INSERT — the fast default for pure logic.
Model needs a parent FKSubFactoryThe dependency must exist before the child row.
Parent should spawn childrenRelatedFactoryRuns after creation — reverse relations without loops.
Field derived from siblingsLazyAttributelambda o: f"{o.username}@corp.dev"
Circular FKsstring ref + SelfAttributeBreak one direction — never two eager SubFactories.

FAKER RULE  Match the provider to the domain — faker.company(), not "test1". Failure messages should read like your data.

02Permission Testing, Without Drowning in Fixtures

Django apps stack three permission layers — model (Meta.permissions), view (permission_classes), object (django-guardian / RLS). Test each layer once in isolation, then test the role × action matrix at the view with one parameterized test instead of thirty functions:

@pytest.mark.parametrize("role, expected", [
("anonymous", 401), ("member", 403),
("staff", 200), ("owner", 200),
])
def test_invoice_update(role, expected,
client_for, invoice):
resp = client_for(role).patch(
invoice.get_absolute_url(),
{"status": "paid"})
assert resp.status_code == expected
ROLE list retrieve update delete
anonymous401401401401
member200200403403
staff200200200403
owner200200200204

Roles come from factory traits — one factory, four personas, zero JSON fixtures.

03The Mock Boundary

Request
test client
View
urls · DRF
Service
your logic
Adapter / Client
✓ MOCK THIS SEAM
Third parties
Stripe · S3 · SMTP
“Mock at the boundary where your code meets code you don’t own.”

04The Rogues’ Gallery — Five Anti-Patterns

ANTI-PATTERN THE SMELL THE FIX
The Leaky Teston_commit hooks silently never fire under TestCase.Use TransactionTestCase when the code manages transactions.
Over-Mockingassert_called_once_with everywhere — tests pin implementation.Assert behavior: assert order.total == Decimal("21.60").
Fixture GraveyardJSON fixture files nobody dares touch; every migration breaks them.Factories declare only what the test needs: OrgFactory(plan="pro").
Order-Dependent TestsModule-level state; test_b passes only after test_a.State lives in fixtures; enforce with pytest-randomly in CI.
The God FactoryDefault factory creates org, plan, team, invoice… half the schema per test.Opt in with traits: UserFactory(with_org=True).
Bring these patterns to your codebase.

Kuldeep Pisda consults on production Django systems — multi-tenant SaaS, 50k+ concurrent-user backends, PostgreSQL performance recovery, and test suites teams actually trust.

kdpisda.in · django-rls on PyPI
SCAN → WORK WITH ME