Cargo Test Expected Macro Use

Hello!

I'm working on a project involving integration tests in a separate directory from the production code, but all the code is in the same overall package. I'm running into an issue with cargo test and am curious if its expected output or not.

Here's an outline of what I'm trying to do:

My file structure is:

example
| - src
    | - methods
        | - method.rs
        | - mod.rs
    | - lib.rs
    | - main.rs
| - test
    | - main_test.rs
| - Cargo.toml

In main_test.rs I'm attempting to call a function in method.rs and the function has a cfg! macro in order to determine which output to print (either test or prod):
Code in method.rs

fn method_test() -> i32 {
    if cfg!(test) {
        println!("test");
        0
    } else {
        println!("prod");
        1
    }
}

Code in main_test.rs

#[cfg(test)]
mod test_try {
	use example::methods::method;

	#[test]
	fn try_main() {
		assert_eq!(method::method_test(), 0); // this test fails every time
	}
}

When I run cargo run the code prints prod. When I run cargo test, main_test calls the function and it prints prod. Is this expected because of the different directories being compiled separately at compile time or is there something I'm doing wrong? Thanks for any feedback you can provide.

When you run cargo test, the following things are built:

  • The library example. (lib.rs)
  • A test harness for unit tests in the library. (lib.rs with --cfg test)
  • The binary example. (main.rs)
  • A test harness for unit tests in the binary. (main.rs with --cfg test)
  • A test harness for integration tests in main_test.rs. (with --cfg test)

and then it runs all three test harnesses. All three of the last items (the things that aren't built from lib.rs) link to the library that was built without --cfg test. After all, the purpose of --cfg test is to enable and disable the generation of unit tests. The unit tests from lib.rs were already compiled into a binary; there's no reason why of these downstream build artefacts should need them.

I would advise against using cfg(test) for any other purpose. If you want to alter the behavior of something in a test, I would suggest adding a feature:

[features]
something = []

[[test]]
name = "main_test"
path = "test/main_test.rs"
required-features = ["something"]

Hi ExpHP

Thanks so much for taking the time to explain all of that! Didn't know a whole lot about features as a cargo option, but feel that it makes a lot of sense in the case that I'm using it.