8 个版本
0.2.1 | 2024 年 5 月 15 日 |
---|---|
0.1.6 | 2024 年 5 月 12 日 |
0.1.5 | 2024 年 4 月 17 日 |
0.1.4 | 2023 年 8 月 21 日 |
#97 in 测试
每月 104 次下载
96KB
2K SLoC
rtest - 基于资源的测试框架
Rust 中有许多 单元测试 框架。本框架专注于集成测试,这意味着外部软件,不一定是用 Rust 编写的。
rtest
通过使用有状态的资源来工作。它使用宏来构建一个可执行的二进制文件,可以处理所有过滤器并返回一个良好的输出。
想象你正在运营一个网店,并想通过集成测试来验证它是否正常工作。
#[derive(rtest_derive::Resource)]
struct Orderinfo {
item: String,
}
#[derive(rtest_derive::Resource)]
struct Order(String);
#[derive(Debug, thiserror::Error)]
pub enum ShopError {
#[error("{0}")]
Network(#[from] reqwest::Error),
}
impl rtest::TestError for ShopError {}
const SHOP: &str = "http://shop.example.com";
#[rtest_derive::rtest]
async fn place_order(info: Orderinfo) -> Result<Order, ShopError> {
let client = reqwest::Client::new();
let url = format!("{}/v1/order/{}", SHOP, info.item);
let id = client.post(url).send().await?.text().await?;
Ok(Order(id))
}
#[rtest_derive::rtest]
async fn check_order(order: Order) -> Result<Order, ShopError> {
let res = reqwest::get(format!("{}/v1/order/{}", SHOP, order.0)).await?;
assert_ne!(res.status(), 404);
Ok(order)
}
#[rtest_derive::rtest]
async fn cancel_order(order: Order) -> Result<(), ShopError> {
let client = reqwest::Client::new();
let res = client.delete(format!("{}/v1/order/{}", SHOP, order.0)).send().await?;
assert_eq!(res.status(), 200);
Ok(())
}
pub fn main() -> std::process::ExitCode {
let water = Orderinfo {
item: "water".to_string(),
};
let pizza = Orderinfo {
item: "pizza".to_string(),
};
let runconfig = rtest::RunConfig {
context: rtest::Context::default().with_resource(water).with_resource(pizza),
..Default::default()
};
rtest_derive::run!(runconfig)
}
测试框架将知道为了测试 check_order
函数,它首先需要有一个 Order
。但是生成此类订单的唯一方法是通过 place_order
测试。 cancel_order
将消耗订单,使其不再可用。
是的,你可以通过删除所有生成 Order
的测试来欺骗它 - 框架将在运行时注意到这一点并失败。可能存在多个路径可以测试所有函数,如果出现错误,则将输出所采取的路径。假设使用 water
检查订单会失败。框架可能会决定创建另一个带有 pizza
的订单,因为它无法验证删除,测试可能会多次执行。
rtest Results:
[✓]
[✓] delete_file
[✓] create
[✓] create_file
[✓] setup_fileinfo
[x] read
[✓] optional_test
[✓] read_metadata
[x] test_that_should_fail
--- Run: 1/1 ---
Error: test failure: No such file or directory (os error 2)
Logs:
2024-05-14T10:11:59.824647Z INFO filesystem: Wubba Lubba dub-dub
[x] test_that_should_panic - 183ms
--- Run: 1/1 ---
Error: Panic: 'Yes Rico, Kaboom'
at rtest/examples/filesystem/main.rs:88
Stacktrace:
0: rust_begin_unwind
at /rustc/098d4fd74c078b12bfc2e9438a2a04bc18b393bc/library/std/src/panicking.rs:647:5
1: core::panicking::panic_fmt
at /rustc/098d4fd74c078b12bfc2e9438a2a04bc18b393bc/library/core/src/panicking.rs:72:14
2: filesystem::test_that_should_panic
at rtest/examples/filesystem/main.rs:88:5
Logs:
2024-05-14T10:11:59.641008Z INFO filesystem: Kaboom?
Total Tests: 7. Total Runs: 6 Errors: 2
Failed
示例
执行网店,其中一个测试标记为可选,重新运行并显示结果
cargo run --example=webshop -- run --optional-tests=run_test_on_2_servers -o rtest_result.json
cargo run --example=webshop -- re-run rtest_result.json
cargo run --example=webshop -- display rtest_result.json
功能
- 允许任何输入/输出资源
- 自定义错误
- 自定义上下文(尽管很少需要)
- 考虑(过程/资源的)成本的执行模型
- 多线程支持
- 异步支持
- 捕获日志
- 捕获恐慌(对于断言而言是必需的)
- 捕获 println
- 外部日志捕获,例如通过适配器在测试执行期间捕获 Kubernetes 容器的日志。
- Json 输入/输出到持久运行、重试运行、与之前的运行进行比较
- Markdown 输出
依赖关系
~4–18MB
~193K SLoC