test_generator_utest/lib.rs
1//! # Overview
2//! This crate provides the macro `utest!(..)` Implementing the 3 phases setup/test/teardown.
3//! [](https://crates.io/crates/test-generator-utest)
4//! [](https://github.com/frehberg/test-generator/blob/master/LICENSE-MIT)
5//! [](https://github.com/frehberg/test-generator/blob/master/LICENSE-APACHE)
6//! [](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}