测试与高效 Rust 实践

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!("调试模式");
    }
}

优先使用 OptionResult 代替需要 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;
    }
}
  • 类型、Trait:大驼峰 MyStruct
  • 函数、变量、模块:蛇形命名 my_function
  • 常量:全大写下划线 MAX_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 doccargo testcargo clippy 等工具

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • rust/测试与高效实践.txt
  • 最后更改: 2026/06/15 15:44
  • 张叶安