#pattern-matching #generator #glob #testing #test-files #utest

开发工具 test-generator

Rust 测试生成器:根据文件系统模式枚举条目并为每个条目生成测试函数

6 个版本

0.3.1 2022年12月8日
0.3.0 2019年7月28日
0.2.2 2019年1月23日
0.1.0 2019年1月17日

#293文件系统

Download history 2246/week @ 2024-03-14 2264/week @ 2024-03-21 2818/week @ 2024-03-28 3278/week @ 2024-04-04 2272/week @ 2024-04-11 2792/week @ 2024-04-18 2895/week @ 2024-04-25 2649/week @ 2024-05-02 2804/week @ 2024-05-09 3146/week @ 2024-05-16 3188/week @ 2024-05-23 2740/week @ 2024-05-30 3056/week @ 2024-06-06 2310/week @ 2024-06-13 1899/week @ 2024-06-20 1936/week @ 2024-06-27

9,745 每月下载量
用于 55 crates

MIT/Apache

43KB
56 代码行

MIT License Apache 2.0 Licensed

测试生成器

此 crate 提供 #[test_resources]#[bench_resources] 程序宏属性,用于使用不同的资源输入参数的一个主体生成多个参数化测试。为每个与特定资源位置模式匹配的资源生成一个测试。

以下示例假设包布局如下

├── build.rs
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── res
│   ├── set1
│   │   ├── expect.txt
│   │   └── input.txt
│   ├── set2
│   │   ├── expect.txt
│   │   └── input.txt
│   └── set3
│       ├── expect.txt
│       └── input.txt
├── src
│   └── main.rs
├── benches
│   └── mybenches.rs
└── tests
    └── mytests.rs

这是 示例包 的包布局,这里测试位于文件 mytests.rs 中,基准测试位于文件 mybenches.rs 中;测试和基准测试依赖于 res/ 目录的内容。

构建脚本 build.rs 用于实现条件重新运行,如果资源文件已更改或(更有趣的是)如果资源文件已添加到子目录结构 res/ 中。

示例用法 test

以下测试函数 verify_resource(str) 应为资源文件夹 res/ 中匹配 glob 模式 res/*/input.txt 的所有项执行。

#![cfg(test)]
extern crate test_generator;

use test_generator::test_resources;

#[test_resources("res/*/input.txt")]
fn verify_resource(resource: &str) { 
   assert!(std::path::Path::new(resource).exists()); 
}

对于匹配模式的 3 个测试输入文件,以下是从 cargo test 的输出,对于此示例

$ cargo test

running 3 tests
test tests::verify_resource_res_set1_input_txt ... ok
test tests::verify_resource_res_set2_input_txt ... ok
test tests::verify_resource_res_set3_input_txt ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

示例用法 bench

#![feature(test)] // nightly feature required for API test::Bencher

extern crate test; /* required for test::Bencher */

extern crate test_generator;
use test_generator::bench_resources;

mod bench {
    #[bench_resources("res/*/input.txt")]
    fn measure_resource(b: &mut test::Bencher, resource: &str) {
        let path = std::path::Path::new(resource);
        b.iter(|| path.exists());
    }
}

对于匹配模式的 3 个基准输入文件,以下是从 cargo +nightly bench 的输出,对于此示例

running 3 tests
test bench::measure_resource_res_set1_input_txt ... bench:       2,492 ns/iter (+/- 4,027)
test bench::measure_resource_res_set2_input_txt ... bench:       2,345 ns/iter (+/- 2,167)
test bench::measure_resource_res_set3_input_txt ... bench:       2,269 ns/iter (+/- 1,527)

test result: ok. 0 passed; 0 failed; 0 ignored; 3 measured; 0 filtered out

示例

示例 展示了这些宏的使用和配置,以及 crate build-deps 监控这些资源文件的任何更改和条件重建。

内部

让我们假设以下代码和 3 个匹配模式 "res/*/input.txt" 的文件

#[test_resources("res/*/input.txt")]
fn verify_resource(resource: &str) {
   assert!(std::path::Path::new(resource).exists());
}

此输入资源的生成代码将如下所示

fn verify_resource(resource: &str) {
    assert!(std::path::Path::new(resource).exists());
}
 
#[test]
#[allow(non_snake_case)]
fn verify_resource_res_set1_input_txt() { verify_resource("res/set1/input.txt".into()); }
#[test]
#[allow(non_snake_case)]
fn verify_resource_res_set2_input_txt() { verify_resource("res/set2/input.txt".into()); }
#[test]
#[allow(non_snake_case)]
fn verify_resource_res_set3_input_txt() { verify_resource("res/set3/input.txt".into()); }

注意:尾随的 into() 方法调用允许用户实现 Into 特性以实现自动转换。

条件构建过程

每次添加新的资源文件或现有文件之一发生变化时,应重新运行测试函数生成器。

可以使用 crate build-deps 实现条件构建,扩展
一个 glob 模式,例如 res/*/input.txt,并在 cargo 监控列表中注册这些元素。用户指定要由 cargo 进程监控的目录、一组文件或过滤器模式以检测更改。在发生更改的情况下,将重新运行 Rust 源文件的构建过程。

以下图表说明了将构建脚本集成到条件 cargo 构建过程中的方式。

 <Diagram - Build Script Intregration>

GLOB 过滤模式示例

过滤器可能是一个包含通配符的 glob 模式,例如

"res/*" 将列出 "res/" 目录中的所有文件/目录并监控更改

"res/" - 将将目录本身添加到监控列表,如果添加了新实体则触发重新运行。

"res/**/*.protobuf" 将遍历所有子目录并枚举所有 protobuf 文件。

"res/**" 将遍历所有子目录并枚举所有目录

依赖关系

~2MB
~47K SLoC