Expand description
§ Test harness for macro expansion.
Similar to trybuild, but allows you to write tests on how macros are expanded.
Minimal Supported Rust Version: 1.34.0
§Macro expansion tests
A minimal duplicate_macrotest setup looks like this:
#[test]
pub fn pass() {
duplicate_macrotest::expand("tests/expand/*.rs");
// Alternatively,
duplicate_macrotest::expand_without_refresh("tests/expand/*.rs");
}The test can be run with cargo test. This test will invoke the cargo expand command
on each of the source files that matches the glob pattern and will compare the expansion result
with the corresponding *.expanded.rs file.
If a *.expanded.rs file doesn’t exists and it’s not explicitly expected to (see expand_without_refresh),
it will be created (this is how you update your tests).
Possible test outcomes are:
- Pass: expansion succeeded and the result is the same as in the
.expanded.rsfile - Fail: expansion was different from the
.expanded.rsfile content - Refresh:
.expanded.rsdidn’t exist and has been created - Refresh-fail:
.expanded.rsis expected to be present, but not exists. Seeexpand_without_refresh.
Note: when working with multiple expansion test files, it is recommended to
specify wildcard (*.rs) instead of doing a multiple calls to expand functions for individual files.
Usage of wildcards for multiple files will group them under a single temporary crate for which
dependencies will be built a single time. In contrast, calling expand functions for each
source file will create multiple temporary crates and that will reduce performance as depdendencies
will be build for each of the temporary crates.
§Passing additional arguments to cargo expand
It’s possible to specify additional arguments for cargo expand command.
In order to do so, use the following functions with _args suffix:
Example:
pub fn pass() {
duplicate_macrotest::expand_args("tests/expand/*.rs", &["--features", "my-feature"]);
// Or
duplicate_macrotest::expand_without_refresh_args("tests/expand/*.rs", &["--features", "my-feature"]);
}The _args functions will result in the following cargo expand command being run:
cargo expand --bin <test-name> --theme none --features my-feature§Workflow
First of all, the cargo expand tool must be present. You can install it via cargo:
cargo install cargo-expandA nightly compiler is required for this tool to work, so it must be installed as well.
cargo-expand uses rustfmt to format expanded code.
It’s highly recommended to install it since the examples in the test-project/ and
test-procmacro-project/ folders are using a formatted version of the expanded code
to compare with.
§Setting up a test project
In your crate that provides procedural or declarative macros, under the tests directory,
create an expand directory and populate it with different expansion test cases as
rust source files.
Then create a tests.rs file that will run the tests:
#[test]
pub fn pass() {
duplicate_macrotest::expand("tests/expand/*.rs");
// Or:
duplicate_macrotest::expand_without_refresh("tests/expand/*.rs");
}And then you can run cargo test, which will
- Expand macros in source files that match glob pattern
- In case if
expandfunction is used:- On the first run, generate the
*.expanded.rsfiles for each of the test cases under theexpanddirectory - On subsequent runs, compare test cases’ expansion result with the
content of the respective
*.expanded.rsfiles
- On the first run, generate the
- In case if
expand_without_refreshis used:- On each run, it will compare test cases’ expansion result with the content of the
respective
*.expanded.rsfiles. - If one or more
*.expanded.rsfiles is not found, the test will fail.
- On each run, it will compare test cases’ expansion result with the content of the
respective
§Updating .expanded.rs
This applicable only to tests that are using expand or expand_args function.
Run tests with the environment variable MACROTEST=overwrite or remove the *.expanded.rs
files and re-run the corresponding tests. Files will be created automatically; hand-writing
them is not recommended.
Functions§
- expand
- Attempts to expand macros in files that match glob pattern.
- expand_
args - Same as
expandbut allows to pass additional arguments tocargo-expand. - expand_
args_ fail - Same as
expand_failbut allows to pass additional arguments tocargo-expand. - expand_
fail - Attempts to expand macros in files that match glob pattern and expects the expansion to fail.
- expand_
without_ refresh - Attempts to expand macros in files that match glob pattern.
More strict version of
expandfunction. - expand_
without_ refresh_ args - Same as
expand_without_refreshbut allows to pass additional arguments tocargo-expand. - expand_
without_ refresh_ args_ fail - Same as
expand_without_refresh_failbut allows to pass additional arguments tocargo-expandand expects a failure. - expand_
without_ refresh_ fail - Attempts to expand macros in files that match glob pattern and expects a failure.
More strict version of
expand_failfunction.