Generic-tests: Parameterize tests with generics and a procedural macro

Announcing release 0.1.0 of generic-tests, a procedural macro crate providing an attribute that allows the test writer to reuse code between test cases or benchmarks that use the same test protocol with different types under test. As in general programming with Rust, this is achieved by using generic parameters and traits. The specific test cases are expanded in multiple submodules with type arguments given in another attribute.

#[generic_tests::define]
mod tests {
    use std::borrow::Cow;
    use std::fmt::Display;

    #[test]
    fn print<S>()
    where
        S: From<&'static str> + Display,
    {
        let s = S::from("Hello, world!");
        println!("{}", s);
    }

    #[instantiate_tests(<String>)]
    mod string {}

    #[instantiate_tests(<&'static str>)]
    mod str_slice {}

    #[instantiate_tests(<Cow<'static, str>>)]
    mod cow {}
}

With const generics available in the nightly compiler, value-based parameterization is also possible through this macro, though obviously limited to const expressions.

Release 0.1.1 is now available.

New features:

  • Support for arbitrary test function attributes provided by other crates.
  • A customizable set of attributes is copied from the generic test function to
    its instantiations.
  • Support for async tests.

Bug fixes:

  • Resolve ambiguity between names local for the macro root module and names local to the instantiation module's parent, which may be different with nested modules.