You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
New-test detection lists tests with cargo nextest list and compares against the coverage DB. The build args for that listing are extracted from the post--- passthrough by cargo_build_args (src/collect.rs), which is an allowlist of cargo build flags — it deliberately drops everything else, including positional test-name filters and -E/--filterset.
So when the user runs cargo affected run -- some_test_name:
cargo nextest list enumerates all tests (the positional filter is dropped).
cargo nextest run receives the positional filter and runs only matching tests.
A new test (absent from the DB) that does not match some_test_name is still flagged new, lands in the generated --config-file selection, and is handed to nextest run — which then skips it because it doesn't match the positional filter. If the selection collapses to only such tests, nextest run exits 4 (error: no tests to run). run_tests in src/run.rs does not pass --no-tests=warn, so that exit propagates.
This is the same failure class as the bugs fixed in #38, via a different trigger. It is pre-existing and was not introduced or worsened by #38 — flagged there as a known follow-up.
Proposed fix
Two coordinated changes:
cargo_build_args → a run-only-flag denylist. Instead of allowlisting build flags, forward everything to nextest listexcept nextest run-only flags (--retries, --no-fail-fast, --no-tests, --max-fail, -j/--test-threads, --status-level, …). That carries positionals and -E through, so the listing reflects the run's full filter config.
Key detection off filter-match.status instead of the ignored boolean.cargo nextest list --message-format json tags every testcase with filter-match: {status: matches|mismatch, …}. A test counts toward new/stranded/affected selection only when filter-match.status == "matches". This single predicate subsumes #[ignore]d tests, positional/-E filters, --run-ignored, and the project's own default-filter — unifying the three exclusion checks (new/stranded/affected) that fix: correct new-test detection for ignored tests and feature builds #38 left as separate listing.ignored filters.
Verified: cargo nextest list <positional-filter> still enumerates all testcases (each tagged with its filter-match status), so forwarding filters to list does not shrink Listing.tests and does not break collect --diff's prune.
Tradeoff
The denylist must stay complete against nextest's CLI. A future nextest run-only flag not in the denylist would be forwarded to cargo nextest list, which rejects unknown args and exits non-zero — cargo affected run -- --that-new-flag would break loudly until the denylist is updated. The current allowlist instead fails silently on a future cargo build flag (listing mismatch, no error). The denylist's loud failure is arguably better aligned with the repo's "fail loudly over silently degrading" principle, but it is a maintenance commitment worth noting.
Problem
New-test detection lists tests with
cargo nextest listand compares against the coverage DB. The build args for that listing are extracted from the post---passthrough bycargo_build_args(src/collect.rs), which is an allowlist of cargo build flags — it deliberately drops everything else, including positional test-name filters and-E/--filterset.So when the user runs
cargo affected run -- some_test_name:cargo nextest listenumerates all tests (the positional filter is dropped).cargo nextest runreceives the positional filter and runs only matching tests.A new test (absent from the DB) that does not match
some_test_nameis still flaggednew, lands in the generated--config-fileselection, and is handed tonextest run— which then skips it because it doesn't match the positional filter. If the selection collapses to only such tests,nextest runexits 4 (error: no tests to run).run_testsinsrc/run.rsdoes not pass--no-tests=warn, so that exit propagates.This is the same failure class as the bugs fixed in #38, via a different trigger. It is pre-existing and was not introduced or worsened by #38 — flagged there as a known follow-up.
Proposed fix
Two coordinated changes:
cargo_build_args→ a run-only-flag denylist. Instead of allowlisting build flags, forward everything tonextest listexcept nextestrun-only flags (--retries,--no-fail-fast,--no-tests,--max-fail,-j/--test-threads,--status-level, …). That carries positionals and-Ethrough, so the listing reflects the run's full filter config.filter-match.statusinstead of theignoredboolean.cargo nextest list --message-format jsontags every testcase withfilter-match: {status: matches|mismatch, …}. A test counts toward new/stranded/affected selection only whenfilter-match.status == "matches". This single predicate subsumes#[ignore]d tests, positional/-Efilters,--run-ignored, and the project's owndefault-filter— unifying the three exclusion checks (new/stranded/affected) that fix: correct new-test detection for ignored tests and feature builds #38 left as separatelisting.ignoredfilters.Verified:
cargo nextest list <positional-filter>still enumerates all testcases (each tagged with itsfilter-matchstatus), so forwarding filters tolistdoes not shrinkListing.testsand does not breakcollect --diff's prune.Tradeoff
The denylist must stay complete against nextest's CLI. A future nextest
run-only flag not in the denylist would be forwarded tocargo nextest list, which rejects unknown args and exits non-zero —cargo affected run -- --that-new-flagwould break loudly until the denylist is updated. The current allowlist instead fails silently on a future cargo build flag (listing mismatch, no error). The denylist's loud failure is arguably better aligned with the repo's "fail loudly over silently degrading" principle, but it is a maintenance commitment worth noting.Ref #38.