macro_rules! build_test_binary_once {
    ($name:ident, $tests_dir:expr) => { ... };
}
Expand description

Generate a singleton function to save invoking Cargo multiple times for the same binary.

This is useful when you have many integration tests that use the one test binary, and don’t want to invoke Cargo over and over for each one. Note that Cargo itself implements both locking and caching at the filesystem level, so all this macro will save you is the overhead of spawning the Cargo process to do its checks. That may still be appreciable for high numbers of tests or on slow systems.

Calling build_test_binary_once!(binary_name, "tests_dir") (no quotes on binary_name) will generate a function path_to_binary_name() that returns the path of the built test binary as an OsString, just like build_test_binary("binary_name", "tests_dir") would. Unlike build_test_binary(), the generated function will only build the binary once, and only on the first call. Subsequent calls will use a cached path and assume the initial build is still valid. The generated function unwraps the result internally and will panic on build errors.

For example, if you use build_test_binary_once!(my_test, "testbins") in tests/common/mod.rs, that module will then contain a function path_to_my_test() -> std::ffi::OsString. Multiple integration tests can then use common::path_to_my_test() to obtain the path. Cargo will only be run once for this binary, even if the integration tests that use it are being run in multiple threads.

Note

That this means the binary name must be a valid identifier eg. not have dashes in it.

// Build a test binary named "multiple".
build_test_binary_once!(multiple, "testbins");

// The first test that gets run will cause the binary "multiple" to be built
// and the path will be cached inside the `path_to_multiple()` function.

let test_bin_path = path_to_multiple();
assert!(std::process::Command::new(test_bin_path)
    .status()
    .expect("Error running test binary")
    .success());

// Subsequent tests will just get the cached path without spawning Cargo
// again.

let test_bin_path_again = path_to_multiple();
assert!(std::process::Command::new(test_bin_path_again)
    .status()
    .expect("Error running test binary")
    .success());

If you need to use extra features or a non-default profile, you will need to go back to using the builder.