pytest over TicketFlow's services. No solutions.md before submitting.
Exercise 1 — The suite audit
- Run
pytest --durations=10(ormanage.py test): list the 10 slowest tests. Classify each: legitimate unit / integration in disguise / real-time test. - Hunt the anti-patterns in YOUR suite: a test that depends on another (run the whole file vs test by test), a literal-message assertion, a
sleep, an ORM mock. Document each finding with the test's name. - Migrate 3 tests from the old suite (
manage.py test→ pytest): the setUp → fixture, and one of them parametrized. Verify the whole suite stays green with both runners.
Exercise 2 — The parametrization that survives
- Write
test_calcular_totalwith 6 parametrized cases (1 seat, 3, 10, 0 [error], -1 [error], 1000 [limit]) — case table on top, single assert below. - The test must survive TWO refactors: rename
calcular_total→precio_porand change its internal signature (extract_descuento_volumen). The tests are NOT edited. How many died? (expected: 0 if you tested the WHAT). - Add the org's commission case (08) with
parametrizeoverpytest.param(..., id="org-10-pct")— readable ids in the report.
Exercise 3 — Fakes before mocks
- Write the
gateway_rechazafixture (a configurable FakeGateway:declina_todo,timeout_pero_cobra— 32's one) and rewrite 3 tests that mocked the gateway withpatch. How many lines were saved and which new assertion did it enable (the saga's state)? - The repository test: rewrite the duplicate-reservation test (10) with
InMemoryReservationRepository(25) WITHOUT a DB. How many ms does it run in? (measure with--durations). - The one legitimate mock: verify that
enviar_email_confirmacion.delaygets ENQUEUED via on_commit (here the interaction IS the contract). Write the test withcaptureOnCommitCallbacksand the task mock.
Exercise 4 — The HOW tests, hunted
- Write a BAD test on purpose:
with patch("reservations.services.Seat.objects") as mock_seat:... mock_seat.filter.assert_called_once(). Now refactorreservar()(useselect_for_updateinstead offilter): the good test stays green, the bad one dies. Paste the evidence of both. - The literal message: find a test with a full-text assertion and change it to
err.code. Verify: change the human error's text → the test stays green.
Exercise 5 — The project's convention
- Write the project's
conftest.pywith the 5 base fixtures (clock_fijo, evento, comprador, gateway, mailbox) and document each with a one-line docstring. - Rename 5 tests to the
test_<subject>_<scenario>_<result>convention and run the suite:pytest -k "reservar"must find them all by keyword. - Measure
services/coverage:pytest --cov=reservations.services --cov-report=term. Which service is below 90% and which line is NOT tested? (the answer is not "add a test": it is "is that line dead code?").
Submit
Paste the durations report, the 3 migrated tests, the mocks→fakes before/after and the services coverage. Next: Lesson 34 — Integration testing.