Sharing (derivable) test artefacts between crates

Hi! How, in general, do I share test-only artifacts derived from the production enum/structs between crates in the same workspace? I realise Rust doesn't export test code between crates, so how do I work around this?

I have a model crate which some non-trivial core domain structs which are used by many other crates in the same workspace.

These structs implement, via #derive, the arbitrary - Rust trait and I want to share those derived implementations of the Arbitrary trait with other crates, but only for testing.

So, for example, I really want crate model to look like:

#[cfg(test)] use proptest::prelude::*;
#[cfg(test)] use proptest::prop_oneof;
#[cfg(test)] use proptest_derive::Arbitrary;

pub type UserId = usize;

#[derive(Debug)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct LoginDetail {
    pub user_id: UserId,
}

and then in another crate:


// THIS WORKS FINE, as expected
fn some_production_code() {
  let s = model::LoginDetail { user_id: 10};
  // ....
}

// THIS FAILS TO COMPILE, as it claims `LoginDetail` doesn't implement `Arbitrary`
proptest! {
    #[test]
    fn doesnt_crash(c in any::<model::LoginDetail>()) { 
       let mut sut = sut();
       let result = sut.execute(c); 
       // ....
    }
}

Unfortunately, the proptest! code can't see any of the test code in the model crate. If I get rid of the cfg(test) qualifiers in the model crate then everything works as expected.

I'm sure Rust, like (almost?) every other language doesn't export test artefacts, so what do I do :-). "Remove the test qualifiers and stop being so anal" is a perfectly acceptable answer ;-).

Thanks!

There is no way to have code which is conditionally compiled only when it is a dependency of a crate being tested. (cfg(test) means "when compiling the tests declared in this crate" only.) The closest you can get is

#[cfg_attr(
    any(feature = "arbitrary", test),
    derive(Arbitrary)
)]

and then write tests either in the same crate, or in a package dedicated to tests which depends on the arbitrary features of the packages it is testing. (Note that this is the exact same dependency structure you have if you're using arbitrary with cargo fuzz.)

1 Like

(thanks @kpreid)

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.