So instead of tests that look like the code below, you'd replace the let tests
with something that either parses a file or is generated from a macro (with a file as macro parameter). Is that what you mean?
#[test]
fn test() {
let tests = vec![
( /* parameters test */, /* expected result */),
( /* parameters test */, /* expected result */),
( /* parameters test */, /* expected result */),
];
for (index, (parameter1, ..., expected_result)) in tests.into_iter().enumerate() {
// performs test
assert_eq!(result, expected_result, "message");
}
}
I'd say it depends on the formats you're dealing with and the easiness to write the data in a text file vs Rust code. Another possibility is to use declarative macros to write the data in the tests
array (or whatever other collection you want to use) using a "human-readable" format—I find that those are often useful to instantiate specific values in the code itself.
The advantage of the code approach is that your input format is verified, that everything is at the same place, and that there is no extra file to create and take care of. It may also be quicker than reading so many files in parallel threads, depending on their size (I assume it's not a factor here). Then you have to create a parser for each type of file.
The advantage of files is the possibility to use them with other tools (again, that depends on what those files and formats are), and possibly an easier-to-read format (though if you need to write the parser for those data, I'd argue you can put the easy-to-read format in your test code).
EDIT: To answer the question below: you only have to launch the test from a function with the attribute #[test]
. If your input is in a file, that function will have to call code to read the file and do whatever test you must do with the data parsed from the file. It will be launched on every cargo test
, so no problem there. If part of that code is a macro, declarative or procedural, it will be executed each time.