在Rust中编写智能化测试
1.摘要
Rust中的测试函数是用来验证非测试代码能否是依照希冀的形式运转的, 测试函数体通常须要口头三种操作:
本篇文章关键讨论了Rust智能化测试的几种经常出现场景。
2.测试函数详解
在Rust名目工程中, 可以对恣意函数启动智能化测试, 前提是须要在被测试函数上方加上#[test]注解, 而后运转cargo test命令启动函数智能化测试, Rust会查找一切被#[test]注解的函数并智能启动测试。
先看上方一段代码:
#[test]fn add_calc() {let result = 1 + 2;assert_eq!(result, 3);}
在上方的代码中, 我成功了一个加法计算的函数: add_calc(), 将加法结果保留到无法变变量result中, 并经常使用了assert_eq!宏来断言1+2的结果, assert!宏由规范库提供, 在宿愿确保测试环节中一些条件为true时十分有用。在函数上方加上了#[test]注解, 示意该函数将口头智能化测试, 运转: cargo test看下结果:
从测试结果中, 可以看到test add_calc ... ok 这行, 示意该函数测试经过了。
如今我修正下断言的结果, 将代码修正为:
#[test]fn add_calc() {let result = 1 + 2;assert_eq!(result, 4);}
再次运转cargo test命令, 前往结果如下:
可以看到, 计算的结果是3, 但断言相等的条件是等于4, 因此函数口头失败, add_calc()函数智能化测试不经过。
接上去咱们再参与一个函数, 看看在具有多个函数的前提下, 同时具有成功和失败的状况, 代码如下:
#[test]fn add_calc() {let result = 1 + 2;assert_eq!(result, 3);}#[test]fn another_method() {panic!("口头失败,抛出一个意外!")}
在上方的代码中, 参与了一个名为another_method()的函数, 该函数间接经常使用panic!抛出一个意外, 间接表演了函数口头失败的角色, 而上方的add_calc()函数我讲assert_eq!宏修正正确, 将表演口头成功的角色, 经常使用cargo test命令看下结果:
可以看到, add_calc()函数测试没疑问, 前面用绿色ok示意, 而another_method()函数口头失败, 经常使用白色的FAILED标志。
3.自定义失败信息
在上方的案例中, 我经常使用了assert_eq!宏来断言结果, 雷同, 也可以向宏传递一个可选的失败信息参数, 可以在测试失败时将自定义的失败信息一并打印进去, 经常使用自定义信息有个好处, 当测试失败时, 能更好的了解代码究竟出了什么疑问, 看一段上方的代码:
pub fn make_string(name: &str) -> String {format!("Hello,{}!", name)}#[test]fn is_contain_name() {let result = make_string("cargo");assert!(result.contains("cargo"));}
在这段代码中, 定义了一个函数make_string, 该函数接纳一个字符串参数, 并在函数外部经过format!宏格局化字符串后前往, 在函数is_contain_name()中, 传入一个字符串"cargo", assert!会判别make_string()函数前往的字符串中能否会蕴含"cargo"字符串,假设蕴含就是成功的,否则就失败, 这里咱们能预言结果应该是成功的, 测试一下看看:
结果跟咱们预想的一样, 如今再参与一些更详细的变动信息看看, 代码如下:
pub fn make_string(name: &str) -> String {format!("Hello,{}!", name)}#[test]fn is_contain_name() {let result = make_string("rustup");assert!(result.contains("cargo"), "make_string中不蕴含该字符串,值为:`{}`", result);}
我在assert!宏中参与了变量打印, 假设make_string()函数没有前往预期的结果, 那结果究竟是什么,这里咱们将能看到失败要素, 测试结果如下:
从结果可以看到, 函数确实测试失败了, 但咱们看到了关键信息, 失败的要素是由于make_string()函数前往的字符串内容为:Hello,rustup!,这个结果与断言中的result.contains("cargo")结果是不同的, “Hello,rustup!”字符串中并不蕴含"cargo"字符串,所以函数测试失败。
4.审核解体意外
除了经常使用断言宏之外, Rust还提供了一个should_panic用来检测程序中的panic,并且提供了一个名为expected的参数用来自定义信息,看一段上方的代码:
pub fn number_calc(value: i32) -> i32 {let ret_value = 40;if value < 0 {panic!("值必定大于0,传参的值为:{}", value)}return ret_value}#[test]#[should_panic(expected = "传参不能小于0")]fn is_contain_name() {let result = number_calc(-1);}
在number_calc()函数中, 假设判别参数传入的值小于0, 会抛出一个panic, 为了监督是什么要素造成, 在函数is_contain_name()上方经常使用should_panic启动监控, 并经常使用expected参数指定自定义信息, 假设遇到传入的参数小于0, 将触发该信息打印, 经常使用cargo test运转一下看看结果:
从结果可以看到, 确实检测到了panic发生, panic打印了自身的信息, 最后一行shoud_panic也触发了信息, 并打印出失败的要素。
5.经常使用Result<T, E>测试
先看一段上方的代码:
pub fn number_calc(value: i32) -> i32 {let ret_value = 40;if value < 0 {return 30}return ret_value}#[test]fn is_contain_name() -> Result<(), String>{if number_calc(2) == 40 {OK(())}else{Err(String::from("结果不等于40,请审核要素!"))}}
在上方的代码中, is_contain_name()函数的前往类型如今变为:Result<(), String>, 在函数体中, 不同于调用assert_eq!,如今假设测试经过,将前往Ok(()), 在测试失败时, 前往带有String的Err失误。如今传入参数为2, 将显示反常的结果:
如今咱们再传入一个小于0的负值看看,结果如下:
可以看到, 假设经常使用Result<(), String>接纳结果, 当进去失误时, 将前往一个Error,并打印对应的自定义信息。
6.总结
在本篇文章中, 咱们经常使用#[test]注解成功了对指定函数的智能化测试, 经常使用assert!宏对失误启动断言, 在断言中自定义失误显示信息用于检查更详细的失误要素。经常使用了should_panic对panci失误启动了监控, 最后经常使用Result<T, E>代替断言区分成功了代码测试和自定义失误信息打印, 在的实践运行中, 或许还会有一些组合测试的场景发生, 到时刻再详细疑问详细剖析。