generate_test_macro 0.1.2

A proc macro for writing test suites as methods on a struct, generating a macro_rules! macro to instantiate each test individually.
Documentation
This crate contains a proc macro for writing a suite of unit tests as methods of an object which can be instantiated via a new macro to run each method as an individual test.

# Example

Consider this test suite in `src/mytrait_tests.rs`:

```rust
pub struct TestSuite<T> {
  // Data needed for each test in the suite.
  param1: usize,
  param2: String,
}

#[generate_test_macro(mytrait_test_suite)]
impl<T: MyTrait> TestSuite<T> {
  fn new(param1: usize, param2: String) -> Self {
    Self { param1, param2 }
  }

  #[test]
  fn my_test(&self) {
    todo!("run a test");
  }
}
```

The expansion of the impl looks like this:

```rust
impl<T: MyTrait> TestSuite<T> {
  #[doc(hidden)]
  pub fn new(param1: usize, param2: String) -> Self {
    Self { param1, param2 }
  }

  #[doc(hidden)]
  pub fn my_test(&self) {
    todo!("run a test");
  }
}

#[macro_export]
macro_rules! mytrait_test_suite {
  ($mod_name:ident, $T:ty, $param1:expr, $param2:expr) => {
    mod $mod_name {
      use super::*;

      #[test]
      fn my_test() {
        TestSuite::<$T>::new($param1, $param2).my_test();
      }
    }
  }
}
```

The `TestSuite` type is referenced without qualification.  The generated module
contains `use super::*;`, so `TestSuite` must be in scope at the site where the
macro is invoked — either because it is defined there, or via an explicit `use`
statement:

```rust
use my_crate::mytrait_tests::TestSuite;
mytrait_test_suite!(my_tests, ConcreteType, 1, "hello".to_string());
```

If the "quickcheck" feature is enabled, quickcheck tests are also supported.  Consider this implementation of `TestSuite<T>`:

```rust
#[generate_test_macro(mytrait_test_suite)]
impl<T: MyTrait> TestSuite<T> {
  #[quickcheck]
  fn test_result_prop(data: MyTestData<T>) -> TestResult {
    todo!("generate a TestResult")
  }

  #[quickcheck]
  fn boolean_prop(data: MyTestData<T>) -> bool {
    todo!("generate a boolean result")
  }
}
```

The expansion looks like this:

```rust
impl<T: MyTrait> TestSuite<T> {
  #[doc(hidden)]
  pub fn test_result_prop(data: MyTestData<T>) -> TestResult {
    todo!("generate a TestResult")
  }

  #[doc(hidden)]
  pub fn boolean_prop(data: MyTestData<T>) -> bool {
    todo!("generate a boolean result")
  }
}

#[macro_export]
macro_rules! mytrait_test_suite {
  ($mod_name:ident, $T:ty) => {
    mod $mod_name {
      use super::*;

      #[test]
      pub fn test_result_prop() {
        quickcheck::quickcheck(TestSuite::<$T>::test_result_prop as fn(_) -> _);
      }


      #[test]
      pub fn boolean_prop() {
        quickcheck::quickcheck(TestSuite::<$T>::boolean_prop as fn(_) -> _);
      }
    }
  }
}
```

Other than a `new` method and methods annotated with `#[test]` or `#[quickcheck]`, all methods are copied as-is to the result.