[][src]Crate demonstrate

Declarative testing framework

Allows for tests to be defined in a declarative manner, hiding repetitive code before generation.


describe/context blocks define a scope such as a mod block and can be nested as such.

demonstrate! {
    describe "outer" {
        describe "inner" {}
    }
}

This is generated into:

#[cfg(test)]
mod outer {
    mod inner {}
}

it/test blocks define a unit test.

demonstrate! {
    describe "tests" {
        it "asserts" {
            assert!(true)
        }
    }
}

This is generated into:

#[cfg(test)]
mod tests {
    #[test]
    fn asserts() {
        assert!(true)
    }
}

Unlike mod blocks, describe/context blocks pass their use paths to nested describe/context blocks

fn so_true() -> bool {
    true
}

demonstrate! {
    describe "outer" {
        use super::so_true;
        describe "inner" {
            it "uses" {
                assert!(so_true())
            }
        }
    }
}

This is generated into:

fn so_true() -> bool {
    true
}

#[cfg(test)]
mod outer {
    use super::so_true;
    mod inner {
        use super::*;
        #[test]
        fn uses() {
            asssert!(so_true())
        }
    }
}

Note: If you would like to call use without it being inherited: call it within a seperate, nested describe/context block


before and after blocks prevent shared starting and ending sequences of code from being written for each test within a the describe/context block it is contained in and each nested describe/context block.

demonstrate! {
    describe "tests" {
        before {
            let one = 1;
        }

        it "one" {
            assert_eq!(one, 1)
        }

        it "zero" {
            assert_eq!(one - 1, 0)
        }

        describe "nested" {
            before {
                let two = 2;
            }

            it "two" {
                assert_eq!(one + 1, two)
            }
        }
    }
}

This is generated into:

#[cfg(test)]
mod tests {
    #[test]
    fn one() {
        let one = 1;
        assert_eq!(one, 1)
    }

    #[test]
    fn zero() {
        let one = 1;
        assert_eq!(one - 1, 1)
    }

    mod nested {
        #[test]
        fn two() {
            let one = 1;
            let two = 2;
            assert_eq!(one + 1, two)
        }
    }
}

Outer attributes, returning result types, and async tokens are all valid for it/test blocks, and can be applied to describe/context blocks as well which will affect all descendant tests. (Return types will only be inherited by blocks without one already defined)

demonstrate! {
    describe "returnable" -> Result<(), &'static str> {
        it "is ok" { Ok(()) }

        it "does not fail" {
            assert!(!false);
            Ok(())
        }

        #[should_panic]
        it "fails" -> () {
            assert!(false)
        }
    }
}

This is generated into:

#[cfg(test)]
mod returnable {
    #[test]
    fn is_ok() -> Result<(), &'static str> {
        Ok(())
    }

    #[test]
    fn does_not_fail() -> Result<(), &'static str> {
        assert!(!false);
        Ok(())
    }

    #[test]
    #[should_panic]
    fn fails() -> () {
        assert!(false)
    }
}

Note: If a describe/context block has a return type with an after block containing a success result type being returned, keep in mind that a compile error will occur if a descendant test has different return type than the one appearing in that after block.

Macros

demonstrate