From 877eb9439495afe4dea21fbeb80933b4aa9dc135 Mon Sep 17 00:00:00 2001 From: Michele d'Amico Date: Sun, 20 Nov 2022 13:04:14 +0100 Subject: [PATCH] Use value for name #160 (#168) * WIP: enable check tests by partial name * WIP: values tests name from content * WIP: Single test check itself * Now framework accept also contains rule * Add ok_in and fail_in shortcut * Fixed tests and operation characters traslated to _ --- rstest/tests/rstest/mod.rs | 155 +++++++++++------------ rstest_macros/Cargo.toml | 1 + rstest_macros/src/render/mod.rs | 53 +++++++- rstest_macros/src/render/test.rs | 22 ++-- rstest_test/Cargo.toml | 1 + rstest_test/src/utils.rs | 205 ++++++++++++++++++++++++++----- rstest_test/tests/framework.rs | 204 ++++++++++++++++++++++++++++-- 7 files changed, 501 insertions(+), 140 deletions(-) diff --git a/rstest/tests/rstest/mod.rs b/rstest/tests/rstest/mod.rs index 2dfd524..da17ab7 100644 --- a/rstest/tests/rstest/mod.rs +++ b/rstest/tests/rstest/mod.rs @@ -100,6 +100,7 @@ fn use_mutable_fixture_in_parametric_argumnts() { let (output, _) = run_test("use_mutable_fixture_in_parametric_argumnts.rs"); TestResults::new() + .with_contains(true) .ok("use_mutate_fixture::case_1::b_1") .assert(output); } @@ -171,22 +172,8 @@ mod dump_input_values { .fail("cases_fail::case_2") .fail("no_trace_cases_fail::case_1") .fail("no_trace_cases_fail::case_2") - .fail("matrix_fail::u_1::s_1::t_1") - .fail("matrix_fail::u_1::s_1::t_2") - .fail("matrix_fail::u_1::s_2::t_1") - .fail("matrix_fail::u_1::s_2::t_2") - .fail("matrix_fail::u_2::s_1::t_1") - .fail("matrix_fail::u_2::s_1::t_2") - .fail("matrix_fail::u_1::s_2::t_1") - .fail("matrix_fail::u_2::s_2::t_2") - .fail("no_trace_matrix_fail::u_1::s_1::t_1") - .fail("no_trace_matrix_fail::u_1::s_1::t_2") - .fail("no_trace_matrix_fail::u_1::s_2::t_1") - .fail("no_trace_matrix_fail::u_1::s_2::t_2") - .fail("no_trace_matrix_fail::u_2::s_1::t_1") - .fail("no_trace_matrix_fail::u_2::s_1::t_2") - .fail("no_trace_matrix_fail::u_1::s_2::t_1") - .fail("no_trace_matrix_fail::u_2::s_2::t_2") + .fail_with("matrix_fail::u_1", false, 8) + .fail_with("matrix_fail::u_2", false, 8) .assert(output); assert_in!(out, "fu32 = 42"); @@ -257,7 +244,7 @@ mod dump_input_values { TestResults::new() .fail("simple") .fail("cases::case_1") - .fail("matrix::a_1::b_1::dd_1") + .fail_in("matrix::a_1") .assert(output); assert_in!(out, "fu32 = 42"); @@ -745,10 +732,11 @@ mod matrix { let (output, _) = run_test(res("simple.rs")); TestResults::new() - .ok("strlen_test::expected_1::input_1") - .ok("strlen_test::expected_1::input_2") - .ok("strlen_test::expected_2::input_1") - .ok("strlen_test::expected_2::input_2") + .with_contains(true) + .ok("strlen_test::expected_1_4::input_1___ciao__") + .ok("strlen_test::expected_1_4::input_2___buzz__") + .ok("strlen_test::expected_2_2_3_2::input_1___ciao__") + .ok("strlen_test::expected_2_2_3_2::input_2___buzz__") .assert(output); } @@ -757,34 +745,26 @@ mod matrix { let (output, _) = run_test(res("partial.rs")); TestResults::new() - .ok("default::a_1::b_1") - .ok("default::a_1::b_2") - .ok("default::a_2::b_1") - .ok("partial_2::a_2::b_2") - .ok("partial_attr_2::a_2::b_2") - .ok("complete::a_2::b_2") - .ok("complete_attr::a_2::b_2") - .fail("default::a_2::b_2") - .fail("partial_1::a_1::b_1") - .fail("partial_1::a_1::b_2") - .fail("partial_1::a_2::b_1") - .fail("partial_1::a_2::b_2") - .fail("partial_2::a_1::b_1") - .fail("partial_2::a_1::b_2") - .fail("partial_2::a_2::b_1") - .fail("complete::a_1::b_1") - .fail("complete::a_1::b_2") - .fail("complete::a_2::b_1") - .fail("partial_attr_1::a_1::b_1") - .fail("partial_attr_1::a_1::b_2") - .fail("partial_attr_1::a_2::b_1") - .fail("partial_attr_1::a_2::b_2") - .fail("partial_attr_2::a_1::b_1") - .fail("partial_attr_2::a_1::b_2") - .fail("partial_attr_2::a_2::b_1") - .fail("complete_attr::a_1::b_1") - .fail("complete_attr::a_1::b_2") - .fail("complete_attr::a_2::b_1") + .with_contains(true) + .ok_times("default::a_1", 2) + .ok("default::a_2") + .ok("partial_2::a_2") + .ok("partial_attr_2::a_2") + .ok("complete::a_2") + .ok("complete_attr::a_2") + .fail("default::a_2") + .fail_times("partial_1::a_1", 2) + .fail_times("partial_1::a_2", 2) + .fail_times("partial_2::a_1", 2) + .fail("partial_2::a_2") + .fail_times("complete::a_1", 2) + .fail("complete::a_2") + .fail_times("partial_attr_1::a_1", 2) + .fail_times("partial_attr_1::a_2", 2) + .fail_times("partial_attr_2::a_1", 2) + .fail("partial_attr_2::a_2") + .fail_times("complete_attr::a_1", 2) + .fail("complete_attr::a_2") .assert(output); } @@ -796,10 +776,11 @@ mod matrix { let output = prj.run_tests().unwrap(); TestResults::new() - .ok("my_async_test::first_1::second_1") - .fail("my_async_test::first_1::second_2") - .fail("my_async_test::first_2::second_1") - .ok("my_async_test::first_2::second_2") + .with_contains(true) + .ok("my_async_test::first_1") + .fail("my_async_test::first_1") + .fail("my_async_test::first_2") + .ok("my_async_test::first_2") .assert(output); } @@ -811,14 +792,15 @@ mod matrix { let output = prj.run_tests().unwrap(); TestResults::new() - .ok("sync::first_1::second_1") - .fail("sync::first_1::second_2") - .fail("sync::first_2::second_1") - .ok("sync::first_2::second_2") - .ok("fn_async::first_1::second_1") - .fail("fn_async::first_1::second_2") - .fail("fn_async::first_2::second_1") - .ok("fn_async::first_2::second_2") + .with_contains(true) + .ok("sync::first_1") + .fail("sync::first_1") + .fail("sync::first_2") + .ok("sync::first_2") + .ok("fn_async::first_1") + .fail("fn_async::first_1") + .fail("fn_async::first_2") + .ok("fn_async::first_2") .assert(output); } @@ -827,18 +809,18 @@ mod matrix { let (output, _) = run_test(res("use_attr.rs")); TestResults::new() - .ok("both::expected_1::input_1") - .ok("both::expected_1::input_2") - .ok("both::expected_2::input_1") - .ok("both::expected_2::input_2") - .ok("first::input_1::expected_1") - .ok("first::input_2::expected_1") - .ok("first::input_1::expected_2") - .ok("first::input_2::expected_2") - .ok("second::expected_1::input_1") - .ok("second::expected_1::input_2") - .ok("second::expected_2::input_1") - .ok("second::expected_2::input_2") + .ok("both::expected_1_4::input_1___ciao__") + .ok("both::expected_1_4::input_2___buzz__") + .ok("both::expected_2_2_3_2::input_1___ciao__") + .ok("both::expected_2_2_3_2::input_2___buzz__") + .ok("first::input_1___ciao__::expected_1_4") + .ok("first::input_2___buzz__::expected_1_4") + .ok("first::input_1___ciao__::expected_2_2_3_2") + .ok("first::input_2___buzz__::expected_2_2_3_2") + .ok("second::expected_1_4::input_1___ciao__") + .ok("second::expected_1_4::input_2___buzz__") + .ok("second::expected_2_2_3_2::input_1___ciao__") + .ok("second::expected_2_2_3_2::input_2___buzz__") .assert(output); } } @@ -859,11 +841,11 @@ fn convert_string_literal() { .ok("cases::case_4") .fail("cases::case_5") .fail("cases::case_6") - .ok("values::addr_1") - .ok("values::addr_2") - .fail("values::addr_3") - .fail("values::addr_4") - .ok("not_convert_byte_array::case_1::values_1") + .ok_in("values::addr_1") + .ok_in("values::addr_2") + .fail_in("values::addr_3") + .fail_in("values::addr_4") + .ok_in("not_convert_byte_array::case_1::values_1") .ok("not_convert_impl::case_1") .ok("not_convert_generics::case_1") .ok("not_convert_generics::case_2") @@ -877,14 +859,14 @@ fn happy_path() { let (output, _) = run_test("happy_path.rs"); TestResults::new() - .ok("happy::case_1::expected_1::input_1") - .ok("happy::case_1::expected_1::input_2") - .ok("happy::case_1::expected_2::input_1") - .ok("happy::case_1::expected_2::input_2") - .ok("happy::case_2_second::expected_1::input_1") - .ok("happy::case_2_second::expected_1::input_2") - .ok("happy::case_2_second::expected_2::input_1") - .ok("happy::case_2_second::expected_2::input_2") + .ok("happy::case_1::expected_1_4::input_1___ciao__") + .ok("happy::case_1::expected_1_4::input_2___buzz__") + .ok("happy::case_1::expected_2_2_3_2::input_1___ciao__") + .ok("happy::case_1::expected_2_2_3_2::input_2___buzz__") + .ok("happy::case_2_second::expected_1_4::input_1___ciao__") + .ok("happy::case_2_second::expected_1_4::input_2___buzz__") + .ok("happy::case_2_second::expected_2_2_3_2::input_1___ciao__") + .ok("happy::case_2_second::expected_2_2_3_2::input_2___buzz__") .assert(output); } @@ -905,6 +887,7 @@ fn ignore_underscore_args() { let (output, _) = run_test("ignore_args.rs"); TestResults::new() + .with_contains(true) .ok("test::case_1::_ignore3_1") .ok("test::case_1::_ignore3_2") .ok("test::case_1::_ignore3_3") diff --git a/rstest_macros/Cargo.toml b/rstest_macros/Cargo.toml index aab5636..a11edd9 100644 --- a/rstest_macros/Cargo.toml +++ b/rstest_macros/Cargo.toml @@ -25,6 +25,7 @@ cfg-if = "1.0.0" proc-macro2 = "1.0.27" quote = "1.0.9" syn = {version = "1.0.72", features = ["full", "parsing", "extra-traits", "visit", "visit-mut"]} +unicode-ident = "1.0.5" [dev-dependencies] actix-rt = "2.2.0" diff --git a/rstest_macros/src/render/mod.rs b/rstest_macros/src/render/mod.rs index 09a2b24..7e5936a 100644 --- a/rstest_macros/src/render/mod.rs +++ b/rstest_macros/src/render/mod.rs @@ -8,7 +8,8 @@ use syn::token::Async; use proc_macro2::{Span, TokenStream}; use syn::{parse_quote, Attribute, Expr, FnArg, Ident, ItemFn, Path, ReturnType, Stmt}; -use quote::{format_ident, quote}; +use quote::{format_ident, quote, ToTokens}; +use unicode_ident::is_xid_continue; use crate::utils::attr_ends_with; use crate::{ @@ -92,8 +93,9 @@ impl ValueList { ) -> impl Iterator)> + 'a { let max_len = self.values.len(); self.values.iter().enumerate().map(move |(index, expr)| { + let sanitized_expr = sanitize_ident(expr); let name = format!( - "{}_{:0len$}", + "{}_{:0len$}_{sanitized_expr:.64}", self.arg, index + 1, len = max_len.display_len() @@ -398,3 +400,50 @@ fn cases_data( } }) } + +fn sanitize_ident(expr: &Expr) -> String { + expr.to_token_stream() + .to_string() + .chars() + .filter(|c| !c.is_whitespace()) + .map(|c| match c { + '"' | '\'' => "__".to_owned(), + ':' | '(' | ')' | '{' | '}' | '[' | ']' | ',' | '.' | '*' | '+' | '/' | '-' | '%' + | '^' | '!' | '&' | '|' => "_".to_owned(), + _ => c.to_string(), + }) + .collect::() + .chars() + .filter(|&c| is_xid_continue(c)) + .collect() +} + +#[cfg(test)] +mod tests { + use crate::test::ToAst; + + use super::*; + use crate::test::{assert_eq, *}; + + #[rstest] + #[case("1", "1")] + #[case(r#""1""#, "__1__")] + #[case(r#"Some::SomeElse"#, "Some__SomeElse")] + #[case(r#""minnie".to_owned()"#, "__minnie___to_owned__")] + #[case( + r#"vec![1 , 2, + 3]"#, + "vec__1_2_3_" + )] + #[case( + r#"some_macro!("first", {second}, [third])"#, + "some_macro____first____second___third__" + )] + #[case(r#"'x'"#, "__x__")] + #[case::ops(r#"a*b+c/d-e%f^g"#, "a_b_c_d_e_f_g")] + fn sanitaze_ident_name(#[case] expression: impl AsRef, #[case] expected: impl AsRef) { + let expression: Expr = expression.as_ref().ast(); + + assert_eq!(expected.as_ref(), sanitize_ident(&expression)); + } +} diff --git a/rstest_macros/src/render/test.rs b/rstest_macros/src/render/test.rs index 1beda72..6a32537 100644 --- a/rstest_macros/src/render/test.rs +++ b/rstest_macros/src/render/test.rs @@ -1244,7 +1244,10 @@ mod matrix_cases_should { .map(|i| format!("{}_{}", names[0], i)) .collect::>(); - assert_eq!(expected, modules); + assert_eq!(expected.len(), modules.len()); + for (e, m) in expected.into_iter().zip(modules.into_iter()) { + assert_in!(m, e); + } } #[test] @@ -1289,7 +1292,10 @@ mod matrix_cases_should { .map(|i| format!("{}_{}", names[1], i)) .collect::>(); - assert_eq!(expected, tests); + assert_eq!(expected.len(), tests.len()); + for (e, m) in expected.into_iter().zip(tests.into_iter()) { + assert_in!(m, e); + } } } @@ -1356,18 +1362,18 @@ mod matrix_cases_should { let mods = tg.get_modules().names(); - assert_eq!(mods[0], "first_001"); - assert_eq!(mods[99], "first_100"); + assert_in!(mods[0], "first_001"); + assert_in!(mods[99], "first_100"); let mods = tg.get_modules()[0].get_modules().names(); - assert_eq!(mods[0], "second_01"); - assert_eq!(mods[9], "second_10"); + assert_in!(mods[0], "second_01"); + assert_in!(mods[9], "second_10"); let functions = tg.get_modules()[0].get_modules()[1].get_tests().names(); - assert_eq!(functions[0], "third_1"); - assert_eq!(functions[1], "third_2"); + assert_in!(functions[0], "third_1"); + assert_in!(functions[1], "third_2"); } } diff --git a/rstest_test/Cargo.toml b/rstest_test/Cargo.toml index 52409da..e898afd 100644 --- a/rstest_test/Cargo.toml +++ b/rstest_test/Cargo.toml @@ -19,4 +19,5 @@ toml_edit = "0.15.0" [dev-dependencies] lazy_static = "1.4.0" +rstest = {version = "0.15.0", default-features = false} temp_testdir = "0.2.3" diff --git a/rstest_test/src/utils.rs b/rstest_test/src/utils.rs index a6d1cbf..fac798a 100644 --- a/rstest_test/src/utils.rs +++ b/rstest_test/src/utils.rs @@ -1,12 +1,6 @@ use std::borrow::Cow; use std::thread; -#[derive(Clone)] -pub enum TestResult> { - Ok(S), - Fail(S), -} - #[macro_export] macro_rules! assert_in { ($text:expr, $message:expr) => ({ @@ -112,63 +106,187 @@ macro_rules! assert_regex { }); } +#[derive(Clone)] +pub(crate) struct TestInfo { + exactly: bool, + times: usize, +} + +impl Default for TestInfo { + fn default() -> Self { + Self { + exactly: true, + times: 1, + } + } +} + +#[derive(Clone)] +pub(crate) enum TestResult> { + Ok(S, TestInfo), + Fail(S, TestInfo), +} + impl> TestResult { + fn assert(&self, output: impl AsRef) { + let regex = if self.exactly() { + format!("test {}( - should panic)? ... {}", self.name(), self.msg()) + } else { + format!( + "test .*{}.*( - should panic)? ... {}", + self.name(), + self.msg() + ) + }; + match self.times() { + 0 => {} + 1 => { + assert_regex!(regex, output.as_ref()); + } + n => { + assert_regex!(regex, output.as_ref()); + assert_eq!( + n, + output.count_regex(regex), + "test {} is present but wrong count", + self.name() + ); + } + } + } + + fn ok(name: S, exactly: bool, occurence: usize) -> Self { + Self::Ok( + name, + TestInfo { + exactly, + times: occurence, + }, + ) + } + + fn fail(name: S, exactly: bool, occurence: usize) -> Self { + Self::Fail( + name, + TestInfo { + exactly, + times: occurence, + }, + ) + } + pub fn is_fail(&self) -> bool { - use self::TestResult::*; - matches!(*self, Fail(_)) + use TestResult::*; + matches!(*self, Fail(_, _)) } + #[allow(dead_code)] pub fn is_ok(&self) -> bool { use self::TestResult::*; - matches!(*self, Ok(_)) + matches!(*self, Ok(_, _)) } pub fn name(&self) -> String { use self::TestResult::*; match *self { - Ok(ref s) => s.as_ref().to_owned(), - Fail(ref s) => s.as_ref().to_owned(), + Ok(ref s, _) => s.as_ref().to_owned(), + Fail(ref s, _) => s.as_ref().to_owned(), } } pub fn msg(&self) -> &'static str { use self::TestResult::*; match *self { - Ok(_) => "ok", - Fail(_) => "FAILED", + Ok(_, _) => "ok", + Fail(_, _) => "FAILED", } } + + fn info(&self) -> &TestInfo { + match self { + TestResult::Ok(_, o) => o, + TestResult::Fail(_, o) => o, + } + } + + fn exactly(&self) -> bool { + self.info().exactly + } + + fn times(&self) -> usize { + self.info().times + } } #[derive(Default, Clone)] -pub struct TestResults(Vec>) +pub struct TestResults where - S: AsRef + Clone; + S: AsRef + Clone, +{ + results: Vec>, + contains: bool, +} impl TestResults where S: AsRef + Clone, { pub fn new() -> Self { - TestResults(vec![]) + TestResults { + results: vec![], + contains: false, + } + } + + pub fn with_contains(self, contains: bool) -> Self { + Self { + results: self.results, + contains, + } + } + + pub fn ok_with(self, name: S, exactly: bool, occurence: usize) -> Self { + self.append(TestResult::ok(name, exactly, occurence)) + } + + pub fn fail_with(self, name: S, exactly: bool, occurence: usize) -> Self { + self.append(TestResult::fail(name, exactly, occurence)) } pub fn ok(self, name: S) -> Self { - self.append(TestResult::Ok(name)) + let contains = self.contains; + self.ok_with(name, !contains, 1) } pub fn fail(self, name: S) -> Self { - self.append(TestResult::Fail(name)) + let contains = self.contains; + self.fail_with(name, !contains, 1) + } + + pub fn ok_in(self, name: S) -> Self { + self.ok_with(name, false, 1) + } + + pub fn fail_in(self, name: S) -> Self { + self.fail_with(name, false, 1) + } + + pub fn ok_times(self, name: S, occurence: usize) -> Self { + let contains = self.contains; + self.ok_with(name, !contains, occurence) + } + + pub fn fail_times(self, name: S, occurence: usize) -> Self { + let contains = self.contains; + self.fail_with(name, !contains, occurence) } - pub fn append(mut self, test: TestResult) -> Self { - self.0.push(test); + pub(crate) fn append(mut self, test: TestResult) -> Self { + self.results.push(test); self } pub fn assert(&self, output: ::std::process::Output) { - let tests = &self.0; - let (expected_code, msg) = if !self.should_fail() { (0, "Unexpected fails!") } else { @@ -190,14 +308,9 @@ where panic!("Empty stdout!"); } - assert_in!(output, format!("running {} test", tests.len())); + assert_in!(output, format!("running {} test", self.count_tests())); - self.for_each(|t| { - assert_regex!( - format!("test {}( - should panic)? ... {}", t.name(), t.msg()), - output - ) - }); + self.for_each(|t| t.assert(output.as_ref())); if self.should_fail() { assert_in!(output, "failures:".to_string()); @@ -207,15 +320,19 @@ where } fn should_fail(&self) -> bool { - self.0.iter().any(|r| r.is_fail()) + self.results.iter().any(|r| r.is_fail()) } fn for_each)>(&self, action: F) { - self.0.iter().for_each(action) + self.results.iter().for_each(action) } fn for_each_failed)>(&self, action: F) { - self.0.iter().filter(|r| r.is_fail()).for_each(action) + self.results.iter().filter(|r| r.is_fail()).for_each(action) + } + + fn count_tests(&self) -> usize { + self.results.iter().map(|t| t.times()).sum() } } @@ -235,6 +352,8 @@ pub fn testname() -> String { pub trait CountMessageOccurrence { fn count>(&self, message: S) -> usize; + + fn count_regex>(&self, message: S) -> usize; } impl CountMessageOccurrence for ST @@ -247,6 +366,14 @@ where .filter(|line| line.contains(message.as_ref())) .count() } + + fn count_regex>(&self, regex: S) -> usize { + let regex = regex::Regex::new(regex.as_ref()).unwrap(); + self.as_ref() + .lines() + .filter(|line| regex.is_match(line)) + .count() + } } #[cfg(test)] @@ -267,6 +394,20 @@ mod test { assert_eq!(3, foo_occurences); } + #[test] + fn should_count_regex_occurence() { + let message = " + 123 + aa2bb + abc + 2aa + foo + " + .count_regex(r"\d+"); + + assert_eq!(3, message); + } + #[test] fn should_get_test_path() { use super::*; diff --git a/rstest_test/tests/framework.rs b/rstest_test/tests/framework.rs index 751571c..b13dd68 100644 --- a/rstest_test/tests/framework.rs +++ b/rstest_test/tests/framework.rs @@ -1,6 +1,7 @@ use lazy_static::lazy_static; use temp_testdir::TempDir; +use rstest::rstest; use rstest_test::*; lazy_static! { @@ -14,8 +15,10 @@ fn prj() -> Project { ROOT_PROJECT.subproject(&prj_name) } -#[test] -fn one_success() { +#[rstest] +#[case::default_conf(TestResults::new())] +#[case::contains(TestResults::new().with_contains(true))] +fn one_success(#[case] results: TestResults<&str>) { let project = prj(); project.append_code( @@ -29,11 +32,13 @@ fn one_success() { let output = project.run_tests().unwrap(); - TestResults::new().ok("success").assert(output); + results.ok("success").assert(output); } -#[test] -fn one_fail() { +#[rstest] +#[case::default_conf(TestResults::new())] +#[case::contains(TestResults::new().with_contains(true))] +fn one_fail(#[case] results: TestResults<&str>) { let project = prj(); project.append_code( @@ -47,11 +52,13 @@ fn one_fail() { let output = project.run_tests().unwrap(); - TestResults::new().fail("fail").assert(output); + results.fail("fail").assert(output); } -#[test] -fn more_tests() { +#[rstest] +#[case::default_conf(TestResults::new())] +#[case::contains(TestResults::new().with_contains(true))] +fn more_tests(#[case] results: TestResults<&str>) { let project = prj(); project.append_code( @@ -77,7 +84,7 @@ fn more_tests() { let output = project.run_tests().unwrap(); - TestResults::new() + results .ok("success") .ok("eq") .fail("fail") @@ -85,8 +92,10 @@ fn more_tests() { .assert(output); } -#[test] -fn tests_with_should_panic() { +#[rstest] +#[case::default_conf(TestResults::new())] +#[case::contains(TestResults::new().with_contains(true))] +fn tests_with_should_panic(#[case] results: TestResults<&str>) { let project = prj(); project.append_code( @@ -106,7 +115,178 @@ fn tests_with_should_panic() { let output = project.run_tests().unwrap(); - TestResults::new().ok("success").fail("fail").assert(output); + results.ok("success").fail("fail").assert(output); +} + +#[test] +fn should_check_just_contains_conf() { + let project = prj(); + + project.append_code( + r#" + #[test] + fn success() { + assert!(true); + } + #[test] + fn fail() { + assert!(false); + } + #[test] + fn eq() { + assert_eq!(1, 1); + } + #[test] + fn two_eq() { + assert_eq!(2, 2); + } + #[test] + fn enq() { + assert_eq!(1, 2); + } + #[test] + fn two_enq() { + assert_eq!(1, 3); + } + "#, + ); + + let output = project.run_tests().unwrap(); + let results = TestResults::new().with_contains(true); + + results + .ok("suc") + .ok_times("eq", 2) + .fail("fai") + .fail_times("enq", 2) + .assert(output); +} + +#[test] +fn should_check_just_contains_on_some_test() { + let project = prj(); + + project.append_code( + r#" + #[test] + fn success() { + assert!(true); + } + #[test] + fn fail() { + assert!(false); + } + #[test] + fn eq() { + assert_eq!(1, 1); + } + #[test] + fn two_eq() { + assert_eq!(2, 2); + } + #[test] + fn enq() { + assert_eq!(1, 2); + } + #[test] + fn two_enq() { + assert_eq!(1, 3); + } + "#, + ); + + let output = project.run_tests().unwrap(); + let results = TestResults::new(); + + results + .ok("success") + .ok_with("eq", false, 2) + .fail("fail") + .fail("enq") + .fail("two_enq") + .assert(output); +} + +#[test] +fn should_check_some_tests_as_contains() { + let project = prj(); + + project.append_code( + r#" + #[test] + fn case_1() { + assert!(true); + } + #[test] + fn case_2_aa() { + assert!(true); + } + #[test] + fn case_3_b() { + assert!(false); + } + "#, + ); + + let output = project.run_tests().unwrap(); + let results = TestResults::new(); + + results + .ok("case_1") + .ok_in("case_2") + .fail_in("case_3") + .assert(output); +} + +#[test] +#[should_panic] +fn should_dont_wrongly_check_contains() { + let project = prj(); + + project.append_code( + r#" + #[test] + fn case_1_aa() { + assert!(true); + } + "#, + ); + + let output = project.run_tests().unwrap(); + let results = TestResults::new(); + + results.ok("case_1").assert(output); +} + +#[test] +#[should_panic(expected = "but wrong count")] +fn should_detect_wrong_contains() { + let project = prj(); + + project.append_code( + r#" + #[test] + fn case_1() { + assert!(true); + } + #[test] + fn case_2() { + assert!(true); + } + #[test] + fn case_3() { + assert!(true); + } + "#, + ); + + let output = project.run_tests().unwrap(); + let results = TestResults::new(); + + results + .ok("case_3") + .ok_with("case", false, 2) + .assert(output); } #[test]