Rust编程-编写自动化测试

编写单元测试步骤:

        1. 准备所需的数据        

        2. 调用需要测试的代码

        3. 断言运行结果与我们所期望的一致

Rust的test元数据:

        #[cfg(test)]是一个属性宏(attribute macro)。用于控制特定的代码段仅在测试环境中编译。

#[cfg(test)]
mod tests {// 测试函数#[test]fn my_test() {// 测试代码}
}

     #[cfg(test)]的作用是确保tests模块内的代码仅在执行cargo test命令时被编译和运行。

        cfg还可以用于更复杂的条件编译场景:

#[cfg(target_os = "linux")]
fn os_specific_function() {// Linux-specific code
}#[cfg(target_os = "windows")]
fn os_specific_function() {// Windows-specific code
}

 cfg指定目标操作系统,选择性的编译代码

        #[test] 关键字:表示是测试函数

        测试函数:将#[test] 添加到fn关键字的上一行就将函数转变为测试函数

单元测试执行命令:

        cargo test命令来运行测试

        这个命令会构建并执行一个用于测试的可执行文件,该文件在执行过程中会逐一调用所有标注了test属性的函数,并生成统计测试运行成功或失败的报告。

        Rust能够编译在API文档中出现的任何代码示例

assert_eq! 宏

 assert_eq!(2 + 2, 4);

        用于断言两个值相等。如果不相当则panic,单元测试失败 

assert_ne!宏:

        断言两个值不相等,单元测试则通过

        确定它绝不可能 是某些值的时候的使用

        总结:

                assert_eq! 和assert_ne! 宏分别使用了==和!=运算符来进行判断,并在断言失败时使用调试输出格式({:?})将参数值打印出来,它们的参数必须同时实现PartialEq和Debug这两个trait

                这两个trait都是可派生trait,可以通过在自定义的结构体或枚举的定义的上方添加#[derive(PartialEq, Debug)]标注来自动实现这两个trait。

assert! 宏检查结果

        assert! 宏由标准库提供,它可以确保测试中某些条件的值为true

        assert! 宏可以检查代码是否按照我们预期的方式运行。

        assert! 宏接收一个能够被计算为布尔类型的值作为参数:当这个值为true时,assert! 宏正常通过测试。当值为false时,assert! 宏就会调用panic! 宏,进而导致测试失败。

        assert!宏传入两个值==,则等价于assert_eq!

添加自定义的错误提示信息

        任何在assert!、assert_eq! 或assert_ne! 的必要参数之后出现的参数都会一起被传递给format! 宏:

assert!(result.contains("Carol"),"Greeting did not contain name, value was `{}`", result
)

其中,第二个参数会被传给format!宏

should_panic检查panic

        should_panic:编写一个测试来检查使用了非法值是否会如期发生panic

        新属性:should_panic。标记了这个属性的测试函数会在代码发生panic时顺利通过,而在代码不发生panic时执行失败。

        将#[should_panic]属性放在了#[test]属性之后、对应的测试函数之前

pub struct Guess{value:u32,
}impl Guess{pub fn new(value:u32) ->  Guess{if value <1 || value > 100{panic!("Guess value must be between 1 and 100,got {}",value);}Guess{value}}
}#[cfg(test)]mod tests{use super::*;#[test]#[should_panic]fn greater_than_100(){Guess::new(200);}
}

        should_panic属性中添加可选参数expected,让should_panic测试更加精确一些

#[should_panic(expected = "Guess value must be less than or equal to 100")]fn greater_than_100() {

        测试某个条件会触发带有特定错误提示信息的panic!

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

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

不要在使用Result<T, E>编写的测试上标注#[should_panic]

编写返回Result<T, E>的测试,就可以在测试函数体中使用问号运算符了。

在测试运行失败时,我们应当直接返回一个Err值

控制测试的运行方式:

cargo test同样会在测试模式下编译代码,并运行生成的测试二进制文件

cargo test生成的二进制文件默认会并行执行所有的测试

可以为cargo test指定命令行参数,也可以为生成的测试二进制文件指定参数:

        分隔符--

        cargo test --help会显示出cargo test的可用参数

        运行cargo test -- --help则会显示出所有可以用在--之后的参数

并行或串行地进行测试

        Rust会默认使用多线程来并行执行

        开发者必须保证测试之间不会互相依赖,或者依赖到同一个共享的状态或环境上

        

cargo test -- --test-threads=1

       指定测试执行的线程数

显示函数输出

        默认只有在测试失败时,我们才能在错误提示信息的上方观察到打印至标准输出(println!)中的内容。

cargo test -- --nocapture

        在测试通过时也将值打印出来

只运行部分特定名称的测试

        

cargo test one_hundred

给cargo test传递一个测试函数的名称来单独运行该测试

cargo test add

指定测试名称的一部分来作为参数,任何匹配这一名称的测试都会得到执行

通过显式指定来忽略某些测试

#[ignore]

添加#[ignore]属性宏

cargo test -- --ignored

通过--ignored参数单独运行添加了#[ignore]属性宏的测试函数

测试的组织结构:

        测试分类:单元测试(unit test)和集成测试(integration test)

        单元测试小而专注,每次只单独测试一个模块或私有接口

        集成测试完全位于代码库之外,访问公共接口,并且在一次测试中可能会联用多个模块。

标注#[cfg(test)]可以让Rust只在执行cargo test命令时编译和运行该部分测试代码,而在执行cargo build时剔除它们。

不需要对集成测试标注#[cfg(test)],因为集成测试本身就放置在独立的目录

单元测试:

一般将单元测试与需要测试的代码存放在src 目录下的同一文件中。同时也约定俗成地在每个源代码文件中都新建一个tests模块来存放测试函数,并使用cfg(test)对该模块进行标注。

集成测试:

集成测试是完全位于代码库之外。意味着你只能调用对外公开提供的那部分接口。集成测试的目的在于验证库的不同部分能否协同起来正常工作

集成测试首先需要建立一个tests 目录:项目根目录下创建tests 文件夹,它和src 文件夹并列。Cargo会自动在这个目录下寻找集成测试文件。我们可以在这个目录下创建任意多个测试文件,Cargo在编译时会将每个文件都处理为一个独立的包。

成测试需要在代码顶部添加语句use 包名:因为tests 目录下的每一个文件都是一个独立的包,所以我们需要将目标库导入每一个测试包中

cargo test 输出中出现了单元测试、集成测试和文档测试这3部分

cargo test --test integration_test

cargo test时使用--test并指定文件名,可以单独运行某个特定集成测试文件下的所有测试函数

 创建tests/common/mod.rs 将功能函数放在该文件中,这是可以被Rust理解的命名规范,rust不会将common模块看成集成测试文件了原因:tests 子目录中的文件不会被视作单独的包进行
编译,更不会在测试输出中拥有自己的区域。

mod common; 声明了需要引用的模块

二进制包的集成测试

只有代码包(librarycrate)才可以将函数暴露给其他包来调用,而二进制包只被用于独立执行

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自定义类型:联合体

像结构体一样&#xff0c;联合体也是由一个或者多个成员组成&#xff0c;这些成员可以是不同的类型。 联合体类型的声明 编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫&#xff1a;共⽤体。 输出结果&#xff1a; 联合体…

size_t 数据类型的好处

什么是size_t size_t 类型在不同的平台上对应不同的底层整数类型&#xff0c;具体取决于平台的指针大小。size_t 主要用于表示大小和长度&#xff0c;如数组的元素数量、缓冲区的大小等&#xff0c;它的设计目的是为了匹配指针的大小&#xff0c;以避免类型不匹配引起的错误。…

代码随想录算法训练营DAY58|101.孤岛的总面积、102.沉没孤岛、103. 水流问题、104.建造最大岛屿

忙。。。写了好久。。。。慢慢补吧。 101.孤岛的总面积 先把周边的岛屿变成水dfs def dfs(x, y, graph, s):if x<0 or x>len(graph) or y<0 or y>len(graph[0]) or graph[x][y]0:return sgraph[x][y]0s1s dfs(x1, y, graph, s)s dfs(x-1, y, graph, s)s dfs(…

【爬虫入门知识讲解:xpath】

3.3、xpath xpath在Python的爬虫学习中&#xff0c;起着举足轻重的地位&#xff0c;对比正则表达式 re两者可以完成同样的工作&#xff0c;实现的功能也差不多&#xff0c;但xpath明显比re具有优势&#xff0c;在网页分析上使re退居二线。 xpath 全称为XML Path Language 一种…

软考高级第四版备考--第16天(规划沟通管理)Plan Communication Management

定义&#xff1a;基于每个干系人或干系人群体的信息需求、可用的组织资产以及具体的项目的需求&#xff0c;为项目沟通活动制定恰当的方法和计划的过程。 作用&#xff1a; 及时向干系人提供相关信息&#xff1b;引导干系人有效参与项目&#xff1b;编制书面沟通计划&#xf…

【基于R语言群体遗传学】-16-中性检验Tajima‘s D及连锁不平衡 linkage disequilibrium (LD)

Tajimas D Test 已经开发了几种中性检验&#xff0c;用于识别模型假设的潜在偏差。在这里&#xff0c;我们将说明一种有影响力的中性检验&#xff0c;即Tajimas D&#xff08;Tajima 1989&#xff09;。Tajimas D通过比较数据集中的两个&#x1d703; 4N&#x1d707;估计值来…

vue项目中常见的一些preset及其关系

Babel的作用 Babel主要用途是用来做js代码转换的&#xff0c;将最新的js语法或者api转换成低版本浏览器可兼容执行的代码。 语法兼容是指一些浏览器新特性增加的js写法&#xff0c;例如箭头函数 ()>{}&#xff1b;低版本的浏览器无法识别这些&#xff0c;会导致一些语法解…

spark shuffle写操作——UnsafeShuffleWriter

PackedRecordPointer 使用long类型packedRecordPointer存储数据。 数据结构为&#xff1a;[24 bit partition number][13 bit memory page number][27 bit offset in page] LongArray LongArray不同于java中long数组。LongArray可以使用堆内内存也可以使用堆外内存。 Memor…

秋招突击——7/9——字节面经

文章目录 引言正文八股MySQL熟悉吗&#xff1f;讲一下MySQL索引的结构&#xff1f;追问&#xff1a;MySQL为什么要使用B树&#xff1f;在使用MySQL的时候&#xff0c;如何避免索引失效&#xff1f;讲一下MySQL的事物有哪几种特征&#xff1f;MySQL的原子性可以实现什么效果&…

GESP C++ 三级真题(2023年9月)T2 进制判断

进制判断 问题描述 N进制数指的是逢N进一的计数制。例如&#xff0c;人们日常生活中大多使用十进制计数&#xff0c; 而计算机底层则一般使用二进制。除此之外&#xff0c;八进制和十六进制在一些场合也是 常用的计数制(十六进制中&#xff0c;一般使用字母A至F表示十至十五…

【区块链+跨境服务】粤澳健康码跨境互认系统 | FISCO BCOS应用案例

2020 年突如其来的新冠肺炎疫情&#xff0c;让社会治理体系面临前所未见的考验&#xff0c;如何兼顾疫情防控与复工复产成为社会 各界共同努力的目标。区块链技术作为传递信任的新一代信息基础设施&#xff0c;善于在多方协同的场景中发挥所长&#xff0c;从 而为粤澳两地的疫情…

uniapp上传文件并获取上传进度

1. 上传普通文件 uni.chooseMessageFile({count: 1,success: (res) > {console.log(res)console.log("res123456", res.tempFiles[0].path)const uploadTask uni.uploadFile({url: http://localhost:8000/demo,filePath: res.tempFiles[0].path,name: file,form…

CSS关于居中的问题

文章目录 1. 行内和块级元素自身相对父控件居中1.1. 块级元素相对父控件居中1.2. 行内元素相对于父控件居中 2. 实现单行文字垂直居中3. 子绝父相实现子元素的水平垂直居中3.1. 方案一3.1.1. 示例 3.2. 方案二3.2.1. 示例 3.3. 方案三(推荐)3.3.1. 示例 3.4. 方案四(了解一下) …

AI大模型知识点大梳理_ai大模型的精度以下哪项描述的准确

AI大模型是什么 AI大模型是指具有巨大参数量的深度学习模型&#xff0c;通常**包含数十亿甚至数万亿个参数。**这些模型可以通过学习大量的数据来提高预测能力&#xff0c;从而在自然语言处理、计算机视觉、自主驾驶等领域取得重要突破。 AI大模型的定义具体可以根据参数规模…

短信验证码研究:公开的短信验证码接口、不需要注册的短信验证码接口

短信验证码研究&#xff1a;公开的短信验证码接口、不需要注册的短信验证码接口 0 说明 本文提供了一个短信验证码接口&#xff0c;主要用于以下场景&#xff1a; 1、用于开发调试 2、用于申请验证码困难的企业和个人 3、用于短信验证码认证还没有通过&#xff0c;但是着急…

DBeaver操作MySQL无法同时执行多条语句的解决方法

DBeaver选择数据库连接&#xff0c;在【驱动属性】中将allowMultiQueries允许执行多条语句置为True

各种音频处理器

在HiFi&#xff08;高保真&#xff09;音频系统中&#xff0c;通常需要使用一些特定类型的音频处理器&#xff0c;以确保音频信号的高保真和优质输出。以下是一些常见的音频处理器类型及其在HiFi系统中的应用&#xff1a; DAC&#xff08;数模转换器&#xff09;&#xff1a; …

mysql 导出导入 数据库

导出 MySQL 数据库可以通过多种方法实现&#xff0c;最常见的方法是使用 mysqldump 工具。以下是一些常用的导出 MySQL 数据库的方法&#xff1a; 使用 mysqldump 工具 mysqldump 是一个命令行工具&#xff0c;用于导出 MySQL 数据库的结构和数据。以下是基本的导出命令&…

泰迪智能科技大数据实验室产品-实训管理平台介绍

高校大数据实验室通常配备有先进的计算机硬件和软件工具&#xff0c;以及专门的数据库和分析平台&#xff0c;以便研究人员和学生能够进行复杂的数据处理、分析和解释。主要利用大数据技术进行科学研究、技术开发和人才培养。 泰迪智能科技实训管理平台作为教学核心&#xff0c…

JS进阶-构造函数

学习目标&#xff1a; 掌握构造函数 学习内容&#xff1a; 构造函数 构造函数&#xff1a; 封装是面向对象思想中比较重要的一部分&#xff0c;js面向对象可以通过构造函数实现的封装。 同样的将变量和函数组合到了一起并能通过this实现数据的共享&#xff0c;所不同的是借助…