25

I have the following code defining a path where generated files can be placed:

fn gen_test_dir() -> tempdir::TempDir {                                        
    tempdir::TempDir::new_in(Path::new("/tmp"), "filesyncer-tests").unwrap()   
} 

This function is defined in tests/lib.rs, used in the tests in that file and I would also like to use it in the unit tests located in src/lib.rs.

Is this possible to achieve without compiling the utility functions into the non-test binary and without duplicating code?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
PureW
  • 4,568
  • 3
  • 19
  • 27
  • Can't you move that funcionality into `src/lib.rs` and then use it in `tests/lib.rs`? – Daniel Fath Jun 23 '16 at 15:00
  • @DanielFath I tried this and annotated with `#[test]` to avoid compiling into release-binary and received this error: "functions used as tests must have signature fn() -> ()" – PureW Jun 23 '16 at 15:16
  • Can you try putting `#cfg(not(test))` that will remove your code, during non-test phases. – Daniel Fath Jun 23 '16 at 15:23
  • I think you mean `#[cfg(test)]`. I tend to have a `#[cfg(test)] mod tests` in my lib.rs (or submodules), into which I put all the unit test functions and any utilities they need. – Chris Emerson Jun 23 '16 at 15:36
  • @ChrisEmerson Ahh this seems to work. If you put it in an answer, I can mark it. – PureW Jun 23 '16 at 15:54

2 Answers2

18

You can import from your #[cfg(test)] modules from other #[cfg(test)] modules, so, for example, in main.rs or in some other module, you can do something like:

#[cfg(test)]
pub mod test_util {
    pub fn return_two() -> usize { 2 }
}

and then from anywhere else in your project:

#[cfg(test)]
mod test {
    use crate::test_util::return_two;

    #[test]
    fn test_return_two() {
        assert_eq!(return_two(), 2);
    }
}

MPlanchard
  • 1,798
  • 1
  • 16
  • 13
  • [Test mode](https://doc.rust-lang.org/reference/attributes/testing.html#the-test-attribute) (the rustc --test flag) also seems to be enabled for benches. It doesn't seem to be enabled for [honggfuzz-rs](https://github.com/rust-fuzz/honggfuzz-rs) targets however. – Tobu Apr 03 '20 at 18:18
  • 1
    for some reason this just doesnt work for me – ditoslav Dec 07 '20 at 17:49
11

What I do is put my unit tests with any other utilities into a submodule protected with #[cfg(test)]:

#[cfg(test)]
mod tests {  // The contents could be a separate file if it helps organisation
    // Not a test, but available to tests.
    fn some_utility(s: String) -> u32 {
        ...
    }

    #[test]
    fn test_foo() {
        assert_eq!(...);
    }
    // more tests
}
Chris Emerson
  • 13,041
  • 3
  • 44
  • 66
  • 6
    What about integration tests? I need to integrate with a database, but I don't want to have to create a dependency just for tests. Integration tests work well for my problem up until I need to reuse utility functions. I guess I'll go and create a testutil crate... – weberc2 Aug 07 '17 at 23:38