Rules for building test data in Python with factory_boy: explicit values for everything a test asserts on, keyword overrides and Traits, build() versus create(), resetting sequences. Use when creating or using a factory in a Python test. Background knowledge that agents preload; not a command.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
SSkills DirectorySkills Directory
Is that skill safe to install?
Are you the author of Builder Rules?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/janszewczyk-builder-rules)
---
name: builder-rules
description: "Rules for building test data in Python with factory_boy: explicit values for everything a test asserts on, keyword overrides and Traits, build() versus create(), resetting sequences. Use when creating or using a factory in a Python test. Background knowledge that agents preload; not a command."
user-invocable: false
---
<!-- generated by knowledge.mjs from 6 note(s) (sha256 d221acc07e84); edit the notes in knowledge/, then run build -->
# Test data factory rules (Python, factory_boy)
Apply these rules whenever you create or use a factory in a Python test.
## Always apply (critical, high)
### Set every value the test asserts on explicitly when you build test data
_high · any_
**Rule.** Build test data from a builder or factory, and pass an explicit override for every field the test
asserts on or branches on. Leave random values only in fields the test never looks at. Use named
variants (traits) for whole states such as "admin" or "inactive" instead of repeating the same
overrides in many tests.
**Why.** An assertion against a randomly generated value passes or fails depending on the seed, and a
reader cannot tell from the test which value matters. An explicit override documents the input the
test depends on and makes the failure reproducible.
### Pass asserted values as keyword arguments and model states as Traits
_high · python, factory-boy_
**Rule.** Pass every value the test asserts on as a keyword argument to the factory call. Use
`build_batch(size, **kwargs)` for lists. Define recurring states as `factory.Trait` in the
factory's `class Params` and switch them on with `admin=True`.
**Why.** A Faker-generated name asserted in a test passes only by coincidence of the seed, and the reader
cannot see which input the test depends on.
**Incorrect:**
```python
user = UserFactory.build()
assert render_greeting(user) == f"Hello, {user.name}"
```
**Correct:**
```python
class UserFactory(factory.Factory):
class Meta:
model = User
name = factory.Faker("name")
role = "member"
class Params:
admin = factory.Trait(role="admin")
user = UserFactory.build(name="Ada Lovelace")
admins = UserFactory.build_batch(3, admin=True)
assert render_greeting(user) == "Hello, Ada Lovelace"
```
**Exceptions.** Under `mypy --strict` the example above fails: `factory.Factory` takes no type argument through the `factory` package, and the declarations are untyped calls. Import `Factory` from `factory.base` and subclass `Factory[User]`, import `Faker` from `factory.faker` and `Trait` from `factory.declarations`, and silence the remaining `no-untyped-call` on each declaration with a reason: `# type: ignore[no-untyped-call] # factory_boy declarations are untyped`.
## Read when the task touches it
| Impact | Rule | Applies to |
| --- | --- | --- |
| medium | [Reset builder counters and random state between tests that depend on them](references/rules.md#reset-builder-counters-and-random-state-between-tests-that-depend-on-them) — Sequences and seeded randomness carry over between tests; reset them where a test depends on their values. | any |
| medium | [Build structured test data with a builder, not inline object literals](references/rules.md#build-structured-test-data-with-a-builder-not-inline-object-literals) — Typed objects with three or more fields come from a shared builder; reuse an existing one before writing one. | any |
| medium | [Call Factory.build() unless the test needs the row in the database](references/rules.md#call-factorybuild-unless-the-test-needs-the-row-in-the-database) — Calling the factory directly runs create() and writes to the database; build() keeps a test in memory. | python, factory-boy |
| medium | [Reset factory sequences in setup when a test depends on sequence values](references/rules.md#reset-factory-sequences-in-setup-when-a-test-depends-on-sequence-values) — Factory.reset_sequence() restarts a Sequence; factory.random.reseed_random() makes Faker values reproducible. | python, factory-boy |