test-harness 0.3.0

a little test macro to wrap your tests with an arbitrary setup/teardown function
Documentation
# test-harness

this proc macro wraps your tests with any function that accepts a
function with your test's signature. Your test function can accept any
number of arguments and return anything, as long as you call it with
the correct arguments in the harness.

## Example
```rust
use test_harness::test;

fn my_test_harness(test: impl FnOnce(String)) {
    let string = std::iter::repeat_with(fastrand::alphanumeric).take(10).collect();
    test(string)
}

#[test(harness = my_test_harness)]
fn my_test(random_string: String) {
    assert_eq!(string.len(), 10);
}
```


This expands to the following, with no further macro magic

```rust
fn my_test_harness<F>(test: impl FnOnce(String)) {
    let string = std::iter::repeat_with(fastrand::alphanumeric).take(10).collect();
    test(string)
}

#[test]
fn my_test() -> impl std::process::Termination {
    fn my_test(random_string: String) -> Result<(), &'static str> {
        assert_eq!(string.len(), 10);
        Ok(())
    }
    my_test_harness(my_test)
}
```

## Returning Result
```rust
use test_harness::test;

fn my_test_harness<F>(test: F) -> Result<(), &'static str>
where F: FnOnce(String) -> Result<(), &'static str> {
    let string = std::iter::repeat_with(fastrand::alphanumeric).take(10).collect();
    test(string)
}

#[test(harness = my_test_harness)]
fn my_test(random_string: String) -> Result<(), &'static str> {
    assert_eq!(string.len(), 10);
    Ok(())
}
```


This expands to the following, with no further macro magic

```rust
fn my_test_harness<F>(test: F) -> Result<(), &'static str>
where F: FnOnce(String) -> Result<(), &'static str> {
    let string = std::iter::repeat_with(fastrand::alphanumeric).take(10).collect();
    test(string)
}

#[test]
fn my_test() -> impl std::process::Termination {
    fn my_test(random_string: String) -> Result<(), &'static str> {
        assert_eq!(string.len(), 10);
        Ok(())
    }
    my_test_harness(my_test)
}
```


## Async example

You can use this to set up an async runtime and spawn or block on the test.

```rust
use test_harness::test;

mod my_mod {
    pub fn set_up<F, Fut>(test: F) -> Result<(), Box<dyn std::error::Error>>
    where
        F: FnOnce(&'static str) -> Fut,
        Fut: std::future::Future<Output = Result<(), Box<dyn std::error::Error>>> + Send + 'static,
    {
        futures_lite::future::block_on(test("hello"))
    }
}

#[test(harness = my_mod::set_up)]
async fn my_test(s: &'static str) -> Result<(), Box<dyn std::error::Error>> {
    assert_eq!(s, "hello");
    Ok(())
}
```


## Eliding harness name

If you name your harness `harness`, you can elide the harness name, like so:

```rust
use test_harness::test;

pub fn harness<F, Fut, Out>(test: F) -> Out
where
    F: FnOnce(&'static str) -> Fut,
    Fut: std::future::Future<Output = Out> + Send + 'static,
    Out: std::process::Termination
{
    futures_lite::future::block_on(test("hello"))
}


#[test(harness)]
async fn test_one(s: &'static str) -> Result<(), Box<dyn std::error::Error>> {
    assert_eq!(s, "hello");
    Ok(())
}

#[test(harness)]
async fn test_two(s: &'static str) {
    assert_eq!(s, "hello");
}

```




## Drop down to standard #[test]

If this macro is used without any additional arguments, it works identically to the built-in `#[test]` macro.

```rust
use test_harness::test;
#[test]
fn normal_test() {
    assert!(true);
}
```