Rust测试工具库test-binary的使用,test-binary提供二进制测试框架和自动化测试功能
Rust测试工具库test-binary的使用
test-binary是一个用于管理和构建集成测试额外二进制文件的Rust工具库,它允许你将测试用的支持二进制文件作为常规Rust crate来组织。
使用场景
当你需要进行以下类型的测试时,test-binary会非常有用:
- 子进程管理测试
- 进程间通信测试
- 平台工具测试
例如:
- 测试代码对子进程退出状态的处理
- 测试IPC通信时需要一个能发送预设回复的"mock"二进制程序
传统方式的限制
虽然不使用test-binary也能实现类似功能,但有以下限制:
-
使用
src/bin
或[[bin]]
的二进制文件:- 必须与整个crate共享依赖
- 通过
CARGO_BIN_EXE_<name>
环境变量访问
-
示例二进制文件(
examples/
或[[example]]
):- 使用
[dev-dependencies]
- 没有对应的环境变量
- 可能在测试运行时尚未构建完成
- 使用
-
作为工作区crate组织:
test-binary解决方案
test-binary提供了一个简单接口来构建组织在crate单独目录下的额外二进制文件。
目录结构示例
├── Cargo.toml (你的crate的manifest)
├── src
│ └── lib.rs (你的crate的lib.rs)
├── tests
│ └── tests.rs (你的crate的测试)
│
└── testbins (所有额外二进制项目)
├── test-something (第一个额外二进制)
│ ├── Cargo.toml (额外二进制manifest)
│ └── src
│ └── main.rs (额外二进制源文件)
├── test-whatever (另一个额外二进制)
│ ├── Cargo.toml
│ └── src
│ └── main.rs
基本用法
使用build_test_binary("test-something", "testbins")
:
"test-something"
是二进制名称(也是子目录名)"testbins"
是包含测试二进制项目的目录名
示例代码
// 构建测试二进制
let test_bin_path = build_test_binary("does-build", "testbins")
.expect("error building test binary");
// 运行测试二进制
let mut test_bin_subproc = std::process::Command::new(test_bin_path)
.spawn()
.expect("error running test binary");
// 测试你的程序与mock二进制的交互行为
// 例如:发送stdin输入,断言stdout输出,检查IPC或副作用
assert!(test_bin_subproc
.wait()
.expect("error waiting for test binary")
.success());
高级功能
-
Builder API:如果需要设置不同profile或features,或需要更多控制目录结构
-
build_test_binary_once!()
宏:懒加载构建二进制并缓存路径
完整示例
- 首先在项目根目录创建
testbins
目录 - 在
testbins
下创建测试二进制项目,例如test-example
:
// testbins/test-example/src/main.rs
fn main() {
println!("This is a test binary");
std::process::exit(0);
}
- 在
testbins/test-example/Cargo.toml
中添加:
[package]
name = "test-example"
version = "0.1.0"
edition = "2021"
[dependencies]
- 在你的集成测试中使用:
// tests/integration_test.rs
use test_binary::build_test_binary;
#[test]
fn test_with_support_binary() {
let bin_path = build_test_binary("test-example", "testbins")
.expect("Failed to build test binary");
let output = std::process::Command::new(bin_path)
.output()
.expect("Failed to run test binary");
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout), "This is a test binary\n");
}
注意事项
- 可以在测试二进制的
Cargo.toml
中添加空[workspace]
section - 最低支持的Rust版本:1.57
- MIT许可证
1 回复
Rust测试工具库test-binary使用指南
test-binary
是一个Rust测试工具库,专门用于测试二进制程序,提供了一套完整的二进制测试框架和自动化测试功能。它特别适合测试命令行应用程序和其他可执行程序。
主要特性
- 执行二进制程序并捕获输出
- 验证退出状态码
- 检查标准输出和标准错误内容
- 提供断言宏用于测试验证
- 支持测试环境设置和清理
安装方法
在Cargo.toml中添加依赖:
[dev-dependencies]
test-binary = "0.4"
基本使用方法
1. 简单测试示例
use test_binary::build_test_binary;
#[test]
fn test_hello_world() {
// 构建要测试的二进制程序
let bin = build_test_binary!("../path/to/your/binary")
.expect("failed to build test binary");
// 执行程序并捕获输出
let output = bin.output().expect("failed to execute binary");
// 验证退出码是否为0(成功)
assert!(output.status.success());
// 验证标准输出是否包含特定文本
assert!(String::from_utf8_lossy(&output.stdout).contains("Hello, world!"));
}
2. 带参数测试
use test_binary::build_test_binary;
#[test]
fn test_with_args() {
let bin = build_test_binary!("../path/to/your/binary")
.expect("failed to build test binary");
// 执行带参数的程序
let output = bin.args(&["--name", "Rust"]).output().unwrap();
assert!(String::from_utf8_lossy(&output.stdout).contains("Hello, Rust!"));
}
3. 测试错误情况
use test_binary::build_test_binary;
#[test]
fn test_error_case() {
let bin = build_test_binary!("../path/to/your/binary")
.expect("failed to build test binary");
let output = bin.args(&["--invalid-arg"]).output().unwrap();
// 验证程序是否以错误码退出
assert!(!output.status.success());
// 验证错误输出
assert!(String::from_utf8_lossy(&output.stderr).contains("invalid argument"));
}
高级功能
1. 测试环境设置
use test_binary::{build_test_binary, TestBinary};
use tempfile::tempdir;
#[test]
fn test_with_environment() {
// 创建临时目录
let temp_dir = tempdir().unwrap();
let bin = build_test_binary!("../path/to/your/binary")
.current_dir(temp_dir.path()) // 设置工作目录
.env("MY_VAR", "test_value") // 设置环境变量
.expect("failed to build test binary");
let output = bin.output().unwrap();
// 进行断言...
}
2. 测试交互式程序
use test_binary::build_test_binary;
use std::io::Write;
#[test]
fn test_interactive() {
let mut bin = build_test_binary!("../path/to/your/binary")
.spawn()
.expect("failed to spawn binary");
// 向程序标准输入写入数据
bin.stdin.as_mut().unwrap().write_all(b"input data\n").unwrap();
// 等待程序结束
let output = bin.wait_with_output().unwrap();
// 进行断言...
}
最佳实践
- 将测试二进制程序放在项目的
tests/
目录中 - 为每个主要功能编写单独的测试用例
- 使用临时目录和文件进行需要文件系统操作的测试
- 清理测试创建的任何资源
- 测试正常情况和各种错误情况
test-binary
库为Rust程序的二进制测试提供了强大而灵活的工具,特别适合测试命令行应用程序和其他需要执行环境验证的程序。
完整示例demo
下面是一个完整的测试示例,展示如何使用test-binary测试一个简单的命令行程序:
// 测试一个简单的命令行计算器程序
use test_binary::build_test_binary;
use tempfile::tempdir;
#[test]
fn test_calculator() {
// 1. 测试加法功能
let bin = build_test_binary!("../target/debug/calculator")
.expect("failed to build test binary");
let output = bin.args(&["add", "5", "3"]).output().unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "8");
// 2. 测试减法功能
let output = bin.args(&["sub", "10", "4"]).output().unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "6");
// 3. 测试错误情况 - 缺少参数
let output = bin.args(&["add", "5"]).output().unwrap();
assert!(!output.status.success());
assert!(String::from_utf8_lossy(&output.stderr).contains("not enough arguments"));
// 4. 测试文件操作功能
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.txt");
let bin = build_test_binary!("../target/debug/calculator")
.current_dir(temp_dir.path())
.expect("failed to build test binary");
let output = bin.args(&["create-file", "test.txt"]).output().unwrap();
assert!(output.status.success());
assert!(file_path.exists());
}
这个完整示例演示了:
- 测试不同的命令行参数组合
- 验证正常情况和错误情况的输出
- 使用临时目录进行文件系统操作测试
- 检查程序的退出状态码和输出内容