rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.5k stars 2.37k forks source link

make code compiled with cfg(test) visible across crates #8379

Open toxeus opened 4 years ago

toxeus commented 4 years ago

I find myself creating test helpers/mocks in my test modules that are marked with #[cfg(test)]. They are exported as pub and can conveniently be used throughout the crate. These helpers are not visible from other crates nor from integration tests in particular.

Making code compiled with cfg(test) be visible outside of the scope of a crate would allow for better code reuse. Please consider adapting that behavior.

Related: https://github.com/rust-lang/rust/issues/45599

TomzBench commented 3 years ago

I have a util crate that exports some mocks. Real code imports a real routine from the crate and test code imports a mock routine from the crate. However this does not work!

Is there a way to implement this or do I have to stuff everything with a mock in the same crate?

As work around I declare the mock in the crate that needs the mock, but then I have to duplicate this mock in every crate :(

oldgalileo commented 2 years ago

As work around I declare the mock in the crate that needs the mock, but then I have to duplicate this mock in every crate :(

Did you ever come up with or find a more ergonomic solution to this? After running into this, I've been very surprised at this being a largely unresolved issue. It seems like it would be more of a common practice to, for example, provide a once_cell::sync::Lazy initialization of cool_library::InterestingStruct which has private fields so that you don't need to compromise good visibility hygiene for testability.

So far, I've seen suggestions for mock crates, or a "testing" feature-flag with #[cfg(not(testing))] -> panicking. These seem like hacks.

oeed commented 1 year ago

While this would be nice to have, you can replicate this in a less nice way using crate features. On your utils crate, add a feature, e.g. test-utils, tag modules with #[cfg(feature = "test-utils")] and then on your consumer crate add:

[dev-dependencies]
my-crate = {path = "../my-crate", features = ["test-utils"]}
simsekgokhan commented 1 year ago

Also facing this problem, thx for the "feature" workaround. This is how I used the workaround if anybody needs: https://github.com/OLSF/libra/commit/6106c0730b9953cb8021b5dfc33f9e48cf578a34, look for "ol-smoke-test".

ryoqun commented 1 year ago

While this would be nice to have, you can replicate this in a less nice way using crate features. On your utils crate, add a feature, e.g. test-utils, tag modules with #[cfg(feature = "test-utils")] and then on your consumer crate add:

[dev-dependencies]
my-crate = {path = "../my-crate", features = ["test-utils"]}

I'm seriously thinking about coping with the limitation described in the issue... @oeed this work around looks nice but i think it's affected by cargo's feature unification, right? in my testing, it seems that other member crates of my workspace are seeing #[cfg(feature = "test-utils")] -ed code even without proper dev-dependencies and narrowing down cargo check with -p foo actually causes expected compile errors...

jaques-sam commented 7 months ago

While this would be nice to have, you can replicate this in a less nice way using crate features. On your utils crate, add a feature, e.g. test-utils, tag modules with #[cfg(feature = "test-utils")] and then on your consumer crate add:

[dev-dependencies]
my-crate = {path = "../my-crate", features = ["test-utils"]}

How to enable the feature for a integration test?

ryoqun commented 1 month ago

While this would be nice to have, you can replicate this in a less nice way using crate features. On your utils crate, add a feature, e.g. test-utils, tag modules with #[cfg(feature = "test-utils")] and then on your consumer crate add:

[dev-dependencies]
my-crate = {path = "../my-crate", features = ["test-utils"]}

I'm seriously thinking about coping with the limitation described in the issue... @oeed this work around looks nice but i think it's affected by cargo's feature unification, right? in my testing, it seems that other member crates of my workspace are seeing #[cfg(feature = "test-utils")] -ed code even without proper dev-dependencies and narrowing down cargo check with -p foo actually causes expected compile errors...

FYI, I implemented this with the quoted concern being addressed. If interested, please look for dev-context-only-utils at https://github.com/anza-xyz/agave

It seems dev-context-only-utils is working as expected over 1 year at the moderate cost of increased CI to detect any misuse of the special feature.

Note that I recently encountered a minor problem: https://github.com/rust-lang/cargo/issues/10958, see extended explanation as well: https://github.com/rust-lang/cargo/issues/10958#issuecomment-2201839222

In near (?) future, I'm going to publish cargo-dcou or something for ease of use...