当前位置: 首页 > news >正文

编写自动化测试(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 中的主要功能

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 测试开发面试题---JVM
  • 基于ansible进行运维自动化的研究以及相关的属性
  • 【区块链+绿色低碳】双碳数字化管控平台 | FISCO BCOS应用案例
  • NET 语言识别,语音控制操作、语音播报
  • leetcode位运算(1684. 统计一致字符串的数目)
  • Google Chrome 浏览器在链接上点右键的快捷键
  • “微软蓝屏”事件暴露了网络安全哪些问题?
  • Photoshop(PS) 抠图简单教程
  • 17_高级进程间通信 UNIX域套接字1
  • 软件测试10 渗透性测试及验收测试
  • 项目中加班的意义
  • 80. 删除有序数组中的重复项 II【 力扣(LeetCode) 】
  • primeflex教学笔记20240720, FastAPI+Vue3+PrimeVue前后端分离开发
  • 第三届智能机械与人机交互技术学术会议(IHCIT 2024)
  • html+css+js前端作业 王者荣耀官网5个页面带js
  • [case10]使用RSQL实现端到端的动态查询
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 2019年如何成为全栈工程师?
  • CentOS 7 防火墙操作
  • DataBase in Android
  • echarts的各种常用效果展示
  • Java 网络编程(2):UDP 的使用
  • java概述
  • MySQL主从复制读写分离及奇怪的问题
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 分布式事物理论与实践
  • 规范化安全开发 KOA 手脚架
  • 后端_MYSQL
  • 后端_ThinkPHP5
  • 利用DataURL技术在网页上显示图片
  • 驱动程序原理
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 终端用户监控:真实用户监控还是模拟监控?
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 【干货分享】dos命令大全
  • # 职场生活之道:善于团结
  • #VERDI# 关于如何查看FSM状态机的方法
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (20050108)又读《平凡的世界》
  • (7)svelte 教程: Props(属性)
  • (C++17) std算法之执行策略 execution
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (编译到47%失败)to be deleted
  • (二)Eureka服务搭建,服务注册,服务发现
  • (二十三)Flask之高频面试点
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (文章复现)基于主从博弈的售电商多元零售套餐设计与多级市场购电策略
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • .NET Core 2.1路线图
  • .net 按比例显示图片的缩略图