#[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.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.