Fix Test¶
Overview¶
Fix-test keeps a project's tests in step with its source. It turns file-system events into a prioritized, partly auto-executable maintenance plan, and it records what actually ran so the next plan can reason about staleness and coverage gaps.
Two modules cooperate:
test_maintenanceowns planning.TestMaintenanceWorkflowinspects file events and produces aTestMaintenancePlan— an ordered set ofTestPlanItementries, each describing one piece of test work (which file, whatTestAction, at whatTestPriority).test_runnerowns measurement. Standalone functions (run_tests_with_tracking,track_coverage,track_file_tests) execute tests and persist the results as telemetry records, and query functions (get_file_test_status,get_files_needing_tests) read those records back.
Fix-test is not a test generator — it decides what test work a
change implies and whether it can run unattended. It is reached as
the /fix-test skill; there is no dedicated attune CLI subcommand.
This page documents the Python API you call directly when wiring test
maintenance into a hook, a CI step, or a custom tool.
Concepts¶
From a file event to a plan¶
TestMaintenanceWorkflow is the coordinator. Construct it with a
project root, then drive it one of two ways:
- Event handlers —
on_file_created,on_file_modified, andon_file_deletedeach take a singlefile_pathand return a dict describing the test work that change implies. These are the integration point for a file-watcher or a git hook. run(context)— generates a whole-projectTestMaintenancePlanin one of four modes (analyze,execute,auto,report).
Both paths lean on the same building blocks:
| Type | What it represents |
|---|---|
TestPlanItem |
One unit of test work: file_path, the action (TestAction), the priority (TestPriority), a reason, an optional test_file_path, an estimated_effort string, an auto_executable flag, and a free-form metadata dict. |
TestMaintenancePlan |
The assembled plan: generated_at, the list of items, a summary dict, and options. Filter it with get_items_by_action, get_items_by_priority, or get_auto_executable_items. |
TestAction |
What to do with a test — one of CREATE, UPDATE, REVIEW, DELETE, SKIP, MANUAL. |
TestPriority |
How urgent — one of CRITICAL, HIGH, MEDIUM, LOW, DEFERRED. |
The two modules fit together¶
- Planning (
test_maintenance) answers "given this change, what test work is needed and how urgent is it?" It is index-backed: the workflow holds aProjectIndexand refreshes it when files change, so impact and staleness drive the priorities it assigns. - Measurement (
test_runner) answers "what did the tests actually do?" Its functions run pytest (or a custom command), parse the results, and writeTestExecutionRecord,CoverageRecord, andFileTestRecordentries into the telemetry store. The query functions then surface "is this file covered?" and "what still needs tests?" — the same signals the workflow'sget_stale_testsandget_test_health_summarysummarize.
Async vs sync — the one thing to get right¶
The workflow's event and run surface is asynchronous; everything else is a plain function call:
async—run,on_file_created,on_file_modified,on_file_deleted.awaitthem (or drive withasyncio.run).- sync — the plan-filter methods (
get_items_by_action, …), the workflow's summary methods (get_files_needing_tests,get_stale_tests,get_test_health_summary), and everytest_runnerfunction.
Two functions named get_files_needing_tests¶
Mind the namespace: there is a module-level
test_runner.get_files_needing_tests(stale_only=False,
failed_only=False) that reads telemetry records, and a
TestMaintenanceWorkflow.get_files_needing_tests(limit=20) method that
reads the project index. They are different functions with different
signatures and return types — import or call the one you mean.
Design & extension¶
Design decisions¶
- Planning is separated from measurement.
test_maintenancedecides what test work is needed;test_runnerrecords what tests did. Keeping them apart lets a hook plan without running tests, and lets a CI step record results without planning — each side is useful alone, and they compose when you want the full loop. - Plans are data, results are records. A
TestMaintenancePlanserializes viato_dict, and thetest_runnerfunctions return dataclass records (TestExecutionRecord,CoverageRecord,FileTestRecord) persisted to the telemetry store. Both sides hand back inspectable values rather than printing — callers own presentation. auto_executableis a per-item flag, not a global mode. Whether an item may run unattended is decided when theTestPlanItemis built, so a single plan can mix auto-runnable work with items that require humanREVIEWorMANUALattention."auto"mode simply filters on the flag.
Extension points¶
- Wire fix-test into a file-watcher or git hook: call the
on_file_created/on_file_modified/on_file_deletedcoroutines with the changed path and act on the returned status dict. - Add a maintenance step to CI:
await workflow.run({"mode": "auto"})to execute the safe subset, or{"mode": "report"}for a health summary you can gate on. - Feed measurement back into planning: record runs with
run_tests_with_tracking/track_coverage, then let the workflow'sget_stale_testsandget_test_health_summarysurface the gaps the recorded telemetry exposes.