Command-line reference¶
Top-level command¶
testenix [-h] [--version]
testenix [--config PYPROJECT] run [RUN_ARGS ...]
testenix pytest [PYTEST_ARGS ...]
testenix migrate FRAMEWORK PATH [PATH ...] [MIGRATION_ARGS ...]
testenix [--config PYPROJECT] tune [PATH ...] [TUNING_ARGS ...]
testenix [--config PYPROJECT] benchmark [PATH ...] [TUNING_ARGS ...]
testenix manifest PATH [PATH ...] --output FILE
Option |
Description |
|---|---|
|
Show command help. |
|
Print the installed Testenix version. |
|
Load |
testenix run¶
testenix run [PATH ...]
[--config PYPROJECT]
[-w auto|N]
[--retries N]
[--timeout SECONDS]
[-t TAG ...]
[--json FILE]
[--junit FILE]
[--history FILE | --no-history]
[--shard-modules]
[--manifest FILE]
[-q | -v | -vv]
[--color {auto,always,never} | --no-color]
[--show-skips]
[--durations N]
Argument |
Default |
Description |
|---|---|---|
|
configured |
Files or directories to discover. |
|
|
Positive worker count, or adaptive selection from schedulable units, history, startup cost, and CPU capacity. |
|
|
Additional attempts after a gating outcome. |
|
none |
Global hard deadline for every selected test. |
|
none |
Required tag; repeat for AND selection. |
|
none |
Write the lossless JSON run result. |
|
none |
Write a JUnit XML report. |
|
|
Override the duration-history database. |
|
off |
Disable reading and writing history. |
|
off |
Opt eligible modules into per-test execution units after conservative static safety checks. |
|
none |
Reuse an explicitly generated, source-verified trusted collection manifest. |
|
off |
Hide the run header and compact per-file table. Collection errors, failure details, and the final summary remain visible. |
|
off |
Print one result row per test in the stable detailed format. Repeat for |
|
off |
Add worker, attempt, and phase metadata, including captured output. |
|
|
Select automatic ANSI styling, force styling, or disable it. |
|
off |
Alias for |
|
off |
Include reasons for skipped and expected-failure tests. |
|
none |
List the |
CLI options override [tool.testenix] values for the current run.
With no presentation flags, Testenix prints a compact row for each source file, complete collection/failure diagnostics, and a final summary. Console output is assembled in stable source order after execution completes; these modes do not promise live progress updates. Presentation flags change only terminal rendering, not selection, scheduling, result statuses, JSON, JUnit, or exit codes.
workers = auto never means “start one process per logical CPU.” Testenix caps it by the number of
units that can run independently. Reliable duration history feeds a makespan/startup-cost model;
cold runs use a conservative cap. The final console and JSON results report the worker count
actually used. An explicit integer remains useful for fixed CI resource limits and reproducible
published benchmarks.
--shard-modules is an explicit safety/performance trade-off. Modules with module/session
fixtures, statically visible mutable global state, or import-time lifecycle hazards keep module
affinity; eligible modules may be split. Static analysis cannot prove every dynamic side effect.
--manifest accepts the versioned JSON produced by testenix manifest. Malformed input is a usage
error. An otherwise valid manifest whose roots, complete Python-file inventory, or SHA-256 digests
no longer match is treated as stale, and the run safely performs ordinary supervised collection.
In auto color mode, Testenix requires a terminal, respects NO_COLOR, allows FORCE_COLOR, and
disables styling for a truthy CI value or TERM=dumb. Explicit always or never takes
precedence.
testenix pytest¶
testenix pytest [PYTEST_ARGS ...]
This compatibility command hands the current CLI process to pytest from the same interpreter and
forwards every argument without translation. It preserves pytest configuration, collection,
fixtures, parametrization, markers, classes, hooks, plugins, output, and normal exit status. The
compact native Testenix renderer is not involved: output is pytest’s own output, just as with
uv run pytest tests. For a concise bridge invocation, use testenix pytest -q --tb=short tests.
$ testenix pytest -q --tb=short tests
$ testenix pytest tests/test_api.py::test_health -k smoke --maxfail=1
$ testenix pytest -n auto tests
$ testenix pytest --junitxml=reports/pytest.xml tests
Pytest and its plugins must be installed in the same Python environment as Testenix. The optional
testenix[pytest] extra installs a supported pytest (>=8.3,<10) when needed. Testenix does not
consume a leading --: pytest receives it unchanged, including its normal end-of-options meaning.
[tool.testenix] does not configure this command. Arguments after pytest are never interpreted as
native Testenix options, even when their names overlap: -q, -v, --color, --show-skips,
--durations, --workers, and every other token are forwarded unchanged. They can therefore be
handled by pytest or a plugin, or rejected by pytest if unsupported. Pytest’s equivalent spellings
include -rs, --durations=N, and --color=yes|no|auto; Testenix does not translate native
spellings. In particular,
testenix --config PATH pytest ... is rejected; pytest must immediately follow testenix. See
pytest compatibility for the full boundary.
testenix migrate¶
testenix migrate {auto,pytest,unittest} PATH [PATH ...]
[-o OUTPUT]
[-w auto|N]
[--validation-timeout SECONDS]
[--dry-run | --check]
[--report-json FILE|-]
Argument |
Default |
Description |
|---|---|---|
|
required |
|
|
required |
Source files or directories. Sources are never modified. |
|
|
New directory to publish; it must not exist. |
|
|
Worker count for parallel candidate validation; an integer must be at least |
|
|
Independent deadline for each source/native subprocess. |
|
off |
Static analysis and source-hash check only; run and publish nothing. |
|
off |
Full differential validation, with no published output. |
|
none |
New audit path inside the project and outside source/output suites, or |
Without --dry-run or --check, migration requires a green source baseline, an equal native
serial result, and an equal native parallel result, including every mapped test outcome. It then rechecks source hashes and atomically
renames a complete staging directory to the new output without replacement. A failure before that
rename leaves the output absent. A report-only failure after publication warns but leaves the
validated output and successful exit status intact. See safe migration for supported constructs, unittest’s
SHA-pinned wrapper model, rollback guarantees, and external-side-effect boundaries.
Human-readable output distinguishes an analyzed candidate, a validated candidate, a generated
candidate, a statically convertible subset, and a published conversion. Repeated diagnostics are
grouped by severity and code, with the first source location shown. Use --report-json FILE or
--report-json - when every individual line-addressed diagnostic is required. The JSON field
converted_tests counts source-to-target mappings built in memory; only status: published and
published: true mean that an output directory was created.
MIG006 warns that a candidate has only one schedulable module affinity unit despite a parallel
worker setting. It is emitted only for --check or publication after static analysis succeeds,
because dry-run and unsupported transactions never execute the parallel gate.
testenix tune / testenix benchmark¶
testenix tune [PATH ...]
[--config PYPROJECT]
[--candidates N[,N...]]
[--warmups N]
[--repeats N]
[--pytest-source PATH] ...
[--json FILE|-]
[--shard-modules]
[--manifest FILE]
[--write]
testenix benchmark is an exact alias for testenix tune.
Argument |
Default |
Description |
|---|---|---|
|
configured |
Native Testenix suite to tune. |
|
resource-aware 1/2/4 sweep |
Positive worker counts to measure. Counts above the number of execution units are deduplicated at that limit; values above four require this explicit option. |
|
|
Unrecorded warmups for each native candidate and optional pytest source. |
|
|
Recorded samples for each candidate. Candidate order alternates between rounds. |
|
|
Deadline for each complete native or pytest suite run; cleanup uses a Windows Job Object or POSIX root-session plus identity-tracked descendants. |
|
none |
Also time a corresponding pytest source path; repeat for multiple paths. |
|
none |
Write the complete tuning report to a new file, or standard output with |
|
configured value |
Tune with explicit safe intra-module sharding or module affinity. |
|
configured value |
Use one source-verified collection manifest for every native sample. |
|
off |
Persist the measured recommendation as |
The command measures fresh CLI processes with Testenix history disabled. A one-worker probe
establishes the inventory and outcomes, and every native candidate must match them. To avoid
persisting noise, it recommends the smallest worker count within a narrow tolerance of the best
median. --write is the only configuration-mutating mode; normal tuning and adaptive auto do not
edit configuration. A workers-only write is rejected when a transient sharding or manifest override
differs from the loaded project configuration, or when that configuration file changes during the
measurement, because the recommendation would not describe the persisted execution profile. The
writer compares the pre-tuning bytes again immediately before an atomic replacement. Project
Python/TOML sources, linked source directories, explicit suite files, and a trusted manifest are
fingerprinted by content and file identity after every sample; observed drift discards the complete
result. Run publishable tuning from an immutable checkout to exclude a writer racing the final
filesystem operation; installed packages, non-source data, and other runtime inputs are also outside
that fingerprint.
The optional pytest row is useful for local orientation only when it represents the corresponding source suite. A public pytest/Testenix claim still needs equivalent inventories and outcomes, counterbalanced commands, environment/version provenance, and the complete benchmarking contract.
testenix manifest¶
testenix manifest PATH [PATH ...] --output FILE
The command performs supervised native collection and creates a new deterministic trusted
manifest. It records collection roots, the complete selected Python-source inventory and SHA-256
fingerprints, collected tests and issues, and conservative module-sharding decisions. Test case
parameter names are retained while their values are redacted, so environment-derived secrets are
not copied into the trust artifact. FILE must
not already exist; Testenix does not silently replace a previous trust artifact.
Use it explicitly on later runs:
$ testenix manifest tests --output .testenix/collection.json
$ testenix run tests --manifest .testenix/collection.json
This can avoid importing every selected module once for collection and once again for execution. Execution workers still import the modules they run. Source verification cannot cover dynamic collection inputs such as environment variables or external services; regenerate the manifest when those inputs change.
Examples¶
$ testenix run
$ testenix run tests/unit tests/integration --workers 4
$ testenix run --tag unit --tag fast
$ testenix run --retries 1 --timeout 10
$ testenix run -v --show-skips --durations 10
$ testenix run --color never
$ testenix run --json reports/run.json --junit reports/junit.xml
$ testenix run tests --shard-modules
$ testenix manifest tests --output .testenix/collection.json
$ testenix run tests --manifest .testenix/collection.json
$ testenix tune tests --candidates 1,2,4,8 --warmups 1 --repeats 5
$ testenix benchmark tests --json reports/tuning.json
$ testenix tune --write
$ testenix --config config/pyproject.toml run
$ testenix pytest -q --tb=short tests
$ testenix migrate pytest tests --dry-run
$ testenix migrate auto tests --check --report-json reports/migration.json
$ testenix migrate unittest tests --output tests_testenix
Exit codes¶
The native testenix run command uses these codes:
Code |
Meaning |
|---|---|
|
The run has no gating result. |
|
A test failed, errored, timed out, crashed, became flaky, or unexpectedly passed. |
|
Invalid CLI/configuration, collection error, or empty explicit tag selection. |
|
Internal runner, reporter, or history failure. |
|
User interruption. |
The testenix migrate command uses these codes:
Code |
Meaning |
|---|---|
|
Analysis, check, or publication succeeded; also retained after a report-only failure following publication. |
|
Source/candidate execution failed, timed out, or differed. |
|
Unsafe path, existing output, source drift, or invalid migration usage. |
|
Internal process or report failure before publication. |
|
An unsupported construct was found; nothing was published. |
|
User interruption. |
testenix pytest hands the current CLI process to pytest, so pytest or plugin exit statuses are
returned unchanged. Standard pytest statuses are 0 success, 1 test failure, 2 interruption,
3 internal error, 4 usage error, and 5 no tests collected. Before the handoff, Testenix
returns 2 when pytest is missing and 3 when pytest cannot take over the process.