harness = false
The test
crate is unstable, and likely to be for a while. It’d be good to experiment a bit on crates.io. To support this, Cargo allows specifying in Cargo.toml
:
[[test]]
name = "foo"
harness = false
(Note: when you do this Cargo stops enumerating tests/*.rs
implicitly and you need an explicit [[test]]
section for every test file.)
This causes cargo test
to not rustc --test
when compiling that test file and instead compile it as an executable with a main()
function. Then it’s up to you to test stuff and exit a non-zero status code on failure.
[dependencies] rustc-test = "0.1"
Testing with nothing but main()
and assert!()
is not very nice.
I’ve extracted the test
crate, forked it so that it runs on stable Rust*, and published it at https://crates.io/crates/rustc-test/. Please note that I’m not interested in maintaining or developing a test harness, this is mostly to demonstrate what’s possible today on the stable channel. I’d be happy to give ownership on crates.io if someone is interested.
(* With some caveats: capturing test output and the asm!
implementation of black_box
are behind Cargo features disabled by default since they require unstable features.)
With this, you can create a list of tests with the appropriate structs, call test::test_main()
, and it works just like rustc --test
. This is great for “data driven” tests that are generated dynamically with the same code and different input an expected output (which is not possible to do with rustc --test
today). See html5ever’s tests/tree_builder.rs
for example. But if you have many tests functions, this is not as nice as slapping #[test]
on them.
#[test]
Which leads to the point of this thread. Using an external test harness is possible today, but using #[test]
with it rather then having to enumerate test functions yourself would be nice.
Most of what rustc --test
does is implemented in src/libsyntax/test.rs
. Namely, it generates a module that looks like:
mod __test {
extern crate test (name = "test", vers = "...");
fn main() {
test::test_main_static(&::os::args()[], tests)
}
static tests : &'static [test::TestDescAndFn] = &[
... the list of tests in the crate ...
];
}
So I’d like to (first introduce as unstable and then) stabilize building blocks for external test harnesses:
- A simplified version of
TestDescAndFn
, with just enough to describe whatrustc --test
generates. (So probably without dynamic tests.) - Some way to override which crate/function is used instead of
test::test_main_static
. Maybe#[test_harness] extern crate fancy_test;
? (If benchmark are supported in this mechanism,TestDescAndFn
would probably have to be generic overBencher
.)
Does this sound like it’s worth pursuing?