I have crate-0 that has src/lib.rs
as follows:
#[cfg(test)]
pub mod test_utils {
pub struct OnlyInTests(pub usize);
pub fn helper() -> usize { 999 }
#[test]
fn test_0() { let _ = OnlyInTests(helper()); }
}
I also have crate-1 where I need the testing framework I defined in crate-0:
extern crate crate_0;
#[cfg(test)]
pub mod test_utils {
// This will error out - cannot find mod test_utils in crate_0
use crate_0::test_utils::{OnlyInTests, helper()};
#[test]
fn test_1() { let _ = OnlyInTests(helper()); }
}
The code here is trivial and can be copy-pasted, but in reality I have complex test utilities which I want to use while testing crate-1.
I cannot separate out the test utilities into a different crate as I would get cyclic dependency error: test_utils
would depend on crate-0
create stuff and crate-0
would depend on test_utils
for testing). Nor do I actually want to do this as there are further crates down the line whose testing utilities I would like to use in dependent crates.
Running Tests in Parallel or Consecutively When you run multiple tests, by default they run in parallel using threads, meaning they finish running faster and you get feedback quicker.
The #[cfg(test)] annotation on the tests module tells Rust to compile and run the test code only when you run cargo test , not when you run cargo build .
A primary testing method is Salt Spray testing, which as its name indicates, evaluates how resistant a part or material is to corrosion when exposed to a salt spray for extended periods of time. Effective Salt Spray testing must be performed in a controlled environment, such as a closed salt fog tank.
Two solutions with sightly different trade-offs:
Put your test utilities but not your tests in a new crate crate-0-testutils
.
Make crate-0
dev-depend on crate-0-testutils
; crate-0-testutils
depend on crate-0
; crate-1
dev-depend on crate-0-testutils
and depend on crate-0.
This does not create a circular dependency as the dev-dependencies do not get propagated. Because of the dev-dependency your tests in crate-0 can still use what is in crate-0-testutils.
This at most doubles the number of your lib crates if all your creates had such utilities.
Create a feature in the Cargo.toml
ofcrate-0
that does not depend on anything:
[features]
testing = []
And one in crate-1
that depends on the above:
testing = ["crate-0/testing"]
Then make the first tests on each of the crates fail when the feature is not enabled, to make for an easier to understand error:
#[cfg(all(not(feature = "testing"),test))]
mod testusage {
#[test]
fn panic_without_testing_feature() {
panic!("Please use the feature testing when running tests.\n\nUse: cargo test --features testing\n\n");
}
}
Only compile the utilities when the feature is enabled by adding a guard for it:
#[cfg(feature = "testing")]
fn testing_utility() {
}
This only adds one feature in each crate regardless of how many testing features it depends on but has the downside of needing a special invocation of the tests.
Avoid adding this feature in any crate wide dependency declaration. Including the testing-feature from crate-0
in the dev-dependency of crate-1
where crate-1
also has a normal dependency on crate-0
results in cargo building crate-0
with that feature even for the build target of crate-1
even in release mode.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With