14.编写自动化测试(上)

标题

  • 一、如何编写测试
    • 1.1 一些概念
    • 1.2 测试函数剖析
    • 1.3 使用assert!宏检查结果
    • 1.4 使用assert_eq!和assert_ne!宏来测试相等
      • 1) assert_eq!
      • 2) assert_ne!
    • 1.5 使用 should_panic 检查 panic
  • 二、将 Result<T, E> 用于测试

一、如何编写测试

1.1 一些概念

Rust 中的测试函数体通常执行如下三种操作:

  1. 设置任何所需的数据或状态;
  2. 运动需要测试的代码;
  3. 断言其结果是我们所期望的;

Rust提供的专门用来编写测试的功能:

  • test属性;
  • 一些宏;
  • should_panic属性;

1.2 测试函数剖析

  • Rust中的测试就是一个在fn行之间加上#[test]属性标注的函数;
  • cargo test命令执行时,会运行被标记了#[test]的函数,并报告是否运行通过;

创建新的库项目

cargo new adder --lib
  • 源码只有src/lib.rs文件,其内容如下
pub fn add(left: usize, right: usize) -> usize {
    left + right
}

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

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}
  • fn函数之前的#[test]表明这是一个测试函数;
  • tests是一个普通的内部模块,要测试外部的中的add函数,因此要用use引入;
  • 函数体通过使用assert_eq!宏来断言2加2等于4,这是测试用例的典型格式;
  • 使用cargo test运行测试用例;
    在这里插入图片描述
  • 结果显示:1 passed; 0 failed;…… 说明所有测试都通过了;
  • tests::it_works中的it_works是测试函数的名字;
  • ignored表示忽略的测试用例,filtered out表示过滤需要运行的测试,measured是针对性能测试的(目前只能用于Rust开发版(nightly Rust,详阅https://doc.rust-lang.org/unstable-book/library-features/test.html);
  • Doc-tests adder 是所有文档测试的结果;

再加一个失败的测试项

#[cfg(test)]
mod tests {
	……
	
    #[test]
    fn another() {
        panic!("Make this test fail");
    }
}

运行时会提示it_works运行成功而another运行失败
在这里插入图片描述

1.3 使用assert!宏检查结果

  • assert!宏由标准库提供,在希望确保测试中一些条件为true时非常有用;
  • 需要向assert!宏提供一个求值为布尔值的参数;
  • 如果值是true,则什么也不做,同时测试通过;
  • 如果值是false,assert!宏调用panic!宏,同时测试失败;
  • assert!最后附上错误提示字符串,以便更好定位 (可选)

为前面写的Rectangle结构体和一个can_hold添加一个测试用例,看看8*7的实例能否放下5*1的实例;

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

#[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), "运行失败!");
    }
}

测试结果为通过
在这里插入图片描述

1.4 使用assert_eq!和assert_ne!宏来测试相等

  • 标准库提供assert_eq!assert_ne!宏比较相等或不相等;
  • 当断言失败时也会打印出这两个值具体是什么,以便于观察测试为什么失败;
  • 依然可以自定义断言失败时候的输出信息;
  • 宏参数中的左右两个值的顺序并不重要;

1) assert_eq!

fn add_two(a: i32) -> i32{
    a + 2
}

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

    #[test]
    fn it_adds_two() {
        let result = add_two(2);
        assert_eq!(4, result);
    }

    #[test]
    fn it_adds_two2() {
        let result = add_two(1);
        assert_eq!(4, result, "4 is not equal {}.", result);
    }
}

输出结果
在这里插入图片描述

  • it_add_two运行通过;
  • it_adds_two2运行失败,左值为4右值为3,因此不相等,断言失败;
  • 输出了我们自己定义的错误提示信息:4 is not equal 3

2) assert_ne!

  • assert_ne!宏在传递给它的两个值不相等时通过;
  • 在代码按预期运行,我们不确定值会是什么,不过能确定值绝对不会是什么的时候,这个宏最有用处;

TIPS:

  • 如果一个函数保证会以某种方式改变其输出,不过这种改变方式是由运行测试时是星期几来决定的,这时最好的断言可能就是函数的输出不等于其输入。
  • assert_eq! 和 assert_ne! 宏在底层分别使用了 == 和 !=。
  • 当断言失败时,这些宏会使用调试格式打印出其参数,这意味着被比较的值必需实现了PartialEq 和 Debug trait
  • 对于自定义的结构体和枚举,需要实现PartialEq才能断言他们的值是否相等。
  • 需要实现Debug才能在断言失败时打印他们的值。
  • 由于这两个 trait 都是派生 trait,因此通常可以直接在结构体或枚举上添加#[derive(PartialEq, Debug)]标注。
  • 更多关于这些和其他派生 trait 的详细信息请参阅 这里 ;

1.5 使用 should_panic 检查 panic

  • 可以对测试程序添加#[should_panic]属性;
  • 即使满足条件也不会触发程序中的panic!宏;
fn add_two(a: i32) -> i32{

    if a < 0 {
        panic!("Par a must larger 0 but a is {}", a);
    }
    a + 2
}

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

    #[test]
    #[should_panic]
    fn it_adds() {
        let result = add_two(-5);
        assert_eq!(4, result);
    }
}
  • 当add_two传入的值小于0时会触发panic!宏;
  • 但是给it_adds额外添加一个#[should_panic]属性时依然会通过测试;

缺点

  • 添加should_panic属性之后的测试结果只是告诉我们代码产生了 panic;
  • should_panic在一些不是我们期望的原因而导致panic时也会通过 ;
  • 可以添加expected参数来关注我们所期待导致的panic;
fn add_two(a: i32) -> i32{

    if a < 0 {
        panic!("Par a must larger than 0 but a is {}", a);
    }else if a > 100{
        panic!("Par a must less than 100 but a is {}", a);
    }
    a + 2
}

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

    #[test]
    #[should_panic(expected = "Par a must larger than 0 but a is")]
    fn it_adds() {
        let result = add_two(101);
        assert_eq!(4, result);
    }
}
  • 为it_adds添加的[should_panic(expected = "Par a must larger than 0 but a is")]属性代表只有当panic!宏提示的字符串不包含Par a must larger than 0 but a is时会出错。
  • 传给add_two函数的值是101,因此走的是else if分支,panic!宏提示的错误是Par a must less than 100 but a is,这不包含expected中的子串,因此会报错。

在这里插入图片描述

二、将 Result<T, E> 用于测试

#[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"))
        }
    }
}
  • it_works 函数的返回值类型为Result<(), String>
  • 测试通过时返回 Ok(()),在测试失败时返回带有 String 的 Err;
  • 这样编写测试来返回 Result<T, E> 就可以在函数体中使用问号运算符,如此可以方便地编写测试,如果其中的任何操作返回 Err 值,则测试将失败;
  • 不能使用#[should_panic],要断言操作返回 Err 值,需要使用assert!(value.is_err())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/717090.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库原理(数据库设计)——(3)

一、数据库设计概述 1.数据库设计的基本任务和目标 基本任务 根据用户的信息需求、数据库操作需求&#xff0c;设计一个结构合理、使用方便、效率高的数据库。 设计目标 满足用户的应用要求&#xff1b;准确模拟现实世界&#xff1b;能背某个DBMS&#xff08;数据库管理系统…

重磅!草料模板库更新,新增签到报名和旅游模板

本次共更新5个签到报名场景模板&#xff0c;以及6个旅游场景模板。 所有模板内容均可自定义修改&#xff0c;并可免费使用。 签到报名场景 签到报名场景更新了 活动报名、大型活动会议报名、展会邀请函、专题讲座活动报名和技能培训邀约报名 5个模板&#xff0c;基于不同的会…

前端学习-day10

文章目录 01-体验平面转换02-平移效果03-绝对定位元素居中04-案例-双开门06-转换旋转中心点07-案例-时钟-转换原点08-平面转换-多重转换09-缩放效果10-案例-按钮缩放11-倾斜效果12-渐变-线性13-案例-产品展示14-渐变-径向15-综合案例-喜马拉雅 01-体验平面转换 <!DOCTYPE h…

选专业还是选学校:分数限制下的抉择

大家好&#xff0c;我是DX3906 在高考的分数公布后&#xff0c;许多考生和家长都会面临一个棘手的问题&#xff1a;在分数限制下&#xff0c;是选择一个好专业&#xff0c;还是选择一个好学校&#xff1f;这个问题没有标准答案&#xff0c;因为每个人的情况和目标都不尽相同。本…

元宇宙三维虚拟场景制作平台为数字化营销发展注入了新的活力

​在数字化浪潮的推动下&#xff0c;我们迎来了全新的3D元宇宙场景在线制作编辑器&#xff0c;为您带来前所未有的创作体验。这款轻量级实时创作工具&#xff0c;让您轻松构建丰富的3D元宇宙场景&#xff0c;实现全网全终端的展示。 3D元宇宙场景在线制作编辑器拥有海量的3D模…

微型丝杆的耐用性和延长使用寿命的关键因素!

无论是机械设备&#xff0c;还是精密传动元件&#xff0c;高精度微型丝杆是各种机械设备中不可或缺的重要组件。它的精度和耐用性直接影响着工作效率和产品品质&#xff0c;在工业技术不断进步的情况下&#xff0c;对微型丝杆的性能要求也越来越高&#xff0c;如何提升微型丝杆…

reverse-android-淘最热点so

资源 1. com.maihan.tredian 2021版 淘最热点 2. 该 app 没有加壳 ,也没混淆。 登录抓包 POST: https://api.taozuiredian.com/api/v1/auth/login/sms POST /api/v1/auth/login/sms HTTP/1.1 Content-Type: application/json Connection: close Charset: UTF-8 User-Agen…

C++中list容器常用接口

list的基本定义: 在C中&#xff0c;list被定义为一个双向链表容器。它是标准模板库&#xff08;STL&#xff09;中的一部分&#xff0c;位于<list>头文件中。 list是一个通用模板类&#xff0c;可以存储任何类型的数据&#xff0c;因此它是一个模板类。它实现了双向链表数…

Web应用安全测试-综合利用(一)

Web应用安全测试-综合利用&#xff08;一&#xff09; 文章目录 Web应用安全测试-综合利用&#xff08;一&#xff09;1.跨站脚本攻击&#xff08;XSS&#xff09;漏洞描述测试方法GET方式跨站脚本Post方式跨站脚本 风险分析风险等级修复方案总体修复方式对于java进行的web业务…

Pycharm怎么默认终端连接远程服务器

因为经常需要从宿舍到学校内通勤&#xff0c;期间所有连接都会中断&#xff0c;所以每次开SSH特别麻烦&#xff0c;每次终端自动切换到本地&#xff1a; 每次都得点一下Start SSH Session 想要默认终端连接远程服务器&#xff0c;需要点File->Setting->Tools->SSH T…

详细描述拍立淘接口的实现过程,包括接口设计、开发、测试、部署等关键步骤

拍立淘接口的实现过程可以详细分为以下几个步骤&#xff1a; 注册与权限获取&#xff1a; 注册成为阿里巴巴开放平台开发者&#xff0c;并创建应用。获取API的调用权限和密钥&#xff08;如AppKey和AppSecret&#xff09;&#xff0c;这些密钥将用于后续的身份验证和请求签名。…

SmartEDA体验记:探索电路设计新纪元,乐趣无限!

在科技日新月异的今天&#xff0c;电路设计早已不再是专业人士的专属领域。随着智能化工具的不断发展&#xff0c;普通人也能轻松体验到电路设计的乐趣。今天&#xff0c;就让我带大家走进SmartEDA的世界&#xff0c;一起感受前所未有的电路设计之旅。 SmartEDA&#xff0c;作为…

Ubuntu如何添加用户环境变量

一&#xff0c;简介 在工作中&#xff0c;需要将某个环境变量添加到用户环境变量中&#xff0c;方便使用。 要将 SOF_WORKSPACE~/work/sof 添加到用户的环境变量中&#xff0c;需要将该设置添加到用户的 shell 配置文件中&#xff0c;例如 ~/.bashrc&#xff08;对于 Bash 用…

IEPL专线和IPLC专线有什么区别?

IEPL和IPLC是两种广泛用于国际通信的专线服务&#xff0c;IEPL是一种以太网专线服务&#xff0c;IPLC是一种传统的专线服务&#xff0c;它们在某些方面有相似之处&#xff0c;但也存在一些关键的区别。下面是IEPL和IPLC的主要区别: 1.技术和定义: IEPL: 技术: IEPL是一种以太…

推广结算统计,Xinstall助您轻松掌握每一分投入与回报!

在移动互联网时代&#xff0c;App的推广与运营离不开精准的数据支持和高效的结算系统。然而&#xff0c;面对众多的推广渠道和复杂的结算流程&#xff0c;如何确保每一分投入都能得到合理的回报&#xff0c;成为了众多企业和开发者关注的焦点。今天&#xff0c;我们就来聊聊如何…

猫:“喵不知道不喝水要打针”,主食冻干、主食罐头骗水远离缺水

猫咪如果长期不喝水&#xff0c;一直处于缺水状态&#xff0c;会对健康产生很大的影响。可能会导致便秘、上火、尿黄、尿少等。在高温的夏季&#xff0c;猫还可能会因为脱水而出现中暑的情况&#xff0c;严重时甚至会导致死亡。此外&#xff0c;长期饮水不足的猫咪也容易患上泌…

SaaS案例分享:成功构建销售渠道的实战经验

面对SaaS产品推广的难题&#xff0c;你是否曾感到迷茫&#xff0c;不知如何选择有效的销售渠道&#xff1f;Shopify独立站联盟营销或许能为你提供新的思路。Shopify作为领先的电商解决方案提供商&#xff0c;其独立站功能为众多商家提供了强大的在线销售平台。而联盟营销&#…

【SpringBoot整合系列】SpringBoot整合kinfe4j

目录 kinfe4j与Swagger的区别 SpringBoot2.x整合kinfe4j1.添加依赖2.启动类注解3.创建Knife4J配置类4.实体类5.接口admin访问 api访问 常用注解汇总SpringBoot3.x整合Kinfe4j启动报错解决1.更换依赖2.启动类3.配置4.配置类5.参数实体类6.接口admin访问 api访问 各版本注解参照 …

SQL综合查询-学校教务管理系统数据库

一、一个完整的数据查询语句的格式 SELECT 【ALL|DISTINCT】<目标列表达式>【&#xff0c;<目标列表达式2>&#xff0c;...】 FROM <表名或视图名1>【&#xff0c;<表名或视图名2>&#xff0c;...】 【WHERE <元组选择条件表达式>】 【GROUP…

AI大模型浪潮席卷而来,你准备好乘风破浪成为行业翘楚了吗?

揭秘AI大模型浪潮&#xff1a;你准备好乘风破浪了吗&#xff1f; 在繁华的都市中&#xff0c;程序员小李一直默默耕耘在代码的海洋中。然而&#xff0c;随着AI大模型技术的迅猛发展&#xff0c;他发现自己仿佛置身于一场没有硝烟的战争中。身边的同事纷纷掌握了新技术&#xf…