Macro testdir::testdir

source ·
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 final mod 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"));
}