10 个版本 (6 个重大更改)
0.7.0 | 2024 年 5 月 30 日 |
---|---|
0.6.0 | 2023 年 7 月 6 日 |
0.5.0 | 2023 年 1 月 29 日 |
0.4.0 | 2022 年 7 月 4 日 |
0.1.0 | 2020 年 6 月 21 日 |
#222 in 测试
每月 320,189 次下载
用于 47 个 crate
21KB
139 行
重用 rstest
的参数化测试用例
此 crate 提供了一种定义测试集合并将它们应用于所有需要测试的情况的方法。使用 rstest
crate 可以定义测试列表,但如果要将相同的测试应用到另一个测试函数中,必须重写所有用例或编写一些宏来完成工作。
这两种解决方案都有一些缺点
- 引入重复
- 宏使代码难以阅读,并分散了对测试核心的关注
此 crate 的目标是解决这个问题。 rstest_reuse
提供了两个属性
#[template]
:定义一个模板#[apply]
:将定义的模板应用到创建测试
这里有一个简单的例子
use rstest::rstest;
use rstest_reuse::{self, *};
// Here we define the template. This define
// * The test list name to `two_simple_cases`
// * cases: here two cases
#[template]
#[rstest]
#[case(2, 2)]
#[case(4/2, 2)]
// Define a and b as cases arguments
fn two_simple_cases(#[case] a: u32, #[case] b: u32) {}
// Here we apply the `two_simple_cases` template: That is expanded in
// #[template]
// #[rstest]
// #[case(2, 2)]
// #[case(4/2, 2)]
// fn it_works(#[case] a: u32,#[case] b: u32) {
// assert!(a == b);
// }
#[apply(two_simple_cases)]
fn it_works(a: u32, b: u32) {
assert!(a == b);
}
// Here we reuse the `two_simple_cases` template to create two
// other tests
#[apply(two_simple_cases)]
fn it_fail(a: u32, b: u32) {
assert!(a != b);
}
如果我们运行 cargo test
我们将得到
Finished test [unoptimized + debuginfo] target(s) in 0.05s
Running target/debug/deps/playground-8a1212f8b5eb00ce
running 4 tests
test it_fail::case_1 ... FAILED
test it_works::case_1 ... ok
test it_works::case_2 ... ok
test it_fail::case_2 ... FAILED
failures:
---- it_fail::case_1 stdout ----
thread 'it_fail::case_1' panicked at 'assertion failed: a != b', src/main.rs:34:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- it_fail::case_2 stdout ----
thread 'it_fail::case_2' panicked at 'assertion failed: a != b', src/main.rs:34:5
failures:
it_fail::case_1
it_fail::case_2
test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--bin playground'
简单且整洁!
注意,如果测试参数的名称与模板中的名称匹配,则可以省略重复的参数属性。
组合和值
如果您需要在应用模板时添加一些用例或值,可以利用组合。以下是一个简单的例子
#[template]
#[rstest]
#[case(2, 2)]
#[case(4/2, 2)]
fn base(#[case] a: u32, #[case] b: u32) {}
// Here we add a new case and an argument in a value list:
#[apply(base)]
#[case(9/3, 3)]
fn it_works(a: u32, b: u32, #[values("a", "b")] t: &str) {
assert!(a == b);
assert!("abcd".contains(t))
}
运行 6 个测试
running 6 tests
test it_works::case_1::t_2 ... ok
test it_works::case_2::t_2 ... ok
test it_works::case_2::t_1 ... ok
test it_works::case_3::t_2 ... ok
test it_works::case_3::t_1 ... ok
test it_works::case_1::t_1 ... ok
如果需要,模板也可以用于值和参数
#[template]
#[rstest]
fn base(#[with(42)] fix: u32, #[values(1,2,3)] v: u32) {}
#[fixture]
fn fix(#[default(0)] inner: u32) -> u32 {
inner
}
#[apply(base)]
fn use_it_with_fixture(fix: u32, v: u32) {
assert!(fix%v == 0);
}
#[apply(base)]
fn use_it_without_fixture(v: u32) {
assert!(24 % v == 0);
}
再运行 6 个测试
running 6 tests
test use_it_with_fixture::v_1 ... ok
test use_it_without_fixture::v_1 ... ok
test use_it_with_fixture::v_3 ... ok
test use_it_without_fixture::v_2 ... ok
test use_it_without_fixture::v_3 ... ok
test use_it_with_fixture::v_2 ... ok
#[export]
属性
现在 #[export]
属性让你能够在不同的crate之间导出模板,但不会提升crate顶部的宏定义(这是0.5.0版本之前的默认行为)。
现在,如果你想将模板放在crate的根目录下,你可以在根模块中定义它,或者在crate顶部重新导出,如下所示:
pub use my::modules::path::of::my::template::my_template;
当你想导出模板时,还应确保在crate顶部将 rstest_reuse
声明为 pub
,以便从导入模板的模块中使用它。
因此,在这种情况下,在导出模板的crate中,你应该在crate的根目录下放置以下内容:
#[cfg(test)]
pub use rstest_reuse;
而不是像标准情况那样仅仅使用 use rstest_reuse
。
免责声明
此crate处于开发阶段。我不知道我是否会将其包含在 rstest
中,或者在未来更改一些语法。
我没有在许多情况下对其进行测试:如果您有一些它不起作用的情况,请在 rstest
上提交一个工单。
许可证
以下任一许可证下提供:
-
Apache License,版本2.0,(LICENSE-APACHE 或 license-apache-link)
-
MIT许可证 LICENSE-MIT 或 license-MIT-link 可选。
依赖项
~0.5–1MB
~22K SLoC