测试是软件开发中不可缺少的部分。Rust中的测试是一个函数,用于检测非测试代码是否按照期望的方式运行。 测试函数的函数体一般包括三部分:

  1. 准备数据或状态。
  2. 调用需要测试的代码
  3. 对结果进行断言。

使用test属性标注函数,这个函数就成为了测试函数。然后执行cargo test就会构建并执行一个用于测试的可执行文件,这个可执行文件调用使用标注了test属性的函数,并生成统计测试运行成功或失败的相关报告。

当我们使用Cargo新建一个库项目时,它会自动为我们生成一个带有测试函数的测试模块

assert宏

使用assert系列宏来对结果进行断言,断言不通过的话就触发panic。

  • assert!:接收布尔类型参数,为true通过,为false则触发panic。
  • assert_eq!:判断两个参数是否相等。相等则通过。
  • assert_ne!:判断两个参数是否不相等。不相等则通过。

assert!相比,后两个宏能够在不通过的时候将参数值以{:?}形式打印出来。这也就要求使用后两个参数的宏需要满足PartialEqDebug这两个trait约束。

assert!,assert_eq!,assert_ne!==必要参数之后的参数都会一起被传入format!,这就可以自定义错误信息。== 示例如下:

let s = "error msg";
assert!(false, "The error message is: {}", s);

其它两个宏同理。

should_panic检查panic

对于程序中不应该出现的错误,要使用panic触发,测试的时候就需要确保发生这种情况会触发panic,为此提供了should_panic,在有panic发生时通过,没有panic发生时失败。

使用属性标注即可,示例如下:

#[test]
#[should_panic]
fn test_should_panic() {
	panic!("pass");
}

为了保证触发的panic是我们想要的,可以使用expected参数检查panic发生时的错误提示信息是否包含了指定的文字。例如

#[test]
#[should_panic(expected="错误提示要包含的信息")]

使用Result<T,E>编写测试

目前为止,测试不通过都会触发panic。但是也可以使用Result<T,E>在不通过的时候返回一个Err值而不是触发panic。 例如:

#[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"))
		}
	}
}

测试在任何一个步骤返回Err变体的时候都会执行失败。


tags: 测试