Macro test_binary::build_test_binary_once
source · 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.