Rust宏测试库macrotest的使用,Rust宏测试库macrotest提供高效的宏单元测试和代码覆盖率分析
Rust宏测试库macrotest的使用
macrotest是一个类似于trybuild的Rust测试库,但它允许您测试声明式宏或过程宏是如何展开的。它提供了高效的宏单元测试和代码覆盖率分析功能。
基本使用
首先需要安装cargo-expand。
在您的Crate的Cargo.toml中添加:
[dev-dependencies]
macrotest = "1"
在您的crate的tests/
目录下,创建tests.rs
文件,包含以下代码:
#[test]
pub fn pass() {
macrotest::expand("tests/expand/*.rs");
}
然后创建tests/expand/
目录,并在其中添加Rust源文件。每个源文件都是一个宏展开测试用例。
完整示例
下面是一个完整的示例项目结构:
my_macro_crate/
├── Cargo.toml
├── src/
│ └── lib.rs
└── tests/
├── expand/
│ └── my_macro_test.rs
└── tests.rs
src/lib.rs
// 定义一个简单的宏
#[macro_export]
macro_rules! greet {
($name:expr) => {
println!("Hello, {}!", $name);
};
}
tests/expand/my_macro_test.rs
use my_macro_crate::greet;
fn main() {
greet!("world");
}
tests/tests.rs
#[test]
pub fn test_greet_macro_expansion() {
macrotest::expand("tests/expand/*.rs");
}
运行测试时,macrotest会检查宏是否正确展开,并与预期的结果进行比较。
功能特点
- 宏展开验证:确保宏按照预期展开
- 代码覆盖率:帮助分析宏测试的覆盖率
- 错误处理:可以测试宏的错误情况
- 与cargo-expand集成:利用cargo-expand的功能
最低支持的Rust版本
macrotest要求的最低Rust版本是1.66.0。
许可证
macrotest采用MIT或Apache-2.0双重许可证。
完整示例代码
以下是一个更完整的macrotest使用示例:
Cargo.toml
[package]
name = "my_macro_crate"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dev-dependencies]
macrotest = "1.0.9"
src/lib.rs
// 定义一个更复杂的宏,带有多个匹配模式
#[macro_export]
macro_rules! calculate {
// 加法
($a:expr + $b:expr) => {
$a + $b
};
// 减法
($a:expr - $b:expr) => {
$a - $b
};
// 默认返回0
() => {
0
};
}
// 过程宏示例
#[proc_macro]
pub fn make_answer(_item: proc_macro::TokenStream) -> proc_macro::TokenStream {
"fn answer() -> u32 { 42 }".parse().unwrap()
}
tests/expand/calculate_test.rs
use my_macro_crate::calculate;
#[test]
fn test_calculate_macro() {
let sum = calculate!(10 + 5);
assert_eq!(sum, 15);
let diff = calculate!(20 - 8);
assert_eq!(diff, 12);
let zero = calculate!();
assert_eq!(zero, 0);
}
tests/expand/proc_macro_test.rs
use my_macro_crate::make_answer;
make_answer!();
#[test]
fn test_proc_macro() {
assert_eq!(answer(), 42);
}
tests/tests.rs
#[test]
fn test_macros_expansion() {
// 测试声明式宏
macrotest::expand("tests/expand/calculate_test.rs");
// 测试过程宏
macrotest::expand("tests/expand/proc_macro_test.rs");
}
1 回复
Rust宏测试库macrotest的使用指南
介绍
macrotest是一个专门为Rust宏设计的测试库,它提供了高效的宏单元测试和代码覆盖率分析功能。这个库特别适合测试过程宏(proc-macro)和声明宏(declarative macro),能够帮助开发者确保宏在各种输入情况下的正确行为。
主要特性
- 支持对宏展开结果的精确测试
- 提供详细的代码覆盖率分析
- 能够捕获和测试宏编译错误
- 支持多文件测试场景
- 与标准Rust测试框架无缝集成
完整示例Demo
以下是基于内容中提供的示例,组合而成的完整演示项目:
- 首先创建项目并添加依赖:
cargo new macro_demo
cd macro_demo
- 编辑
Cargo.toml
文件:
[package]
name = "macro_demo"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true # 如果是过程宏需要这个
[dev-dependencies]
macrotest = "1.0"
- 创建宏实现文件
src/lib.rs
:
// 声明宏示例
#[macro_export]
macro_rules! greet {
($name:expr) => {
format!("Hello, {}!", $name)
};
}
// 过程宏示例
use proc_macro::TokenStream;
#[proc_macro_derive(MyDerive)]
pub fn my_derive(input: TokenStream) -> TokenStream {
// 简单的derive宏实现
"impl Example { fn new() -> Self { Self { field: String::new() } } }"
.parse()
.unwrap()
}
- 创建测试目录结构和测试文件:
tests/
├── expand/
│ ├── greet.rs
│ └── derive.rs
├── compile-errors/
│ └── invalid_greet.rs
├── greet_test.rs
├── compile_error_test.rs
└── derive_test.rs
- 编写测试文件
tests/greet_test.rs
:
use macrotest::expand;
#[test]
fn test_greet_macro() {
// 测试greet宏的展开
expand!("tests/expand/greet.rs");
}
- 编写宏输入文件
tests/expand/greet.rs
:
use macro_demo::greet;
fn main() {
let _ = greet!("World"); // 测试正常输入
}
- 编写错误测试文件
tests/compile_error_test.rs
:
use macrotest::compile_error;
#[test]
fn test_invalid_greet() {
// 测试宏的错误输入
compile_error!("tests/compile-errors/invalid_greet.rs");
}
- 编写错误输入文件
tests/compile-errors/invalid_greet.rs
:
use macro_demo::greet;
fn main() {
let _ = greet!(); // 缺少参数,应该报错
}
- 编写过程宏测试文件
tests/derive_test.rs
:
use macrotest::expand;
#[test]
fn test_derive_macro() {
// 测试derive宏的展开
expand!("tests/expand/derive.rs");
}
- 编写derive宏输入文件
tests/expand/derive.rs
:
use macro_demo::MyDerive;
#[derive(MyDerive)]
struct Example {
field: String,
}
fn main() {}
- (可选)创建配置文件
tests/macrotest.toml
:
# 设置测试环境
rustc_args = ["--edition=2021"]
# 设置宏展开后代码的格式化选项
pretty = true
- 运行测试:
# 首次运行生成预期结果
UPDATE_EXPECT=1 cargo test
# 后续正常测试
cargo test
# 收集覆盖率
cargo install cargo-tarpaulin
cargo tarpaulin --tests --features macrotest/coverage
注意事项
- 确保测试文件位于
tests/
目录下 - 对于过程宏,需要在
Cargo.toml
中正确声明proc-macro特性 - 更新预期结果时,请仔细检查生成的代码
- 复杂的宏可能需要更详细的测试用例来覆盖所有边界情况
macrotest为Rust宏提供了强大的测试能力,能够显著提高宏代码的质量和可靠性。