Repository navigation
New-test detection ignores positional test-name filters in the run passthrough #39
Description
Problem
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 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_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 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.- Key detection off
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 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.
Ref #38.
This was written by Claude Code on behalf of Maximilian Roos
Activity
cargo-affected-bot commentedon May 20, 2026
Reproduced the bug —
cargo affected run -- addwith a new untracked testtest_brand_newexited 4 (error: no tests to run) as described.Opened #41 with the two-part fix from the proposal:
cargo_build_args→args_for_listing(run-only denylist), andListing.ignored→Listing.excludedkeyed offfilter-match.status == "mismatch". The threenew/stranded/affectedexclusion sites that #38 left as separatelisting.ignoredfilters now share the singleexcludedpredicate. Added a reproduction test intests/functional/new_test.rs; all 37 functional tests pass.fix(config): key the filterset warning on what nextest can attribute