Background
I am writing integration tests using the guidelines in the Rust Book. A requirement is to be able to run setup and teardown code at two levels:
- Test level: Before and after each test.
- Crate level: Before and after all tests in the crate.
The basic idea is as follows:
- I wrote a TestRunner class.
- Each integration test file (crate) declares a lazy-static singleton instance.
- Each
#[test]
annotated method passes a test function to arun_test()
method of the TestRunner. - With this design it is straightforward to implement Test level setup and teardown. The
run_test()
method handles that. - It is also no problem to implement the setup part of the Crate level, because the TestRunner knows when
run_test()
is called for the first time.
The Problem
The remaining problem is how to get the TestRunner to execute the Crate level teardown after the last test has run. As tests may run in any order (or even in parallel), the TestRunner cannot know when it is running the last test.
What I Have Tried
I used the ctor crate and the #[dtor]
annotation to mark a function as one that will run before the process ends. This function calls the Crate level teardown function.
This is an unsatisfactory solution because of this issue which documents the limitations of what can be done in a dtor function.
A Step in the Right Direction
I propose to pass a test_count argument to the TestRunner's constructor function. As the TestRunner now knows how many test functions there are, it can call the Crate level teardown function after the last one completes. (there are some thread safety issues to handle, but they are manageable).
The Missing Link
Clearly, the above approach is error prone as it depends on the developer updating the test_count argument every time she adds or removes a test or marks one as ignored.
The Remaining Problem
I would therefore like to be able to detect the number of tests in the crate at compile time without any manual intervention by the developer.
I am not familiar enough with Rust macros to write such a macro myself, but I assume it is possible.
Maybe it is even possible to use the test crate object model for this (See https://doc.rust-lang.org/test/struct.TestDesc.html)
Can anyone suggest a clean way to detect (at compile time) the number of tests that will run in the crate so I can pass it to the constructor of the TestRunner?