Implementing quickcheck::Arbitrary only when testing crates



In my (really simplified) project I have two crates: “my-stdlib” and “my-crate”. The “my-stdlib” crate should contain only code which doesn’t depend on anything outside Rust’s stdlib (when doing release build). It contains things like type definitions, helper functions, etc.

I would like to implement quickcheck::Arbitrary for these types in “my-stdlib” so that these implementations are only available when someone somewhere runs “cargo test”. This brings quickcheck dependency to “my-stdlib”, but I has hoping it’s only dev-dependency.

The actual quickcheck properties are then defined in place of actual use, for example in this case it’s “my-crate”.

This is what I have in my-stdlib/src/

#[derive(Clone, Debug, PartialEq)]
pub enum MyEnum {

extern crate quickcheck;

impl quickcheck::Arbitrary for MyEnum {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
        let vals = &[
        g.choose(vals).expect("choose value").clone()

And in my-crate/src/ is the code I try to test with quickcheck:

extern crate my_stdlib;

use my_stdlib::MyEnum;

pub fn from_enum(val: &MyEnum) -> u8 {
    match *val {
        MyEnum::One => 1,
        MyEnum::Two => 2,
        MyEnum::Three => 3,

pub fn to_enum(val: u8) -> MyEnum {
    match val {
        1 => MyEnum::One,
        2 => MyEnum::Two,
        3 => MyEnum::Three,
        _ => panic!("Invalid value"),

extern crate quickcheck;

mod tests {
    use my_stdlib::MyEnum;
    use super::*;

    quickcheck! {
        fn prop_myenum(xs: MyEnum) -> bool {
            xs == to_enum(from_enum(&xs))

The error I get is:

error[E0277]: the trait bound `my_stdlib::MyEnum: quickcheck::Arbitrary` is not satisfied
  --> my-crate/src/
32 | /     quickcheck! {
33 | |         fn prop_myenum(xs: MyEnum) -> bool {
34 | |             xs == to_enum(from_enum(&xs))
35 | |         }
36 | |     }
   | |_____^ the trait `quickcheck::Arbitrary` is not implemented for `my_stdlib::MyEnum`
   = note: required because of the requirements on the impl of `quickcheck::Testable` for `fn(my_stdlib::MyEnum) -> bool`
   = note: required by `quickcheck::quickcheck`
   = note: this error originates in a macro outside of the current crate

Is there some kind of way to achieve this?

Cfg(test) doesn't propagate to external crates
Cargo feature pass through to another crate

We can get close by using a feature: Specifying optional = true in the metadata for a dependency foo produces a feature named foo that the user can enable.

(Actually, I’ve never played around with features before, so I used this post as an excuse to try them out a bit. :smile:)

This will allow user crates to dodge the dependency in the case where the user crate doesn’t need quickcheck at all. However, I don’t see a way to conditionally toggle features, so users that want to use quickcheck during tests will end up also depending on it in regular builds.


name = "dep"
version = "0.1.0"

quickcheck = { version = "0.4.1", optional = true }


pub struct Unit;

#[cfg(feature = "quickcheck")]
extern crate quickcheck;

#[cfg(feature = "quickcheck")]
impl quickcheck::Arbitrary for Unit {
    fn arbitrary<G: quickcheck::Gen>(_: &mut G) -> Unit { Unit }


name = "user"
version = "0.1.0"

dep = { version = "0.1.0", features = ["quickcheck"] }
quickcheck = "0.4.1"


extern crate quickcheck;
extern crate dep;

use quickcheck::Arbitrary;

fn main() {
    // check that the impl exists

fn check_arbitrary<A:Arbitrary>(a: A) {}

(I tried putting dep = { version = "0.1.0", features = ["quickcheck"] } as a dev-dependency and dep = "0.1.0" as a regular dependency, but this simply added the quickcheck feature to the regular dependency)


I think the user can have their own feature with a different name, something like:

quickcheck = { version = "0.4.1", optional = true }

qc = ["quickcheck", "dep/quickcheck"]


Thanks @ExpHP and @cuviper!

Using features I achieved what I wanted. Truly amazing.