rust学习十二、测试

打印 上一主题 下一主题

主题 812|帖子 812|积分 2436

测试从来不是一件简单的事变,我本人深有体会!
书本作者引用了很重要的话:软件测试是证明 bug 存在的有效方法,而证明其不存在时则显得令人绝望的不敷  (Edsger W. Dijkstra 在其 1972 年的文章【谦卑的程序员】(“The Humble Programmer”))
注:Edsger W. Dijkstra在1972得到图灵奖
 
本人学过一些语言,看过不少雷同书籍,但是在书籍中间部分就让入门者注意测试,的确是挺特别的。
这充实地体现了作者对测试的重视。
既然专家都这么注意测试,我辈自当也必要格外注意。Rust由于其语言特性,应该是必要更加重视测试!
 
把测试当做无足轻重,或者认为不必要什么技术水平的,都是不专业的举动!it新人或者一些水平有题目的常常会有这个方面的看法!
本章节的内容比力多,但只要按照作者的例子作一遍,那么根本能够把握!
rust测试必要用到cargo test命令,这个命令有许多选项,部分会在本章节中提到,还有许多是没有提到的。
把test命令的各个选项都认识下,也必要耗费不少时间!
 
本文所涉及到内容都是入门级别的,属于根本的粗浅的。但是把握这些根本上已经可以做必要的测试了。
至于测试技巧,是别的一门学问了,和rust没有关系。
 
一、编写单元测试代码


本例模仿书上的,在库中编写单元测试代码。
按照惯例:创建一个tests模块,并在tests下编写测试代码
关键词:
#[cfg(test)] -- 告诉编译器运行的时候不要编辑
#[test]   --  告诉编译器这是一个测试单元
#[should_panic] - 告诉测试程序,如果不出意外就是失败函数: assert_eq!,assert_ne!,assert!
二、控制测试

关键题目:

  • 如何控制并发
  • 如何控制必要测试的
  • 如何忽略,或者如何只测试被标志为忽略的
控制并发
默认是多线程,但也可以通过一下方式指定必要的线程
-- --test-threads=n控制测试目的
cargo test xxx ,xxx是测试的名称,即单元测试方法的名称.属于模糊匹配cargo test --test xxx 指定集成测试的文件名,模糊匹配忽略
#[ingore] -- 用于标志测试方法为被忽略cargo test -- --ignored 只测试被忽略的
三、测试的组织结构

如何做单元测试
固定的规范-- 使用#[cfg(test)] 标志测试代码,并使用#[test]标志测试函数。其次模块通常也命名位tests如何做集成测试

创建和src同i的目录tests,在tests下放恣意个rs,每个rs都是一个单元包
每个单元包都可以应用tests的公共模块。
 
集成测试中的公共模块
使用老的模块界说规范:目录+mod.rs
如上图,haha模块在tests/haha下,其下有mod.rs
 
四、完整测试代码和示例


这个例子是基于一个库项目,有三个文件:
src/lib.rs 库 ,单元测试文件
tests/itest1.rs 集成测试文件之一
tests/haha/mod.rs 集成测试的模块haha
lib.rs
  1. pub fn add(left: u64, right: u64) -> u64 {
  2.     left + right
  3. }
  4. #[cfg(test)]
  5. mod tests {
  6.     use super::add;
  7.     //测试宏 assert_eq!
  8.     #[test]
  9.     fn it_works1() {
  10.         let result = add(2, 2);
  11.         assert_eq!(result, 4);
  12.     }
  13.     //测试宏 assert!.并测试自定义的错误信息
  14.     #[test]
  15.     fn it_works2() {
  16.         let result = add(1, 3);
  17.         assert!(result==5,"1+3={},而不是5",result);
  18.     }
  19.     //测试宏 assert_ne!
  20.     #[test]
  21.     fn it_works3() {
  22.         let result = add(1, 4);
  23.         println!("这一句将在--show-output 的时候打印:1+4={}",result);
  24.         assert_ne!(result,6);
  25.     }
  26.     //测试fail!
  27.     #[test]
  28.     #[should_panic]
  29.     fn it_fail() {
  30.         //fail!("this test will fail");
  31.         let result = add(1, 4);
  32.         assert_eq!(result,6);
  33.     }
  34.     #[test]
  35.     #[should_panic]
  36.     fn access_outof_range() {
  37.         let mut v = vec![1,2];  
  38.         v[2] = 3;
  39.     }   
  40.     //如果返回Err,则测试失败
  41.     #[test]
  42.     fn test_result()->Result<(),String> {
  43.         if 1==2 {
  44.             Ok(())
  45.         } else {
  46.             Err("error".to_string())
  47.         }
  48.     }
  49.     #[test]
  50.     #[ignore]
  51.     fn test_ignore() {
  52.         assert_eq!(1,2, "1!={}",2);
  53.     }
  54. }
复制代码
 
itest1.rs
  1. use lzfmath::*;
  2. mod haha;
  3. #[test]
  4. fn itest_add() {
  5.     haha::haha();
  6.     assert_eq!(add(1, 2), 3);
  7. }
复制代码
 
mod.rs
  1. pub fn haha(){
  2.     println!("哈哈!");
  3. }
复制代码
 
 

4.1尺度单元测试效果


4.2设置并发和查看尺度输出


 
4.3只测试it开头的单元测试


 
4.4只测试被忽略的


 
4.5集成测试+集成测试模块


 
五、小结

   代码测试重要有三个部分内容:
   1.如何编写测试
     重要涉及到几个编译标志/指令和几个函数/宏,Result
     编译指令
       a.#[cfg(test)]     一个条件编译指令,用于指定紧随其后的代码块或项(如函数、模块等)仅在测试环境下编译
       b.#[test]          函数测试标志,cargo的测试的时候,会找出有这些标志的函数,并执行测试
       c.#[should_panic]  函数测试标志,标志的函数会期待panic,如果函数没有panic就会测试失败。
     函数
       a.assert!      断定表达式为真。如果为真就是乐成
       b.assert_eq!   断定两个值是否相等。如果相等就是乐成
       c.assert_ne!   断定两个值是否不相等。如果不相等就是乐成
       d.assert_matches! 断定表达式匹配模式。如果匹配就是乐成.特别实用于枚举和结构等类型
       f.fail!        断定测试失败,并打印出字符串
       assert类函数,可以在尺度参数之外再传递其它参数,比如失败时打印的字符串。rust会调用格式化字符串,并打印出参数。
     Result类型
       a.Result  枚举类型,表示乐成或失败。T为乐成时的类型,E为错误类型
   2.如何控制测试
     默认的测试举动
       a.cargo test 在测试模式下编译代码并运行天生的测试二进制文件
       b.cargo test 产生的二进制文件的默认举动是并发运行全部的测试,并截获测试运行过程中产生的输出,阻止它们被显示出来,使得阅读测试效果相干的内容变得更容易
     
     如何控制(控制cargo test的举动)
       a.控制并发  -- --test-threads=1  只允许一个线程运行测试
       b.控制输出  -- --show-output   显示测试运行过程中产生的输出。如许可以输出通过部分的打印输出
       c.控制测试    只运行指定名称的测试 。注意这是模糊匹配   
                   add  测试包含add的测试。即cargo test add
                  --test xxx 指定具体文件名  cargo test --test itest1    测试文件名带itest1的测试
     忽略项目
       a.#[ignore]   在代码中标志必要忽略的内容
       b.测试被忽略项目  -- --ignored    ,如许只会测试被标志为#[ignore]的内容
 
     示例
       cargo test result  -- --test-threads=2  --show-output   在开启两个线程的情况下,测试包含result的测试,同时那些产生的输出也会显示出来
       cargo test -- --ignored  测试被标志为#[ignore]的内容
   3.测试的组织结构  
     如何作单元测试
       a.固定的规范-- 使用#[cfg(test)] 标志测试代码,并使用#[test]标志测试函数。其次模块通常也命名位tests
       
     如何作集成测试
       a.在项目下创建tests目录,然后在该目录下创建测试文件  。注意tests目录和src是同级的. 这个目录应该是可以是别的,也允许以通过test的选项来指定
       b.在测试目录tests可以创建恣意多个文件,cargo会把每一个文件当做一个单元包举行测试
       c.运行 cargo test即可,但是如许会把单元测试一起执行。
       d.通过指定集成测试文件的方式,可以只运行指定的测试文件 cargo test --test itest1.也可以通过指定测试名称的方式
         carggo test xxx   
       综合起来,cargo test --test xxx 也许是更好的选择。
     
     集成测试的公共模块
       a.必须先创建一个目录,假设是haha
       b.在haha下创建mod.rs文件
       c.tests下的其它rs可以调用haha,并且haha不会被测试。haha的内容只会被集成测试代码调用。
       也就是说集成测试目录下的模块组织方式,反而使用的是旧的模块界说规范:基于目录+mod.rs
 
     为什么很多项目既有src/main.rs,src/lib.rs
       这都是为了方便测试。
       引入在集成测试中导入src/main.rs的模块并不容易。 main.rs是一个二进制文件,而lib.rs是库。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连密封材料

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表