integration_test/lib.rs
1extern crate syn;
2
3#[macro_use]
4extern crate quote;
5
6extern crate proc_macro;
7
8use syn::{parse_macro_input, parse_quote, ItemFn};
9use proc_macro::TokenStream;
10
11fn create_content_block(block: Box<syn::Block>) -> syn::Stmt {
12 // Method created context block with catch_unwind
13 // Reason why it creates test body with catch_unwind
14 // is raise panic after tear_down complete.
15 let wrap_body = quote!{
16 let result = ::std::panic::catch_unwind(|| {
17 #block;
18 });
19 };
20 let stmt: syn::Stmt = parse_quote! {
21 #wrap_body
22 };
23 stmt
24}
25
26fn create_setup_call() -> syn::Stmt {
27 // Method creates set_up hook
28 let set_up_call = quote!(set_up(););
29 let stmt: syn::Stmt = parse_quote! {
30 #set_up_call
31 };
32 stmt
33}
34
35fn create_tear_down_call() -> syn::Stmt {
36 // Method creates tear_down hook
37 let tear_down_call = quote!(tear_down(););
38 let stmt: syn::Stmt = parse_quote! {
39 #tear_down_call
40 };
41 stmt
42}
43
44fn create_result_check() -> syn::Stmt {
45 // Method should create result check
46 let result_check = quote!{
47 if let Err(err) = result {
48 ::std::panic::resume_unwind(err);
49 };
50 };
51 let stmt: syn::Stmt = parse_quote! {
52 #result_check
53 };
54 stmt
55}
56
57/// Integration test macros
58/// Usage:
59/// If you want add hooks to you integaration test,
60/// which need to create something before test, or remove something after test
61/// need add #[integration_test] macro after #[test] macro.
62/// If you add #[integration_test] you must add set_up(), and tear_down() hooks
63///
64/// Example:
65///
66/// #[cfg(test)]
67/// pub mod some_test {
68/// use super::*;
69///
70/// fn set_up() {
71/// println!("Set up");
72/// }
73/// fn tear_down() {
74/// println!("Tear down");
75/// }
76///
77/// #[test]
78/// #[integration_test]
79/// fn my_shiney_integration_test() {
80/// asserteq!(1, 2);
81/// }
82/// }
83/// Output order is:
84/// "Set up",
85/// panic!() -> is going to show after tear_down finish
86/// "Tear down"
87
88#[proc_macro_attribute]
89pub fn integration_test(_args: TokenStream, input: TokenStream) -> TokenStream {
90 /* Macros add tear_down and set_up hooks to choosen test
91 TODO Add unittests!!!!!
92 unitests should have state for control execution
93 */
94
95 let mut input_test_function = parse_macro_input!(input as ItemFn);
96 // TODO, at next iteration need add manager for down methods
97 // this should be structure IntegrationTest, with exists logic
98 // for maintaine it in easy way
99 let block = input_test_function.block.clone();
100 let content_block = create_content_block(block);
101 let setup_call = create_setup_call();
102 let tear_down_call = create_tear_down_call();
103 let result_check = create_result_check();
104
105 let call_vector: Vec<syn::Stmt> = vec![
106 setup_call, content_block,
107 tear_down_call, result_check
108 ];
109
110 input_test_function.block.stmts = call_vector;
111 quote!(#input_test_function).to_string().parse().unwrap()
112}