编写自动化测试(11)

编写自动化测试

    • 1.如何编写测试
      • 1.测试函数剖析
        • 1.创建测试库
      • 2.使用 assert! 宏来检查结果
      • 3.使用assert_eq! 和 assert_ne!宏来测试相等
      • 4.自定义失败信息
      • 5.使用should_panic 检查 panic
      • 6.将Result<T, E>用于测试
    • 2.控制测试如何运行
      • 1.并行或连续的运行测试
        • 1.1 精准控制运行测试
      • 2.显示函数输出
        • 1.显示成功测试的输出
      • 3.通过指定名称来运行部分测试
        • 1.运行单个测试
        • 2.过滤运行多个测试
      • 4.除非特别指定否则忽略某些测试
    • 3.测试的组织结构
      • 1.单元测试
        • 1.1测试模块和 #[cfg(test)]
        • 1.2测试私有函数
      • 2.集成测试
        • 1.tests目录
        • 2.集成测试中的子模块
      • 3.二进制crate的集成测试

1.如何编写测试

1.测试函数剖析

1.创建测试库
cargo new adder --lib
  • cargo new 自动生成的测试模块和函数
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);}
}
  • cargo test 命令运行项目中所有的测试
$ cargo testCompiling adder v0.1.0 (file:///projects/adder)Finished `test` profile [unoptimized + debuginfo] target(s) in 0.57sRunning unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4)running 1 test
test tests::it_works ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sDoc-tests adderrunning 0 teststest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
  • 增加因调用了 panic! 而失败的测试
pub fn add(left: usize, right: usize) -> usize {left + right
}#[cfg(test)]
mod tests {use super::*;#[test]fn exploration() {let result = add(2, 2);assert_eq!(result, 4);}#[test]fn another() {panic!("Make this test fail");}
}
  • 调用 cargo test 运行测试
$ cargo testCompiling adder v0.1.0 (file:///projects/adder)Finished `test` profile [unoptimized + debuginfo] target(s) in 0.72sRunning unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4)running 2 tests
test tests::another ... FAILED
test tests::exploration ... okfailures:---- tests::another stdout ----
thread 'tests::another' panicked at src/lib.rs:17:9:
Make this test fail
note: run with `RUST_BACKTRACE=1` environment variable to display a backtracefailures:tests::anothertest result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00serror: test failed, to rerun pass `--lib`

2.使用 assert! 宏来检查结果

  • assert! 宏由标准库提供,在希望确保测试中一些条件为 true 时非常有用
  • 需要向 assert! 宏提供一个求值为布尔值的参数; 如果值是 trueassert! 什么也不做,同时测试会通过。如果值为 falseassert! 调用 panic! 宏,这会导致测试失败
#[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))}#[test]fn smaller_cannot_hold_larger() {let larger = Rectangle {width: 8,height: 7,};let smaller = Rectangle {width: 5,height: 1,};assert!(!smaller.can_hold(&larger))}
}#[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// }// 引入一个bug,将can_hold()函数方法中比较长度时,本应使用大于号的地方改为小于号// larger.length是8,而smaller.length是5,实际应该返回falsefn can_hold(&self, other: &Rectangle) -> bool {self.width < other.width && self.height > other.height}
}

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

pub fn add_two(a: i32) -> i32 {a + 3
}#[cfg(test)]
mod tests {use super::*;#[test]fn it_works() {assert_eq!(4, add_two(2));}
}
  • 测试结果
PS C:\Tools\devTools\vscode\code\rust\adder> cargo testCompiling adder v0.1.0 (C:\Tools\devTools\vscode\code\rust\adder)Finished `test` profile [unoptimized + debuginfo] target(s) in 0.16sRunning unittests src\lib.rs (target\debug\deps\adder-b88936cc1f115a7c.exe)running 1 test
test tests::it_works ... FAILEDfailures:---- tests::it_works stdout ----
thread 'tests::it_works' panicked at src\lib.rs:11:9:
assertion `left == right` failedleft: 4right: 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtracefailures:tests::it_workstest result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00serror: test failed, to rerun pass `--lib`
  • 比较左右两个值不相等,测试失败 left参数是4,right参数是5

4.自定义失败信息

  • 任何在 assert! 的一个必需参数和 assert_eq!assert_ne! 的两个必需参数之后指定的参数都会传递给 format!
pub fn greeting(name: &str) -> String {format!("Hello {}!", name)
}
#[cfg(test)]
mod tests {use super::*;#[test]fn greeting_contains_name() {let result = greeting("Carol");assert!(result.contains("Carol"),"Greeting did not contain name, value was `{}`",result);}
}

5.使用should_panic 检查 panic

pub struct Guess {value: i32,
}
impl Guess {pub fn new(value: i32) -> 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);}
}

6.将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"))}}
}

2.控制测试如何运行

1.并行或连续的运行测试

  • 当运行多个测试时,Rust 默认使用线程来并行运行
1.1 精准控制运行测试
  • 测试并行运行或者想要更加精确的控制线程的数量,可以传递 - -test-threads 参数 和 使用线程的数量
cargo test -- --test-threads=1

2.显示函数输出

  • 默认情况下,当测试通过时,Rust 的测试库会截获打印到标准输出的所有内容
  • println! 而测试通过了,我们将不会在终端看到 println! 的输出:只会看到说明测试通过的提示行;如果测试失败了,则会看到所有标准输出和其他错误信息
fn prints_and_returns_10(a: i32) -> i32 {println!("I got the value {}", a);10
}   
#[cfg(test)]
mod tests {use super::*;#[test]fn this_test_will_pass() {let result = prints_and_returns_10(4);assert_eq!(result, 10);}#[test]fn this_test_will_fail() {let result = prints_and_returns_10(8);assert_eq!(result, 5);}
}
PS C:\Tools\devTools\vscode\code\rust\显示函数输出> cargo testCompiling 显示函数输出 v0.1.0 (C:\Tools\devTools\vscode\code\rust\显示函数输出)
warning: function `prints_and_returns_10` is never used--> src\lib.rs:1:4|
1 | fn prints_and_returns_10(a: i32) -> i32 {|    ^^^^^^^^^^^^^^^^^^^^^|= note: `#[warn(dead_code)]` on by defaultwarning: `显示函数输出` (lib) generated 1 warningFinished `test` profile [unoptimized + debuginfo] target(s) in 0.67sRunning unittests src\lib.rs (target\debug\deps\显示函数输出-68b68f71791c7651.exe)running 2 tests
test tests::this_test_will_pass ... ok
test tests::this_test_will_fail ... FAILEDfailures:---- tests::this_test_will_fail stdout ----
I got the value 8
thread 'tests::this_test_will_fail' panicked at src\lib.rs:17:9:
assertion `left == right` failedleft: 10right: 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtracefailures:tests::this_test_will_failtest result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
1.显示成功测试的输出
cargo test -- --show-output

3.通过指定名称来运行部分测试

1.运行单个测试
  • 可以向 cargo test funName 传递任意测试的名称来只运行某个测试
2.过滤运行多个测试
  • 可以指定部分测试的名称,任何名称匹配这个名称的测试会被运行
  • cargo test add 匹配名称带add字段方法的所有测试

4.除非特别指定否则忽略某些测试

pub fn add_two(a: i32) -> i32 {a + 2
}#[cfg(test)]
mod tests {use super::*;#[test]fn add_two_and_two() {assert_eq!(4, add_two(2));}#[test]fn add_three_and_two() {assert_eq!(5, add_two(3));}#[test]#[ignore]fn one_hundred() {assert_eq!(102, add_two(100));}
}
  • #[test] 之后添加 #[ignore] 行,进行cargo test ,会忽略添加 #[ignore]
  • 如果只要运行被忽略的测试,可以使用 cargo test – --ignored
  • 如果测试方法包含注解 #[ignore] ,想要运行全部测试,可以运行 cargo test – --include-ignored

3.测试的组织结构

1.单元测试

  • 单元测试的目的是在与其他部分隔离的环境中测试每一个单元的代码,以便于快速而准确地验证某个单元的代码功能是否符合预期
  • 单元测试与它们要测试的代码共同存放在位于 src 目录下相同的文件中
  • 规范是在每个文件中创建包含测试函数的 tests 模块,并使用 cfg(test) 标注模块
1.1测试模块和 #[cfg(test)]
  • cfg 属性代表配置(configuration) ,它告诉 Rust,接下来的项,只有在给定特定配置选项时,才会被包含
  • 配置选项是 test,即 Rust 所提供的用于编译和运行测试的配置选项
  • 通过使用 cfg 属性,Cargo 只会在我们主动使用 cargo test 运行测试时才编译测试代码
1.2测试私有函数

2.集成测试

1.tests目录
  • 为了编写集成测试,需要在项目根目录创建一个 tests 目录,与 src 同级
adder
├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
└── tests└── integration_test.rs
adder/src/lib.rspub fn add_two(a: i32) -> i32 {a + 2
}// #[cfg(test)]
// mod tests {
//     use super::*;//     #[test]
//     fn it_works() {
//         assert_eq!(4, add_two(2));
//     }
// }adder/tests/integration_test.rsuse adder::add_two;
#[test]
fn it_adds_two() {assert_eq!(4, add_two(2));
}
  • 通过 cargo test --test 文件名称 ,运行某个特定集成测试文件中的所有测试
2.集成测试中的子模块
  • 项目目录结构
├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
└── tests├── common│   └── mod.rs└── integration_test.rs
tests/common/mod.rspub fn setup() {// setup code specific to your library's tests would go here
}tests/integration_test.rsuse adder::add_two;
mod common;
#[test]
fn it_adds_two() {common::setup();assert_eq!(4, add_two(2));
}

3.二进制crate的集成测试

  • 项目是二进制 crate 并且只包含 src/main.rs 而没有 src/lib.rs,这样就不可能在 tests 目录创建集成测试并使用 extern crate 导入 src/main.rs 中定义的函数
  • 只有库 crate 才会向其他 crate 暴露了可供调用和使用的函数;二进制 crate 只意在单独运行
  • 许多 Rust 二进制项目使用一个简单的 src/main.rs 调用 src/lib.rs 中的逻辑的原因之一
  • 集成测试 就可以 通过 extern crate 测试库 crate 中的主要功能

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

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

相关文章

取消当前的git commit操作

一、取消最近一次提交&#xff08;未推送到远程仓库&#xff09; 使用 git reset 保留工作目录、暂存区&#xff08;即只取消提交&#xff09;不变色 git reset --soft HEAD~1这会将当前分支回退到上一个提交&#xff0c;但保留所有更改在暂存区。 保留工作目录&#xff08…

黑龙江等保测评最新资讯:强化安全基线,赋能数字未来

在黑龙江省&#xff0c;随着数字化转型的不断深化&#xff0c;企业对其信息安全的关注也越来越高&#xff0c;而作为保护信息资产的一个重要环节的等保测评&#xff0c;也面临着新的机遇和挑战。 最新政策动向 最近&#xff0c;有关部门下发了《关于加强网络安全等级保护的指导…

Floyd

Floyd 本质&#xff1a;DP 算法特点&#xff1a;多源最短路&#xff0c;能一次性求解所有点对间的最短距离 适用对象&#xff1a;小图&#xff0c;允许边权为负&#xff0c;无法适用于负环图(负环:环上边权之和为负的环,当任意时刻出现 d p [ i ] [ i ] < 0 dp[i][i]<0…

Spring模块

1 事务注解Transactional 默认的隔离等级&#xff1a;DEFAULT&#xff0c;使用数据库的隔离等级。(读未提交、读已提交、可重复读、串行化、DEFAULT) 默认的传播行为&#xff1a;REQUIRED&#xff0c;有事务则加入当前事务&#xff0c;没有事务则创建一个新的事务 默认的回滚…

基于3D开发引擎HOOPS平台的大型三维PLM系统的设计、开发与应用

产品生命周期管理&#xff08;Product Lifecycle Management&#xff0c;PLM&#xff09;系统在现代制造业中扮演着至关重要的角色。随着工业4.0和智能制造的推进&#xff0c;PLM系统从最初的CAD和PDM系统发展到现在的全面集成、协作和智能化的平台。本文将探讨基于HOOPS平台的…

【python】Numpy运行报错分析:IndexError与形状不匹配问题

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

森林防火,森林防火智能储水罐_鼎跃安全

森林防火是保护森林的重要措施&#xff0c;每年发生的森林火灾都严重威胁着自然安全&#xff0c;对社会经济和生态造成严重的破坏。为了切实有效地预防并扑灭森林火灾&#xff0c;森林防火智能储水罐已成为现代森林防火体系中的重要装备。 储水罐内置传感器和控制系统&#xff…

【CTFWP】ctfshow-web32

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 题目介绍&#xff1a;题目分析&#xff1a;payload&#xff1a;payload解释&#xff1a;flag 题目介绍&#xff1a; <?php/* # -*- coding: utf-8 -*- # Autho…

【每日刷题Day85】

【每日刷题Day85】 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 125. 验证回文串 - 力扣&#xff08;LeetCode&#xff09; 2. 43. 字符串相乘 - 力扣&#xff08;L…

DC系列靶场---DC 2靶场的渗透测试(二)

漏洞利用及探测 rbash逃逸 虽然我们现在已经可以执行切换路径命令了&#xff0c;但是发现还有是很多命令不能用。 我想看看一下目标主机的所有用户&#xff0c;是不能执行的。 那我们就用到了当前shell逃逸。第一种情况&#xff1a;/ 被允许的情况下&#xff1b;直接 /bin/s…

SpringBoot原理解析(二)- Spring Bean的生命周期以及后处理器和回调接口

SpringBoot原理解析&#xff08;二&#xff09;- Spring Bean的生命周期以及后处理器和回调接口 文章目录 SpringBoot原理解析&#xff08;二&#xff09;- Spring Bean的生命周期以及后处理器和回调接口1.Bean的实例化阶段1.1.Bean 实例化的基本流程1.2.Bean 实例化图例1.3.实…

go 协程池的实现

使用场景 这次需求是做一个临时的数据采集功能&#xff0c;为了将积压的数据快速的消耗完&#xff0c;但是单一的脚本消耗的太慢&#xff0c;于是乎就手写了一个简单的协程池&#xff1a; 为了能加快数据的收集速度为了稳定协程的数量&#xff0c;让脚本变得稳定 设计图如下…

数据增强:机器学习中的数据魔法

数据增强&#xff1a;机器学习中的数据魔法 在机器学习领域&#xff0c;数据是模型训练的基石。然而&#xff0c;获取大量高质量的训练数据往往是一个挑战。数据增强技术应运而生&#xff0c;它通过从现有数据中生成新的变体来增加数据集的多样性和丰富性。本文将深入探讨数据…

微服务分布式事务

1、分布式事务是什么&#xff1f; 微服务架构中的分布式事务是指在多个服务实例之间保持数据一致性的机制。由于微服务通常涉及将业务逻辑拆分成独立的服务&#xff0c;每个服务可能有自己的数据库&#xff0c;因此当一个业务操作需要跨多个服务进行时&#xff0c;确保所有服务…

sbti科学碳目标倡议是什么

在科学界、工业界以及全球政策制定者的共同努力下&#xff0c;一个名为“科学碳目标倡议”&#xff08;Science Based Targets initiative&#xff0c;简称SBTi&#xff09;的全球性合作平台应运而生。这一倡议旨在推动企业和组织设定符合气候科学要求的减排目标&#xff0c;以…

2023年国际高校数学建模竞赛

2023年国际高校数学建模竞赛是一项由国际(澳门)学术研究院数学科学研究所、数学建模研究与应用期刊社联合香港数学研究与应用学会主办的国际性学科竞赛&#xff0c;该竞赛已获澳门特别行政区政府澳门基金会&#xff08;行政长官直属&#xff09;立项资助。以下是对该竞赛的详细…

生成式AI未来发展方向充满了无限可能与挑战

生成式AI&#xff0c;作为人工智能领域的一个前沿分支&#xff0c;其未来发展方向充满了无限可能与挑战&#xff0c;将对多个行业产生深远影响。以下是我对生成式AI未来发展方向的几点看法&#xff1a; 技术融合与创新 未来&#xff0c;生成式AI将更加注重与其他技术的深度融合…

问题记录-SpringBoot 2.7.2 整合 Swagger 报错

详细报错如下 报错背景&#xff0c;我将springboot从2.3.3升级到了2.7.2&#xff0c;报了下面的错误&#xff1a; org.springframework.context.ApplicationContextException: Failed to start bean documentationPluginsBootstrapper; nested exception is java.lang.NullPo…

信息收集Part3-资产监控

Github监控 便于收集整理最新exp或poc 便于发现相关测试目标的资产 各种子域名查询 DNS,备案&#xff0c;证书 全球节点请求cdn 枚举爆破或解析子域名对应 便于发现管理员相关的注册信息 通过Server酱接口接收漏洞信息 https://sct.ftqq.com/ https://github.com/easych…

从苏宁电器到卡巴斯基(第二部)第36篇:我当高校教师的这几年 XII

你们是八九点钟的太阳 想想也是有趣,自从我2018年3月入职X高校之后,一直到2019年9月,在这3个学期的时间里面,我讲课的对象全都是大三的同学,而且都是属于专业方向课,比如网络安全、物联网这种。第一学期尽管也教过C++,但是他们毕竟已经是大三第二学期,从心态上来说,他…