Reading about dead code problems in tests, multiple people pointed to this blog post.
The issue is, cargo compiles a single binary for each test suite. When you try to share code across suites, the checking is done at a per-suite level.
For example, you have:
commons/mod.rs
one.rs
two.rs
pub fn shared_fn() {}
If only one.rs uses shared_fn(), cargo test will complain that it's unused, because it's not used in all created binaries.
Moving all the test modules into a integrations/main.rs forces a single binary to be compiled, which has the same type of dead code checking as a regular application.
I also did some timing tests to make sure it didn't make anything slower. This was done running only the mobile_verifier workspace. time was used to get timing for cargo test, the built in timer was used for cargo nextest.
Running tests back to back, the first pass tended to be the faster by about 10 seconds. So take some of these numbers with a grain of salt. Also running on a 2.3 GHz 8-Core Intel Core i9.
time cargo test --quiet --package mobile-verifier -- --test-threads 1
time cargo test --quiet --package mobile-verifier -- --test-threads 1 --include-ignored
time cargo test --quiet --package mobile-verifier
time cargo test --quiet --package mobile-verifier -- --include-ignored
# ---
cargo nextest run -E 'package(mobile-verifier)' -j 1
cargo nextest run -E 'package(mobile-verifier)' -j 1 --run-ignored all
cargo nextest run -E 'package(mobile-verifier)'
cargo nextest run -E 'package(mobile-verifier)' --run-ignored all
the reproducibility of the test timing is finicky at best, but the tests do not get slow to the point where I feel it outweighs the benefits we can get from changing to this testing structure.
The main benefit being more reliable code re-use in our tests, and not needing to mark #[allow(dead_code)] for shared functions that are not used in every test suite.
Reading about dead code problems in tests, multiple people pointed to this blog post.
The issue is, cargo compiles a single binary for each test suite. When you try to share code across suites, the checking is done at a per-suite level.
For example, you have:
If only one.rs uses
shared_fn()
, cargo test will complain that it's unused, because it's not used in all created binaries.Moving all the test modules into a
integrations/main.rs
forces a single binary to be compiled, which has the same type of dead code checking as a regular application.I also did some timing tests to make sure it didn't make anything slower. This was done running only the
mobile_verifier
workspace.time
was used to get timing forcargo test
, the built in timer was used forcargo nextest
.Running tests back to back, the first pass tended to be the faster by about 10 seconds. So take some of these numbers with a grain of salt. Also running on a
2.3 GHz 8-Core Intel Core i9
.Thoughts
the reproducibility of the test timing is finicky at best, but the tests do not get slow to the point where I feel it outweighs the benefits we can get from changing to this testing structure.
The main benefit being more reliable code re-use in our tests, and not needing to mark
#[allow(dead_code)]
for shared functions that are not used in every test suite.