Skip to content

Add assert_task_count() and an isolated-queue pytest recipe - #157

Merged
PhiLily merged 1 commit into
mainfrom
feature/run-tasks-assertions
Oct 28, 2026
Merged

PhiLily merged 1 commit into
mainfrom
feature/run-tasks-assertions

Conversation

@PhiLily

@PhiLily PhiLily commented Oct 27, 2026

Copy link
Copy Markdown
Member

django_ox.testing gains assert_task_count(). It reads OxTask rows for one backend alias, queue and task path and counts those whose stored args and kwargs equal the caller's after the JSON round trip enqueue() applies before storing them, so a tuple in args matches a stored list. A value the standard library's json.dumps() cannot handle, such as a raw datetime, UUID or Decimal, is rejected with TypeError naming the offending field rather than silently mismatching. A count that differs raises AssertionError naming the backend, queue, path, the args and kwargs after that round trip, and the expected and observed counts. The helper reads live rows, so a rolled-back enqueue is not counted.

docs/patterns.md has two new sections. "Assert on the queue directly" documents the helper with a short example. "An isolated queue for one test" documents a pytest fixture recipe that wraps run_tasks() to drain a single reserved queue, and refuses with ValueError at fixture setup, before the test body enqueues anything, if that queue is already occupied by setUpTestData or an earlier fixture. The recipe is documentation, not a shipped API: tests/settings.py reserves the isolated-recipe queue in the test backend's QUEUES for it, and tests/test_testing_assertions.py covers both the helper and the recipe, including JSON matching and rejection, backend and queue scoping, and the occupied-queue refusal.

CHANGELOG.md gets an Added entry and docs/llms-full.txt is regenerated.

The new test module and the full suite pass locally on SQLite; ruff check, ruff format --check, mypy --strict src/ and mkdocs build --strict pass on the branch.

Closes #129

django_ox.testing gains assert_task_count(). It reads OxTask rows for
one backend alias, queue and task path and counts those whose stored
args and kwargs equal the caller's after the JSON round trip enqueue()
applies before storing them, so a tuple in args matches a stored list.
A value the standard library's json.dumps() cannot handle, such as a
raw datetime, UUID or Decimal, is rejected with TypeError naming the
offending field rather than silently mismatching. A count that differs
raises AssertionError naming the backend, queue, path, the args and
kwargs after that round trip, and the expected and observed counts. The
helper reads live rows, so a rolled-back enqueue is not counted.

docs/patterns.md has two new sections. "Assert on the queue directly"
documents the helper with a short example. "An isolated queue for one
test" documents a pytest fixture recipe that wraps run_tasks() to drain
a single reserved queue, and refuses with ValueError at fixture setup,
before the test body enqueues anything, if that queue is already
occupied by setUpTestData or an earlier fixture. The snippet says where
the reserved name belongs: in that backend's own QUEUES list in the
TASKS setting, a sibling of OPTIONS rather than a key inside it. The
recipe is documentation, not a shipped API: tests/settings.py reserves
the isolated-recipe queue in the test backend's QUEUES for it.

docs/stability.md lists django_ox.testing.assert_task_count among the
public testing helpers. It is public and stable: its keyword-only
signature (path, queue, count, backend, args, kwargs) does not carry
the provisional status run_tasks() has on that page.

tests/test_testing_assertions.py, with its tasks in
tests/testing_assertions_tasks.py, covers the helper and the recipe:
JSON matching and rejection, backend and queue scoping, a finished row
still counted, the count mismatch message, and the occupied-queue
refusal. The tests run under both TestCase and TransactionTestCase.
TestCase wraps every test in a transaction it rolls back, so the
TransactionTestCase tests are the ones that read a row enqueue() has
committed, and they also show that a nested atomic() which rolls back
is still excluded without that outer transaction. CHANGELOG.md gets an
Added entry under Unreleased and docs/llms-full.txt is regenerated.

Closes #129
@PhiLily
PhiLily force-pushed the feature/run-tasks-assertions branch from 3f23e18 to 2d81a78 Compare October 28, 2026 09:09
@PhiLily
PhiLily merged commit 520bf02 into main Oct 28, 2026
58 checks passed
@PhiLily
PhiLily deleted the feature/run-tasks-assertions branch October 28, 2026 10:04
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.

Task assertions and an isolated fixture around run_tasks()

1 participant