Cargo: mini-libraries for test-suites?


#1

So, I have some library I’m working on in Cargo. This needs tests. Example programs. Unit tests for various details. Integrative tests running the whole thing. Cargo has options for handling all this; great.

But it turns out the tests aren’t so simple; some set-up code is needed for some of the examples and integration tests and should be shared. This isn’t code an end user would want, but code to tailor the library to some hypothetical (and fairly pointless) use.

How can code be shared within a Cargo library project without being in the library? My only thoughts at the moment are (a) as a configuration within the main library (#[cfg(lib_test_suite)]), (b) as a separate Cargo project or © copy+paste. All three have their disadvantages. Thoughts?


#2

Unit tests: write your helper functions and have them under the scope of a #[cfg(test)] conditional compilation directive, so that they’ll only be used when the test harness is being built. (The usual recommendation is to apply this at the module level, but it works for functions as well).

Examples and integration tests are intended to represent things your downstream crates might do. Your downstream crates will often want to have tests of their own, so if there are functions which are useful for testing things that use your crate, they might actually belong in the public API?


#3

sorear: doesn’t help, thanks. It’s not so much general test stuff or general user stuff as specific examples that are useful in various tests.

Any other thoughts? I don’t really want a different configuration of the library just to include some specific examples (too specific to be widely useful).


#4

I found another option which would almost work. But I don’t believe there’s a way of telling Cargo a certain feature is required by integration tests and examples?

# in Cargo.toml
[features]
# A feature which includes some example applications of the library
example-appls = []
// in lib.rs
#[cfg(feature = "example-appls")]
pub mod ex_appls {
    ...
}

This still results in two different configuratons of the main lib instead of a separate lib, however.