Within Rusts build-tool cargo
, I can define a function for a test-case simply this way:
#[test]
fn test_something() {
assert_eq!(true, true);
}
Running with cargo test
outputs:
Running unittests src/lib.rs (target/debug/deps/example-14178b7a1a1c9c8c)
running 1 test
test test::test_something ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
So far, so good. Now I have the special case, that test cases in my project are defined in files. They can be executed using a special testcase()
function that performs all steps to run the test, and do specific assert_eq!()
calls.
Now I want to achieve the following:
- Read all files from a
tests/
folder - Run
testcase()
on every file - Have every file as a single test case in
cargo test
Latter one is the problem. This is the function (as test) to run all tests from the folder using the testcase()
-function.
#[test]
// Run all tests in the tests/-folder
fn tests() {
let cases = std::fs::read_dir("tests").unwrap();
for case in cases {
testcase(case.unwrap().path().to_str().unwrap());
}
}
A run of cargo test
should print the following, given the testcases a.test
, b.test
and c.test
:
Running unittests src/lib.rs (target/debug/deps/example-14178b7a1a1c9c8c)
running 3 test
test test::tests::tests/a.test ... ok
test test::tests::tests/b.test ... ok
test test::tests::tests/c.test ... ok
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Is this somehow possible?
CodePudding user response:
With Rust's built-in test harness, there is no way to declare a single test case other than with the #[test]
attribute. In order to get the result you want, you would need to write a proc-macro which reads your directory of tests and generates a #[test]
function for each one.
Instead, it will probably be more practical to write a test which uses your own harness code. In your Cargo.toml
, define a test target with it disabled:
[[test]]
name = "lang_tests"
harness = false
Then in tests/lang_tests.rs
(the tests/
directory goes next to src/
and is already known to Cargo), write a program with an ordinary main()
that runs tests:
fn main() {
let cases = std::fs::read_dir("tests").unwrap();
let mut passed = 0;
let mut failed = 0;
for case in cases {
if testcase(case.unwrap().path().to_str().unwrap()) {
eprintln!("...");
passed = 1;
} else {
eprintln!("...");
failed = 1;
}
}
eprintln!("{passed} passed, {failed} failed");
if failed > 0 {
std::process::exit(1);
}
}
Of course there's a bunch of further details to implement here — but I hope this illustrates how to write a custom test harness that does the thing you want to do. Again, you cannot do it with the default test harness except by using macro-generated code, which is probably not worthwhile in this case.