33·工程化入门

单元测试

单元测试

学习目标

  1. 掌握 #[test] 属性
  2. 掌握断言宏
  3. 理解测试组织结构

核心概念

基本测试

// src/lib.rs
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
    }

    #[test]
    fn test_add_negative() {
        assert_eq!(add(-1, 1), 0);
    }

    #[test]
    #[should_panic]
    fn test_panic() {
        panic!("expected panic");
    }

    #[test]
    fn test_with_result() -> Result<(), String> {
        let result = add(2, 2);
        if result == 4 {
            Ok(())
        } else {
            Err(format!("expected 4, got {}", result))
        }
    }
}

断言宏

#[cfg(test)]
mod tests {
    #[test]
    fn assertions() {
        assert!(true);                   // 真值断言
        assert_eq!(2 + 2, 4);           // 相等断言
        assert_ne!(2 + 2, 5);           // 不等断言

        // 带消息
        assert!(true, "should be true");
        assert_eq!(2 + 2, 4, "math works");

        // 浮点数
        assert!((0.1_f64 + 0.2 - 0.3).abs() < 1e-10);
    }
}

运行测试

cargo test                      # 运行所有测试
cargo test test_add             # 运行名字包含 test_add 的测试
cargo test -- --show-output     # 显示 println! 输出
cargo test -- --test-threads=1  # 单线程运行
cargo test --lib                # 只运行库测试

实践练习

练习 1:栈测试

pub struct Stack<T> {
    elements: Vec<T>,
}

impl<T> Stack<T> {
    pub fn new() -> Self {
        Stack { elements: Vec::new() }
    }

    pub fn push(&mut self, item: T) {
        self.elements.push(item);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.elements.pop()
    }

    pub fn peek(&self) -> Option<&T> {
        self.elements.last()
    }

    pub fn is_empty(&self) -> bool {
        self.elements.is_empty()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_new_stack_is_empty() {
        let stack: Stack<i32> = Stack::new();
        assert!(stack.is_empty());
    }

    #[test]
    fn test_push_and_pop() {
        let mut stack = Stack::new();
        stack.push(1);
        stack.push(2);
        assert_eq!(stack.pop(), Some(2));
        assert_eq!(stack.pop(), Some(1));
        assert_eq!(stack.pop(), None);
    }

    #[test]
    fn test_peek() {
        let mut stack = Stack::new();
        stack.push(42);
        assert_eq!(stack.peek(), Some(&42));
        assert_eq!(stack.pop(), Some(42));
        assert_eq!(stack.peek(), None);
    }
}

小结

语法用途
#[test]标记测试函数
#[cfg(test)]条件编译测试模块
assert!真值断言
assert_eq!相等断言
#[should_panic]期望 panic
cargo test运行测试

练习编辑器

rust
Loading...