Sharing code (and macros) in tests directory


#1

After playing around with adding a test trait implementation in one file tests/test_impl.rs, and then using that implementation from within either tests/lib.rs or another file in tests, it appears that this does not work the way I’d expect. The tests use a macro defined in src. If everything is in one file and I do the following #[macro_use] extern crate fsm; the macros are loaded and work correctly.

But if I put the code that uses the macros into the tests/test_impl.rs and #[macro_use] extern crate fsm; in tests/lib.rs the macros are not found in test_impl.rs. If I add the same #[macro_use] extern crate fsm; to test_impl.rs the macros are found, but I can’t do this if I properly include the module in lib.rs with mod test_impl; as the extern can’t be used in a module that isn’t the root of the crate.

Using cargo test --verbose it appears that each file is turned into it’s own binary, and that sharing code in the tests directory is not supported. I believe there are only two options here:

  1. Put shared test code in /src
  2. Add shared code with a non .rs extension and use the include! macro.

Has anyone had this problem before and are there any suggestions about the proper way to handle this? It seems like what should be a very common integration test use case using mock implementations, although I haven’t seen it done in any crates I explored on crates.io.

Thanks,
Andrew


How to use external crate in Cargo integration tests?
#2

Are you using #[macro_use] mod test_impl; in tests/lib.rs? Note that, yes, each .rs file in tests gets compiled as a new test (so you don’t have a tests library, if that’s what you think tests/lib.rs is doing).

What I do with this is put the shared code in a utils module and import it using #[path="utils/mod.rs"] mod utils;.

So to be clear, you add that line to any test file tests/*.rs, which imports tests/utils/mod.rs as the module utils. Add a #[macro_use] if it contains macros you want to access.


#3

What I do with this is put the shared code in a utils module and import it using #[path=“utils/mod.rs”] mod utils;.

I do the same, but the #[path="..."] is unnecessary since utils/mod.rs is one of the paths Rust checks by default.


#4

You’re right. I vaguely recall there was a reason I did it that way… but I don’t remember what it was. Might not have been the same path.

This is annoying me; if only I could remember which project I used that with…


#5

T’hank you so much @DanielKeep and @mbrubeck! It works like a charm. Rust community ftw again.