12个版本
使用旧的Rust 2015
0.8.7 | 2018年1月21日 |
---|---|
0.8.6 | 2017年9月2日 |
0.8.5 | 2017年7月29日 |
0.8.0 | 2017年3月18日 |
#259 在 测试
932 每月下载
用于 13 crates
78KB
892 行
Galvanic-assert:基于匹配器的断言和期望,便于测试
此crate提供基于匹配谓词的新断言宏(assert_that!
、expect_that!
、get_expectation_for!
)来
- 简化断言的编写
- 使断言易于阅读和理解
- 轻松扩展断言框架
- 提供大量常见匹配器
- 与galvanic-test和galvanic-mock集成
- 与您喜欢的测试框架一起使用
该crate是galvanic的一部分——一个完整的Rust测试框架。该框架分为三个部分,因此您可以选择只使用所需的组件。
两分钟教程
每个断言都有以下形式:assert_that!(SOME_VALUE, MATCHES_SOMETHING);
。要检查某个值是否满足某些匹配谓词,例如less_than
、contains_in_order
、is_variant!
等,我们可以写如下代码来操作单个值
#[macro_use]
extern crate galvanic_assert;
use galvanic_assert::matchers::*;
#[test]
fn expression_should_compute_correct_value {
assert_that!(&1+2, eq(3));
// or more wordy ...
assert_that!(&1+2, is(eq(3)));
}
或断言集合的属性...
use galvanic_assert::matchers::collection::*;
#[test]
fn expression_should_compute_correct_value {
/// check for containment
assert_that!(&vec![5,1,3,4,2], contains_in_any_order(vec![1,2,3,4,5]));
// check for internal structure
assert_that!(&vec![4,3,2,1], sorted_descending());
}
或变体的属性...
enum Variants {
First(i32),
Second { x: i32, y: i32 },
Third
}
#[test]
fn should_be_the_correct_variant {
let var = Second { x: 1, y: 2 };
assert_that!(&var, is_variant!(Variants::Second));
}
如果您需要断言结构体或枚举的多个字段,可以使用结构匹配器...
enum Baz {
Var1 { x: i32, y: f64 },
Var2(i32, f64)
}
#[test]
fn expression_should_compute_correct_value {
let var1 = Baz::Var1 { x: 12, y: 23.4 };
assert_that!(&var1, has_structure!(Baz::Var1 {
x: eq(12),
y: lt(25.0)
}));
let var2 = Baz::Var2(12, 23.4);
assert_that!(&var2, has_structure!(Baz::Var2 [eq(12), lt(25.0)] ));
}
也可以将多个匹配器组合起来创建更具有表达力的匹配器...
#[test]
fn expression_should_compute_correct_value {
// invert the meaning of a matcher
assert_that!(&1+2, not(greater_than(3)));
// join several matchers conjunctively
assert_that!(&1+2, all_of!(greater_than(0), less_than(5)));
// join several matchers disjunctively
assert_that!(&1+2, any_of!(greater_than(5), less_than(5)));
}
如果还不够,您可以编写自己的匹配器,可以是闭包...
#[test]
fn expression_should_compute_correct_value {
assert_that!(&1+2, |x| {
let builder = MatchResultBuilder::for_("odd");
if x % 2 == 1 { builder.matched() } else { builder.failed_because("result is not odd") }
});
}
或者如果足够简单,可以直接是表达式...
#[test]
fn expression_should_compute_correct_value {
let val = 1 + 2;
assert_that!(val % 2 == 1, otherwise "result is not odd");
}
如果更复杂,则实现表示匹配器状态的某个结构的Matcher
特质。
断言积极的事情是好的,但有时我们期望某些事情会非常糟糕...
fn press_big_red_button() {
panic!("shouldn't have done that ...");
}
#[test]
fn someting_should_go_wrong {
assert_that!(press_big_red_button(), panics);
}
...除非它没有发生。
fn press_faulty_red_button() {
return;
panic!("shouldn't have done that ...");
}
#[test]
fn everything_is_fine {
assert_that!(press_faulty_red_button(), does not panic);
}
再花两分钟来了解预期
断言会立即检查其正确性。这意味着后续的任何断言都不会执行,你可能会错过调试错误的重要信息。基本上,你想要尽可能多的信息来做到这一点。因此,引入了宏expect_that!
和get_expectation_for!
。
expect_that!
宏和get_expectation_for!
宏都像assert_that!
一样以完全相同的方式声明一个预期,所以上一节中学到的任何内容仍然适用。条件仍然在指定的点上检查,但对结果的检查将推迟到稍后的时间。
expect_that!
宏将结果的检查推迟到当前块的末尾。
{
expect_that!(&1+1, equal_to(0));
expect_that!(&1+1, less_than(4)); // is executed
}
expect_that!(1+1, panics); // is never executed as the first expectation panics at the end of the block
get_expectation_for!
宏提供了更精细的控制。它返回一个Expectation
对象,可以通过调用verify
来验证...
let e1 = get_expectation_for!(&1+1, equal_to(0));
let e2 = get_expectation_for!(&1+1, less_than(4)); // is executed
e1.verify();
let e3 = get_expectation_for!(&1+1, panics); // is never executed as e1 panics
...或者,一旦对象超出作用域,将自动验证。
{
let e1 = get_expectation_for!(&1+1, equal_to(0));
let e2 = get_expectation_for!(&1+1, less_than(4)); // is executed
}
let e3 = get_expectation_for!(1+1, panics); // is never executed as e1 panics
没有更多要说的了——请查看文档和不断增长的匹配器列表。
记住...只有经过测试的代码才是快乐的代码!
贡献
非常欢迎贡献!(请阅读并同意许可证。)
包含的匹配器列表远未完成。如果你遇到一个有用的匹配器,请提交一个问题。在提交问题之前,请检查该类型本身是否已经有一个布尔谓词,例如,如Option::is_none()
。这些已经由断言宏支持,并且只有在Matcher
的错误信息实质上优于默认值时才应包括在内。如果缺少或损坏了某些内容,请提交问题(如果你愿意的话)发送拉取请求。
对于拉取请求,请确保包含测试用例以避免回归。应将针对Matchers
的测试添加为集成测试,因为它们测试了与断言宏的集成。看看现有的那些!