glasses 0.1.1

Macros for writing lots of tests (or specs!)
Documentation
pub trait Harness {
    type Builder;
    fn new_builder() -> Self::Builder;
    fn run_test(case: Self::Builder);
}

#[macro_export]
macro_rules! glasses_make_case_helper {
    ($harness_name: ty, $acc: expr) => {{
        use $crate::Harness;
        let case = <$harness_name>::new_builder();
        ($acc)(case)
    }};
    ($harness_name: ty, $acc: expr, $head_mod: ident $($head_arg: expr)* $(, $mod: ident $($arg: expr)*)*) => {{
        $crate::glasses_make_case_helper!(
            $harness_name,
            |case: <$harness_name as Harness>::Builder | $acc(case).$head_mod($($head_arg , )*)
            $(, $mod $( $arg )* )*
        )
    }};
}

#[macro_export]
macro_rules! glasses_make_case {
    ($harness_name: ty $(, $mod: ident $($arg: expr)*)*) => {
        $crate::glasses_make_case_helper!($harness_name, |case: <$harness_name as Harness>::Builder| case $(, $mod $( $arg )* )* )
    }
}

#[macro_export]
macro_rules! glasses_harness {
    ($harness_name: ident, $builder_type: ty, $test_body: expr) => {
        $crate::glasses_harness!($harness_name, $builder_type, <$builder_type>::default(), $test_body);
    };
    ($harness_name: ident, $builder_type: ty, $builder: expr, $test_body: expr) => {
        pub struct $harness_name;

        impl glasses::Harness for $harness_name {
            type Builder = $builder_type;
            fn new_builder() -> $builder_type {
                $builder
            }
            fn run_test(case: $builder_type) {
                $test_body(case)
            }
        }
    }
}

#[macro_export]
macro_rules! glasses_test {
    (
        $harness_name: ty,
        $name: ident
        $(, [ $attr: meta ] )*
        $(, $mod: ident $($arg: expr)*)*
    ) => {
        #[test]
        $(#[$attr])*
        fn $name() {
            use $crate::Harness;
            let case: <$harness_name as Harness>::Builder = $crate::glasses_make_case!($harness_name $(, $mod $( $arg )* )* );
            <$harness_name>::run_test(case)
        }
    }
}