macro_rules! testdir { () => { ... }; ( TestScope ) => { ... }; ( ModuleScope ) => { ... }; ( $e:expr ) => { ... }; }
Expand description
Creates a test directory at the requested scope.
This macro creates a new or re-uses an existing NumberedDir
in the cargo target
directory. It than creates the requested sub-directory within this NumberedDir
.
The path for this directory is returned as a PathBuf
.
For the typical testdir!()
invocation in a test function this would result in
target/testdir-$N/$CARGO_CRATE_NAME/module/path/to/test_function_name1. A symbolic link to the most recent [
NumberedDir] is also created as
target/testdir-current ->
testdir-$N`.
Reuse of the NumberedDir
is triggered when this process is being run as a
subprocess of Cargo, as is typical when running cargo test
. In this case the same
NumberedDir
is re-used between all Cargo sub-processes, which means it is shared
between unittests, integration tests and doctests of the same test run.
The path within the numbered directory is created based on the context and how it is invoked. There are several ways to specify this:
-
Use the scope of the current test function to create a unique and predictable directory:
testdir!(TestScope)
. This is the default when invoked as without any arguments as well:testdir!()
. In this case the directory path will follow the crate name and module path, ending with the test function name. This also works in integration and doctests. -
Use the scope of the current module:
testdir!(ModuleScope)
. In this case the crate name and module path is used, but with an additional finalmod
component. -
Directly provide the path using an expression, e.g.
testdir!("sub/dir"). This expression will be passed to [
NumberedDir::create_subdir] and thus must evaluate to something which implements ``AsRef<Path>``, e.g. a simple
“sub/dir”can be used or something more advanced evaluating to a path, usually [
Path] or [
PathBuf`].
Panics
If there is any problem with creating the directories or cleaning up old ones this will panic.
Examples
Inside a test function you can use the shorthand:
use std::path::PathBuf;
use testdir::testdir;
let path0: PathBuf = testdir!();
This is the same as invoking:
let path1 = testdir!(TestScope);
These constructs can also be used in a doctest.
The module path is valid in any scope, so can be used together with once_cell (or lazy_static) to share a common directory between different tests.
use std::path::PathBuf;
use once_cell::sync::Lazy;
use testdir::testdir;
static TDIR: Lazy<PathBuf> = Lazy::new(|| testdir!(ModuleScope));
#[test]
fn test_module_scope() {
assert!(TDIR.ends_with("mod"));
}