单元测试

The Rust Programming Language认为,单元测试分为3部分,1. 设置好需要的数据和状态 2. 运行需要测试的代码 3. 检查返回的结果是否如预期。

使用cargo test即可运行以下单元测试。

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

  

书中建议单元测试用mod test + #[cfg(test)],集成测试则是单独建立一个tests文件夹,与src为兄弟文件夹,此时就不用#[cfg(test)]。但tests文件夹中的每个文件都被认为是一个用于测试的crate,不再有src中的父子结构。比如test/common.rs可能只放了一些用来辅助测试的函数和结构体声明,也会被当成是测试模块。为了避免这一点,必须要用test/common/mod.rs这样的路径来保存这些辅助代码。

纯binary crate,即没有lib.rs的crate,没法用tests文件夹创建集成测试。

#[ignore]能不运行某个测试

#[test]
fn it_works() {
    assert_eq!(2 + 2, 4);
}

#[test]
#[ignore]
fn expensive_test() {
    // code that takes an hour to run
}

  

assert!,assert_eq!, assert_ne!宏在这种时候非常有用。

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

    #[test]
    fn larger_can_hold_smaller() {
        let larger = Rectangle {
            width: 8,
            height: 7,
        };
        let smaller = Rectangle {
            width: 5,
            height: 1,
        };

        assert!(larger.can_hold(&smaller));
    }
}

 

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        assert!(
            result.contains("Carol"),
            "Greeting did not contain name, value was `{}`",//出错时的提示语
            result
        );
    }

 

should_panic也十分强大,也能和预期的错误信息做比较

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

    #[test]
    #[should_panic]
    fn greater_than_100() {
        Guess::new(200);
    }
}

 

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

    #[test]
    #[should_panic(expected = "Guess value must be less than or equal to 100")]
    fn greater_than_100() {
        Guess::new(200);
    }
}

  

 出错时可以直接返回Result::Error

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err(String::from("two plus two does not equal four"))
        }
    }
}

  

cargo test

cargo test -- --test-threads=1 #并行地运行单元测试
cargo test -- --show-output #显示成功运行的tests的输出
cargo test <test_func_name_pattern> #只运行包含test_func_name_pattern的测试
cargo test -- --ignored #运行被ignored的测试

  

$ cargo test -- --test-threads=1