test_generator_utest/
lib.rs

1//! # Overview
2//! This crate provides the macro `utest!(..)` Implementing the 3 phases setup/test/teardown.
3//! [![Crates.io](https://img.shields.io/crates/v/test-generator.svg)](https://crates.io/crates/test-generator-utest)
4//! [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/frehberg/test-generator/blob/master/LICENSE-MIT)
5//! [![Apache License](http://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/frehberg/test-generator/blob/master/LICENSE-APACHE)
6//! [![Example](http://img.shields.io/badge/crate-Example-red.svg)](https://github.com/frehberg/test-generator/tree/master/example)
7//!
8//! [Documentation](https://docs.rs/test-generator-utest/)
9//!
10//! [Repository](https://github.com/frehberg/test-generator/)
11//!
12//! # Getting Started
13//!
14//! First of all you have to add this dependency to your `Cargo.toml`:
15//!
16//! ```toml
17//! [dev-dependencies]
18//! test-generator-utest = "^0.2"
19//! ```
20//! The test-functionality is supports stable Rust.
21
22//! ```ignore
23//! #![cfg(test)]
24//! extern crate test_generator-utest;
25//!
26//! // Don't forget that procedural macros are imported with `use` statement,
27//! // for example importing the macro 'test_resources'
28//! #![cfg(test)]
29//! use test_generator-utest::utest;
30//! ```
31//!
32
33/// Macro implementing the 3 phases setup/test/teardown
34///
35/// # Usage
36///
37/// The `utest` functionality supports the stable release of Rust-compiler since version 1.30.
38///
39/// ```ignore
40/// #[cfg(test)]
41/// extern crate test_generator_utest;
42///
43/// // demonstrating usage of utest-harness
44/// mod testsuite {
45///     use std::fs::File;
46///     use std::io::prelude::*;
47///
48///     use test_generator_utest::utest;
49///
50///     utest!(hello_world,
51///         || setup("/tmp/hello_world.txt"),
52///         |ctx_ref| test_write_hello_world(ctx_ref),
53///         |ctx|teardown(ctx));
54///
55///     utest!(hello_europe,
56///         || setup("/tmp/hello_europe.txt"),
57///         test_write_hello_europe,
58///         teardown);
59///
60///     // Defining a context structure, storing the resources
61///     struct Context<'t> { file: File, name: &'t str }
62///
63///     // Setup - Initializing the resources
64///     fn setup<'t>(filename: &str) -> Context {
65///         // unwrap may panic
66///         Context { file: File::create(filename).unwrap(), name: filename }
67///     }
68///
69///     // Teardown - Releasing the resources
70///     fn teardown(context: Context) {
71///         let Context { file, name } = context;
72///         // drop file resources explicitly
73///         std::mem::drop(file);
74///         // unwrap may panic
75///         std::fs::remove_file(name).unwrap();
76///     }
77///
78///     // Test - verify feature
79///     fn test_write_hello_world(ctx: &Context) {
80///         // may panic
81///         let mut file = ctx.file.try_clone().unwrap();
82///         // may panic
83///         file.write_all(b"Hello, world!\n").unwrap();
84///         // !!!! although this assertion will fail, the teardown function will be invoked
85///         assert_eq!(1, 0);
86///     }
87///
88///     // Test - verify feature
89///     fn test_write_hello_europe(ctx: &Context) {
90///         // may panic
91///         let mut file = ctx.file.try_clone().unwrap();
92///         // may panic
93///         file.write_all(b"Hello, Europe!\n").unwrap();
94///     }
95/// }
96/// ```
97#[macro_export]
98macro_rules! utest {
99    ( $id: ident, $setup:expr, $test:expr, $teardown:expr ) => {
100       #[test]
101       fn $id() {
102            let context = std::panic::catch_unwind(|| {
103                $setup()
104            });
105
106            assert!(context.is_ok());
107
108            // unwrap the internal context item
109            let ctx = match context {
110                Ok(ctx) => ctx,
111                Err(_) => unreachable!(),
112            };
113
114            let result = std::panic::catch_unwind(|| {
115                $test(&ctx)
116            });
117
118            let finalizer = std::panic::catch_unwind(|| {
119                $teardown(ctx)
120            });
121
122            assert!(result.is_ok());
123
124            assert!(finalizer.is_ok());
125       }
126    };
127}