Write correct Django tests — TestCase vs TransactionTestCase, setUpTestData, factory-boy, assertNumQueries, mock.patch placement, and DRF APITestCase patterns
99
99%
Does it follow best practices?
Impact
99%
1.33xAverage score across 2 eval scenarios
Passed
No known issues
{
"instruction": "Write correct Django tests following best practices",
"relevant_when": "Agent writes or modifies Django test files",
"context": "Django TestCase wraps each test in a transaction for automatic isolation. TransactionTestCase is needed for on_commit hooks and signals. setUpTestData is faster than setUp for read-only data. factory-boy should be used for complex test data. mock.patch must target where names are looked up, not where they are defined.",
"sources": [
{
"type": "file",
"filename": "skills/django-testing/SKILL.md",
"tile": "tessl-labs/django-testing@0.2.0"
}
],
"checklist": [
{
"name": "correct-testcase-class",
"rule": "Agent uses TestCase by default. Uses TransactionTestCase only when testing on_commit hooks, post-commit signals, or multi-database routing.",
"relevant_when": "Agent writes Django test classes"
},
{
"name": "setup-seeds-data",
"rule": "Agent creates test data in setUp (for mutable data) or setUpTestData (for read-only shared data). TransactionTestCase tests always use setUp, not setUpTestData.",
"relevant_when": "Agent sets up Django test fixtures"
},
{
"name": "setuptestdata-for-readonly",
"rule": "Agent uses @classmethod setUpTestData(cls) for read-only test fixtures that do not change across tests, improving performance.",
"relevant_when": "Agent creates test data that multiple tests read but do not modify"
},
{
"name": "factories-in-setup",
"rule": "When factory-boy is used, factories are defined in <app>/factories.py with DjangoModelFactory, Meta model, SubFactory for FKs, and Faker for fields. Factories are actually called in setUp or setUpTestData, not objects.create().",
"relevant_when": "Agent uses factory-boy for test data"
},
{
"name": "assert-num-queries",
"rule": "Agent uses self.assertNumQueries() on list endpoint tests to catch N+1 query problems. The query count should be constant regardless of result count.",
"relevant_when": "Agent writes tests for list/queryset endpoints"
},
{
"name": "mock-patch-location",
"rule": "Agent patches names where they are looked up (the importing module), not where they are defined. E.g., if orders/views.py does 'from services.email import send_email', patch 'orders.views.send_email'.",
"relevant_when": "Agent uses unittest.mock.patch in Django tests"
},
{
"name": "override-settings",
"rule": "Agent uses @override_settings decorator for tests that depend on Django settings values. Never modifies django.conf.settings directly.",
"relevant_when": "Agent tests behavior that varies by Django settings"
},
{
"name": "file-upload-testing",
"rule": "Agent uses SimpleUploadedFile for file upload tests, passing it in POST data dict (not JSON). Tests both valid and invalid file types.",
"relevant_when": "Agent writes tests for file upload endpoints"
},
{
"name": "management-command-testing",
"rule": "Agent uses call_command() from django.core.management to test management commands, capturing stdout with StringIO. Does not use subprocess.",
"relevant_when": "Agent writes tests for Django management commands"
},
{
"name": "drf-apitestcase",
"rule": "DRF tests extend APITestCase and use APIClient. Authentication tests use force_authenticate(). Both authenticated and unauthenticated paths are tested.",
"relevant_when": "Agent writes Django REST Framework tests"
},
{
"name": "essential-test-patterns",
"rule": "API test suite includes: happy path (200), validation rejection (400), 404 for missing resource, persistence verification (POST then GET), and error response consistency.",
"relevant_when": "Agent writes API test coverage"
},
{
"name": "content-type-on-post",
"rule": "Agent includes content_type='application/json' on POST requests to Django test client.",
"relevant_when": "Agent sends JSON POST requests in tests"
},
{
"name": "no-manual-cleanup",
"rule": "Agent does not write manual tearDown or cleanup code. TestCase transaction rollback handles isolation automatically.",
"relevant_when": "Agent writes Django test cleanup"
},
{
"name": "run-command-documented",
"rule": "Agent documents that tests are run with 'python manage.py test'.",
"relevant_when": "Agent provides instructions for running tests"
}
]
}