Rust 测试简介
Rust 是一种以安全性和性能著称的系统编程语言。然而,即使是最可靠的代码也需要验证。在 Rust 中,测试不仅仅是一个选项,而是开发过程中不可或缺的一部分。得益于 Cargo 内置的测试支持,您可以轻松编写和运行单元测试、集成测试和端到端测试。在本文中,我们将通过实际示例来讲解所有三个级别的测试。
Rust 中的单元测试:可靠性的基础
单元测试(模块测试)在隔离环境中验证单个函数和方法。在 Rust 中,它们通常直接放在代码文件中,位于一个特殊的 tests 模块内。
单元测试的结构
每个单元测试都是一个带有 #[test] 属性的函数。在函数内部,您可以使用 assert!、assert_eq! 和 assert_ne! 宏来验证结果。
// src/math.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err(String::from("Division by zero"))
} else {
Ok(a / b)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_divide_success() {
let result = divide(10.0, 2.0);
assert!(result.is_ok());
assert_eq!(result.unwrap(), 5.0);
}
#[test]
fn test_divide_by_zero() {
let result = divide(10.0, 0.0);
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "Division by zero");
}
}
请注意 #[cfg(test)] 属性。它告诉编译器仅在构建测试时包含此模块。这可以节省最终二进制文件的编译时间。
运行单元测试
要运行项目中所有测试,请使用以下命令:
cargo test
您还可以按名称运行特定测试:
cargo test test_add
或者按关键字过滤测试:
cargo test divide
Rust 中的集成测试:验证交互
集成测试验证应用程序的不同模块如何协同工作。与单元测试不同,它们位于项目根目录级别的单独 tests/ 文件夹中。
集成测试的结构
创建一个文件 tests/integration_test.rs:
// tests/integration_test.rs
use my_project::math; // 假设库名为 my_project
#[test]
fn test_add_and_divide() {
let sum = math::add(10, 5);
let result = math::divide(sum as f64, 3.0).unwrap();
assert_eq!(result, 5.0);
}
#[test]
fn test_complex_calculation() {
let a = math::add(100, 200);
let b = math::add(50, 50);
let result = math::divide(a as f64, b as f64).unwrap();
assert_eq!(result, 3.0);
}
tests/ 中的每个文件都作为独立的 crate 编译。这意味着您可以为不同的场景拥有多个测试文件。
集成测试的公共模块
如果您需要所有集成测试的公共工具,请创建一个子文件夹 tests/common/,其中包含文件 mod.rs:
// tests/common/mod.rs
pub fn setup() {
// 初始化测试环境
println!("Setting up test environment...");
}
并在测试中使用它:
// tests/integration_test.rs
mod common;
#[test]
fn test_with_setup() {
common::setup();
// 您的测试
}
Rust 中的端到端测试:全面深入
端到端测试验证整个应用程序从开始到结束的工作情况。在 Rust 中,这通常使用外部