Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo test: Don't re-run tests that already passed #10673

Open
alecmocatta opened this issue May 16, 2022 · 12 comments
Open

cargo test: Don't re-run tests that already passed #10673

alecmocatta opened this issue May 16, 2022 · 12 comments
Labels
C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` Command-test S-blocked-external Status: ❌ blocked on something out of the direct control of the Cargo project, e.g., upstream fix

Comments

@alecmocatta
Copy link

Problem

I have a large workspace in which there's a crate with several long-running property tests. This makes cargo test --workspace take unreasonably long in the common case where those property tests haven't been touched.

Proposed Solution

Cache the test results, so that cargo test --workspace can complete quickly in the common case where long-running tests haven't been touched.

Notes

Related work:

@alecmocatta alecmocatta added the C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` label May 16, 2022
@epage
Copy link
Contributor

epage commented May 16, 2022

I suspect this is more of a libtest concern but there is the issue of cargo running all of the libtest binaries.

@alecmocatta
Copy link
Author

For my use case, the libtest binary is a fine level of granularity to cache the results of. Caching individual #[test]s within a libtest binary seems more fragile?

@weihanglo
Copy link
Member

IIRC, cargo test is not aware of external environment changes, such as environment variables or files. It might be abit risky to cache and skip previously passed tests as cargo cannot 100% sure about what has been changed.

I know that in JavaScript world, a famous test framework jest gets a shiny watch mode that let you re-run failure tests or a portion of filtered tests in the same interactive session. However, even jest re-runs all tests if you re-invoke the command, so I doubt that cargo should skip passed tests across invocations.

Anyway, this is great advice. The field of test framework in Rust is still young. Maybe there are already some similar tools in Rust. Really looking forwards to some external-command doing what jest does :)

@epage
Copy link
Contributor

epage commented May 24, 2022

For other prior art, pytest has

  --lf, --last-failed   rerun only the tests that failed at the last run (or
                        all if none failed)
  --ff, --failed-first  run all tests, but run the last failures first.
                        This may re-order tests and thus lead to repeated
                        fixture setup/teardown.
  --nf, --new-first     run tests from new files first, then the rest of the
                        tests sorted by file mtime

See https://docs.pytest.org/en/7.1.x/reference/reference.html#command-line-flags

Users opt-in to running failed tests so invalidation isn't a concern.

@leighmcculloch
Copy link

cargo test is not aware of external environment changes, such as environment variables or files

Is there a way to give it access to these things?

+1 This feature. In go test test results and output are cached and reads of env vars and files are tracked so that just those that are read affect the cache. It makes a huge difference to testing large or projects and monorepos.

go test caches successful package test results to avoid unnecessary repeated running of tests. When the result of a test can be recovered from the cache, go test will redisplay the previous output instead of running the test binary again...

The rule for a match in the cache is that the run involves the same test binary and the flags on the command line... Tests that open files within the package's source root (usually $GOPATH) or that consult environment variables only match future runs in which the files and environment variables are unchanged.

Ref: https://pkg.go.dev/cmd/go#hdr-Test_packages

@weihanglo
Copy link
Member

Probably kinda a duplicate of #6826. This has got more discussions so close that in favor of this.

I'd say the relationship between libtest and cargo-test is a bit unclear and there is no obvious progress so far. Some experiments (https://github.com/epage/pytest-rs) and well-developed alternative (https://nexte.st/) are out there. You may want to take a look.

@weihanglo weihanglo added the S-blocked-external Status: ❌ blocked on something out of the direct control of the Cargo project, e.g., upstream fix label May 15, 2023
@alecmocatta
Copy link
Author

alecmocatta commented May 15, 2023

Thanks @weihanglo. For reference here's the corresponding issue in Nextest nextest-rs/nextest#174

@casey
Copy link
Contributor

casey commented Dec 25, 2023

One way to support this would to add a flag to cargo test which would save a JSON report of passed and failed tests. This would allow users to write tools which only run the failed tests.

@epage
Copy link
Contributor

epage commented Dec 27, 2023

While T-testing-devex is still establishing a plan, my expectation for how something like this would work: once libtest has stable json output and cargo leverages it for taking on more responsibilities of libtest, third-party test runners would experiment with what can/should be done in this space and as the design space is explored, we can consider what to include within cargo test.

@dnbln
Copy link
Contributor

dnbln commented Apr 22, 2024

For more prior art, I would like to throw in a shameless plug: over the past year I've worked on cargo-difftests, which attempts to tackle the issue of invalidation (although it pretty much always assumes the tests ran successfully). It uses LLVM coverage information to determine which tests have been "touched," although there might be some other alternatives to this approach which I've not tried to explore (yet?).

@extradosages
Copy link

This is a great idea. Strong feature for TDD.

@AlexandreCassagne
Copy link

Does the compiler support tracing which symbols/functions were invalidated?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` Command-test S-blocked-external Status: ❌ blocked on something out of the direct control of the Cargo project, e.g., upstream fix
Projects
Status: No status
Development

No branches or pull requests

9 participants