Skip to content

test(fixtures): factory_boy factories + delegate make_* helpers (#1272)#1319

Open
jonfroehlich wants to merge 1 commit into
masterfrom
1272-factory-boy-fixtures
Open

test(fixtures): factory_boy factories + delegate make_* helpers (#1272)#1319
jonfroehlich wants to merge 1 commit into
masterfrom
1272-factory-boy-fixtures

Conversation

@jonfroehlich

Copy link
Copy Markdown
Member

First PR slice of #1272 (testing leverage — realistic test data). Introduces factory_boy + Faker fixtures as the single source of truth for building model instances, and rewrites the DatabaseTestCase.make_* helpers as thin wrappers over them.

What's in this slice

  • factory_boy==3.3.3 + Faker==40.23.0 added to requirements.txt (new Testing section).
  • website/tests/factories.py — factories for Person, Project, Video, Publication, Talk, Poster, NewsItem, Award, ProjectRole.
  • website/tests/base.pymake_* helpers now delegate to the factories, preserving their original keyword API (notably the year=YYYY shorthand and with_thumbnail) so the ~200 existing call sites stay unchanged.
  • website/tests/test_factories.py — 10 tests guarding the factories themselves.
  • _GIF_1PX moved to factories.py (single home); the one importer (test_easter_egg_picker.py) repointed.

Two design decisions

  • Filesystem-light by default. Factory file fields use tiny in-memory uploads (a 1×1 GIF, a stub PDF) — same approach base.py already used. Keeps the DB suite fast and skips Person.save()'s Star Wars fallback (which reads a real file off disk). Curated real seed_media/ is deferred to the layer-2 follow-up where exercising real thumbnail/crop/PDF paths actually matters.
  • No auto-authors. Publication/Talk/Poster factories create authorless artifacts unless authors=[...] is passed. This keeps the existing make_publication call sites behavior-identical (they add authors explicitly) and preserves authorless-path coverage. The issue's example showed auto-3-authors; diverging is documented in the factory docstring. seed_dev_data can pass authors=PersonFactory.create_batch(n).

Why

Foundation for #1278 item 5 (backfill high-risk untested code) and #1272 layer 2 (realistic local dev data). Building the connected ProjectRole/M2M/SortedManyToManyField graph is now one line instead of twenty, so future test-writing and data-seeding get much cheaper. No production behavior changes — pure test infrastructure.

Testing

  • Full suite green: 211 passing (was 201) via python manage.py test website --settings=makeabilitylab.settings_test.
  • Factory tests run 3× to confirm no Faker-driven flakiness (Faker is unseeded; no assertion keys off a generated value).
  • CI installs factory_boy/Faker fresh from requirements.txt.

Follow-ups (separate PRs, per the issue)

Note for local dev

A requirements.txt change needs a rebuild to persist locally: ./run-docker-local-dev.sh --build. (I pip install'd into the running container to validate this branch.)

🤖 Generated with Claude Code

First PR slice of #1272 (testing leverage): introduce factory_boy/Faker
fixtures as the single source of truth for building model instances, and
rewrite the DatabaseTestCase make_* helpers as thin wrappers over them.

- Add factory_boy==3.3.3 + Faker==40.23.0 (Testing section of requirements).
- New website/tests/factories.py: Person/Project/Video/Publication/Talk/
  Poster/NewsItem/Award/ProjectRole factories. Filesystem-light by default
  (tiny in-memory GIF/stub PDF) so the suite stays fast and skips
  Person.save()'s Star Wars fallback. No auto-authors: artifacts are
  authorless unless authors=[...] is passed, preserving the ~200 existing
  make_publication call sites and keeping authorless paths testable.
- base.py make_* helpers now delegate to the factories while preserving
  their original keyword API (the year=YYYY shorthand, with_thumbnail).
- New website/tests/test_factories.py guards the factories: each builds a
  saved instance, the ProjectRole/M2M/SortedManyToMany graph composes, and
  the no-auto-authors contract holds.
- Move _GIF_1PX to factories.py (its single home); repoint the one importer.

Follow-ups (separate PRs, per the issue): seed_dev_data command + curated
seed_media/, then pull_prod_subset.sh; #1278 items 4/5/6.

Full suite: 211 passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jonfroehlich

Copy link
Copy Markdown
Member Author

Merge follow-up: this branch was cut before the docs were touched, so on merge one line in CONTRIBUTING.md (~L267, "Running the Test Suite") goes stale — it says the make_* helpers are "built on plain Model.objects.create()", which is exactly what this PR changes (they now delegate to the factories). Update that sentence to mention website/tests/factories.py when merging (or in a quick follow-up), and consider adding a one-liner pointing contributors at the factories for richer fixtures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant