Rust 内置测试框架,无需额外依赖。
#[cfg(test)] mod tests { #[test] fn it_works() { let result = 2 + 2; assert_eq!(result, 4); } #[test] fn it_fails() { panic!("这个测试会失败"); } }
| 宏 | 说明 |
|---|---|
assert!(expr) | 断言表达式为 true |
assert_eq!(a, b) | 断言 a == b |
assert_ne!(a, b) | 断言 a != b |
fn add_two(x: i32) -> i32 { x + 2 } #[cfg(test)] mod tests { use super::*; #[test] fn test_add_two() { assert_eq!(4, add_two(2)); assert_ne!(5, add_two(2)); } #[test] fn test_with_message() { let result = add_two(3); assert!( result > 0, "结果应为正数,但得到 {}", result ); } }
用 #[should_panic] 测试应该 panic 的函数:
fn divide(a: i32, b: i32) -> i32 { if b == 0 { panic!("除数不能为零"); } a / b } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "除数不能为零")] fn test_divide_by_zero() { divide(10, 0); } }
#[cfg(test)] mod tests { #[test] fn test_with_result() -> Result<(), String> { if 2 + 2 == 4 { Ok(()) } else { Err("2+2 不等于 4".to_string()) } } }
cargo test # 运行所有测试 cargo test test_name # 运行指定测试 cargo test -- --nocapture # 显示 println! 输出 cargo test -- --test-threads=1 # 单线程运行
#[derive(Debug, Clone, PartialEq)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 0, y: 0 }; let p2 = p1.clone(); println!("{:?}", p1); // Debug 格式化 println!("{}", p1 == p2); // PartialEq 比较 }
use std::fmt; struct Person { name: String, age: u8, } impl fmt::Display for Person { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}({}岁)", self.name, self.age) } } fn main() { let p = Person { name: "小明".into(), age: 25, }; println!("{}", p); // "小明(25岁)" }
#[cfg(target_os = "windows")] fn platform_function() { println!("这是 Windows 系统"); } #[cfg(target_os = "linux")] fn platform_function() { println!("这是 Linux 系统"); } #[cfg(debug_assertions)] fn debug_only() { println!("仅在调试模式下编译"); } fn main() { platform_function(); // 调试模式下才执行 if cfg!(debug_assertions) { println!("调试模式"); } }
优先使用 Option 和 Result 代替需要 null 或抛出异常的设计。
库代码中避免使用 panic!,返回 Result 让调用者决定如何处理错误。
优先使用迭代器链式操作代替手写循环,代码更简洁且性能不输手写。
// 推荐 let sum: i32 = numbers.iter().filter(|x| x % 2 == 0).sum(); // 不如推荐 let mut sum = 0; for x in &numbers { if x % 2 == 0 { sum += x; } }
MyStructmy_functionMAX_VALUE/// 计算两个数的和 /// /// # 示例 /// /// ``` /// let result = add(2, 3); /// assert_eq!(result, 5); /// ``` fn add(a: i32, b: i32) -> i32 { a + b }
cargo doc –open 生成 HTML 文档。
/// 计算斐波那契数列第 n 项(测试驱动开发) fn fib(n: u32) -> u32 { match n { 0 => 0, 1 => 1, _ => fib(n - 1) + fib(n - 2), } } #[cfg(test)] mod tests { use super::*; #[test] fn test_fib() { assert_eq!(fib(0), 0); assert_eq!(fib(1), 1); assert_eq!(fib(2), 1); assert_eq!(fib(3), 2); assert_eq!(fib(10), 55); } #[test] fn test_fib_large() { assert_eq!(fib(20), 6765); } }
#[test] 注解编写测试,cargo test 运行assert!、assert_eq!、assert_ne! 断言#[should_panic] 测试错误路径#[derive(Debug, Clone, PartialEq)] 自动派生常用 trait#[cfg] 条件编译cargo doc、cargo test、cargo clippy 等工具