The test framework and test-specific methods

I have always imagined that when running cargo test, the actual library would be built using the test cfg attribute:

src/lib.rs:

pub fn cat() -> &'static str {
  "meow"
}

#[cfg(test)]
pub fn kitten() -> &'static str {
  "roar"
}

tests/foo.rs

#[test]
fn hello() {
  testtest::cat();
  testtest::kitten();
}

But that assumption is wrong; the foo.rs file doesn't build because it doesn't know about testtest::kitten().

I'm developing a library crate which uses std::time::Instant and certain objects can time out. I want to be able to control the Instant clock deterministically. At first I tried implementing u64 and add a set_time() function to my library. These were gated behind #[cfg(test)]. This was when I noticed this issue, since my set_time() function didn't exist according to the tests.

Assuming others must have needed a deterministic timer for tests I did a little searching and found sn_fake_clock. While it neatly packages what I wanted to do, it still has the same problem: I need to be able to pick FakeClock in the implementation when building tests, and Instant otherwise.

I realize I can use a feature for this, but if I do that I would like a way to control so that when building tests, that feature is always enabled. Is this possible?

Currently my tests use Instant and adds long delays to "guarantee" that things are run in expected order. :grimacing:

Dependencies in the dev-dependencies Cargo.toml section will be linked in when compiling tests. Currently, any features specified there will be unified with those in the regular dependencies section, but I believe that the v2 Cargo resolver (coming soon) will resolve this issue.

#[cfg(test)] is for tests included in library itself. For external tests, it is compiled in exactly the same way as for any other consumer.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.