1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
// Copyright 2014-2016 The Stainless Developers. See the LICENSE file at the top-level directory of // this distrubution. // // Licensed under the MIT license. This file may not be copied, modified, or distributed except // according to those terms. #![feature(plugin_registrar, quote, rustc_private)] #![deny(missing_docs, warnings)] //! > Stainless is a lightweight, flexible, unopinionated testing framework. //! //! **Note that stainless currently requires the nightly version of the Rust compiler!** //! //! ## Installation //! //! Add stainless as a dependency in your `Cargo.toml` file //! ``` toml //! [dev-dependencies] //! stainless = "*" //! ``` //! //! Add the following lines to the top of your //! [root module](https://doc.rust-lang.org/book/crates-and-modules.html). //! That file is normally called `src/main.rs` for executables and //! `src/lib.rs` for libraries: //! //! ``` rust //! #![feature(plugin)] //! #![cfg_attr(test, plugin(stainless))] //! ``` //! //! This will make stainless available when you run the tests using `cargo //! test`. //! When using stainless only with a library, make sure to run tests using //! `cargo test --lib`. //! //! ## Overview //! //! Stainless exports the `describe!` syntax extension, which allows you //! to quickly generate complex testing hierarchies and reduce boilerplate //! through `before_each` and `after_each`. //! //! Stainless currently supports the following types of subblocks: //! //! * `before_each` and `after_each` //! * `it`, `failing`, and `ignore` //! * `bench` //! * nested `describe!` //! //! `before_each` and `after_each` allow you to group common //! initialization and teardown for a group of tests into a single block, //! shortening your tests. //! //! `it` generates tests which use `before_each` and `after_each`. //! `failing` does the same, except the generated tests are marked with //! `#[should_panic]`. It optionally takes an argument which is matched against the //! failure message. `ignore` is equivalent to marking a test with `#[ignore]` which //! disables the test by default. //! //! `bench` allows you to generate benchmarks in the same fashion, though //! *`before_each` and `after_each` blocks do not currently affect `bench` //! blocks*. //! //! Nested `describe!` blocks allow you to better organize your tests into //! small units and gives you granular control over where `before_each` //! and `after_each` apply. Of course the `before_each` and `after_each` //! blocks of the wrapping `describe!` blocks are executed as well. //! //! Together, these 4 types of subblocks give you more flexibility and //! control than the built in testing infrastructure. //! //! ## Example //! //! ```rust //! describe! stainless { //! before_each { //! // Start up a test. //! let mut stainless = true; //! } //! //! it "makes organizing tests easy" { //! // Do the test. //! assert!(stainless); //! } //! //! after_each { //! // End the test. //! stainless = false; //! } //! //! bench "something simple" (bencher) { //! bencher.iter(|| 2 * 2) //! } //! //! describe! nesting { //! //! before_each { //! let mut inner_stainless = true; //! } //! //! after_each { //! inner_stainless = false; //! } //! //! it "makes it simple to categorize tests" { //! // It even generates submodules! //! assert_eq!(2, 2); //! } //! } //! } //! ``` //! //! Expands to (roughly): //! //! ```rust //! mod stainless { //! #[test] //! fn makes_organizing_tests_easy() { //! let mut stainless = true; //! assert!(stainless); //! stainless = false; //! } //! //! #[bench] //! fn something_simple(bencher: &mut test::Bencher) { //! bencher.iter(|| 2 * 2) //! } //! //! mod nesting { //! #[test] //! fn makes_it_simple_to_categorize_tests() { //! let mut stainless = true; //! let mut inner_stainless = true; //! assert_eq!(2, 2); //! inner_stainless = false; //! stainless = false; //! } //! } //! } //! ``` //! //! ## Importing modules //! //! At this point it is not possible to put `use` statements inside the //! `describe!` blocks. To allow usage of data structures from other //! modules and crates each `describe!` block comes with a silent `pub use //! super::*;` in it. That way everything you `pub use` in the containing //! module is available in your tests. //! //! ```rust //! #[cfg(test)] //! mod tests { //! pub use std::collections::HashMap; //! //! describe! stainless { //! it "can use HashMap" { //! let map = HashMap::new(); //! } //! } //! } //! ``` //! //! ## License //! //! MIT. See the LICENSE file for details. //! //! ## Authors //! //! See Cargo.toml for the full list of authors. extern crate syntax; extern crate rustc_plugin; use self::describe::describe; use rustc_plugin as plugin; use syntax::symbol::Symbol; mod describe; mod parse; mod test; mod bench; mod generate; #[plugin_registrar] #[doc(hidden)] pub fn plugin_registrar(reg: &mut plugin::Registry) { reg.register_syntax_extension( Symbol::intern("describe"), syntax::ext::base::IdentTT(Box::new(describe), None, false) ); }