#[macro_export] and #[cfg(test)]

I have a crate which defines a macro_rules! macro that depends on a dev-dependency (it's used for testing) and therefore its definition is hidden behind a #[cfg(test)].

I would like to be able to use this macro in a test (hence also behind #[cfg(test)]) in a client crate. However I get the error could not find my_macro in the root. Removing the #[cfg(test)] from the macro definition makes it visible in the other cate.

Is it possible to export a macro defined behind #[cfg(test)] to another crate?

1 Like

Anything conditional on #[cfg(test)] is never visible outside the crate. This is the case for all kinds of items, not just macros. There are two mutually exclusive situations:

  • Your crate is being built in the normal fashion as a library, and the configuration predicate test is false.
  • rustc was invoked with --test; cfg(test) is true, and your crate is built as a binary with the test harness embedded, not as a library.

In general, #[cfg(test)] is strictly a tool for use with the #[test] tests of a particular crate (often loosely called “unit tests”) — as soon as you want a test helper to be usable by multiple crates, you cannot use #[cfg(test)] for the purpose.

2 Likes

I guess they could be called --lib tests, since those are the tests run when using cargo test --lib. I think they do deserve a special mention not to be mistaken with "integration tests" / test/-located / --test tests, nor doctests, since these, on the other hand, shall treat the related library as an external crate, which is thence compiled without --cfg test.

So the answer is no, as @kpreid explained, but in some cases it is thus idiomatic to have an integration-tests Cargo feature with which to cfg-gate stuff (such as your macro_export), so that other tests down the line that dev-depend on your library can enable that feature, while normal users won't be polluted with the items defined therein :slightly_smiling_face:

1 Like

Just to be precise: my parenthetical objection was equally to calling those tests integration tests. "Unit tests" and "integration tests" are purposes a test can have, and test targets vs. #[test] are an implementation strategy which may often better suit one type of test or another, but does not fundamentally determine what its purpose is.