Releases: frondeus/test-case
TestCase - v2.0.2
Bug fixes
- Fixed the fact that
match X if Ydidn't produce correct guard code which resulted in false positives.
Full Changelog: v2.0.1...v2.0.2
TestCase - v2.0.1
Bug fixes:
matches Pattern if conditionparses correctly (if conditionpart wasn't allowed despite being documented)
Full Changelog: v2.0.0...v2.0.1
TestCase - v2.0.0
Overview
This crate provides the #[test_case] procedural macro attribute that generates multiple parametrized tests using one body with different input parameters.
A test is generated for each data set passed in the test_case attribute.
Under the hood, all test cases that share the same body are grouped into a mod, giving clear and readable test results.
What's changed
New features
=> with |x: T| assert!(x)custom inline test assertions=> using path::to::fncustom fn test assertionsignoreandinconclusivecan be combined with other keywords=> it|is ...syntax is a built-in (previously requiredhamcrest2crate integration)- Simple test cases support returning
Result<(), _>as#[test]attribute does #50
Improvements
- Code refactoring
- Test function is kept in its original scope so it can be reused for non-test related code #77
- Improved test case name selection
Breaking changes
- Deprecation of
inconclusivewithin test description string - it will no longer act like modifier keyword - Removal of
hamcrest2integration (itandisare kept, complex assertions now have different syntax)
Custom inline test assertions
Now it is possible to pass the closure which will assert the test case.
#[test_case(1.0 => with |v: f64| assert!(v.is_infinite()))]
#[test_case(0.0 => with |v: f64| assert!(v.is_nan()))]
fn divide_by_zero_f64_with_lambda(input: f64) -> f64 {
input / 0.0f64
}Custom fn test assertions
Not only the closure is possible but also you can point to the plain function:
Given:
fn assert_is_power_of_two(input: u64) {
assert!(input.is_power_of_two())
}You can now assert:
#[test_case(1 => using assert_is_power_of_two)]
fn power_of_two_with_using(input: u64) -> u64 {
input
}Not only that, you can also create a higher order function like this one:
fn wrapped_pretty_assert(expected: u64) -> impl Fn(u64) {
move |actual: u64| { pretty_assertions::assert_eq!(actual, expected) }
}to achieve even better parameterized tests:
#[test_case(1 => using wrapped_pretty_assert(1))]
fn pretty_assertions_usage(input: u64) -> u64 {
input
}ignore and inconclusive can be combined with other keywords
Sometimes you might want to temporarily disable one of the test cases without removing the testing assertion.
Thanks to this release now it is possible:
#[test_case(12 => ignore matches Ok(_))]
fn ignore_supported(_value: u64) -> Result<(), Box<dyn Error>> {
todo!()
}=> it|is ... syntax is a built-in
Previously test-case was integrated with hamcrest2 assertion crate.
This release breaks this dependency and provides an alternative solution:
#[test_case(1.0 => is equal_to 2.0 ; "eq1")]
#[test_case(1.0 => is greater_or_equal_than 1.0 ; "geq1")]
#[test_case(1.0 => is geq 1.0 ; "geq2")]
#[test_case(1.0 => is almost_equal_to 2.1 precision 0.15 ; "almost_eq1")]
#[test_case(1.0 => is almost 2.0 precision 0.01 ; "almost_eq2")]
fn complex_tests(input: f64) -> f64 {
input * 2.0
}It also supports asserting paths:
#[test_case("Cargo.toml" => is existing_path)]
#[test_case("src/lib.rs" => is file)]
#[test_case("src/" => is dir ; "short_dir")]
#[test_case("src/" => is directory ; "long_dir")]
fn create_path(val: &str) -> std::path::PathBuf {
std::path::PathBuf::from(val)
}As well as collections:
#[test_case(vec![1, 2, 3, 4] => it contains 1)]
#[test_case(vec![1, 2, 3, 4] => it contains_in_order [3, 4])]
fn contains_tests(items: Vec<u64>) -> Vec<u64> {
items
}You can also use the combinators:
#[test_case(1.0 => is gt 0.0 and lt 5.0)]
#[test_case(0.3 => is (gt 0.0 and lt 1.0) or gt 1.2)]
#[test_case(0.7 => is (gt 0.0 and lt 1.0) or gt 1.2)]
fn combinators(v: f32) -> f32 {
v * 2.0
}Note: The combinators are still a bit unpolished. Currently
test_caseonly supports one type of combinator per group.
It means that if you want to combineandwithoryou need to use()to explicitly mark the precedence.
However...
We hope that in the next version we will lift this restriction by providing a full precedence parsing.
Simple test cases support returning Result<(), _>
Finally, the test_case macro now supports the Result return type just like the #[test] attribute does.
It means the test case would fail if the function returns Err(...).
#[test_case(12)]
#[test_case(13)]
fn is_even(value: u64) -> Result<(), String> {
if value % 2 == 0 {
Ok(())
} else {
Err("is odd".to_string())
}
}TestCase - v2.0.0-rc3
TestCase - v1.2.3
- Fix regression where
panicsandinconclusivewere not allowed ontest_casesreturning a value - Fix case where
test_casewould allow to return a type when only single attribute was used
TestCase - v1.2.2
TestCase - v2.0.0-rc2
New features
complextest_case supports nownot,andandorlogical combinators
Breaking changes
- Bumped MSRV to 1.49
TestCase - v2.0.0-rc1
New features
=> with |x: T| assert!(x)custom inline test assertions=> using path::to::fncustom fn test assertionsignoreandinconclusivecan be combined with other keywords (eg.:=> ignore matches Ok(_))
Improvements
- Code refactoring
Breaking changes
- Deprecation of
inconclusivewithin test description string - it will no longer act like modifier keyword - Deprecation of
hamcrest2integration (itandisare kept, complex assertions now have different syntax)
TestCase - v1.2.1
- Disabled clippy warning when test-case was generating
assert_eq!(bool, bool)expression.
TestCase - v1.2.0
New features
- Allow usage of fully qualified attribute
#[test_case::test_case](thanks to @tomprince)
Improvements
- Stopped code from emmiting unneded
()expression in test cases withexpectedfragment (thanks to @martinvonz)