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

在Rust中编写自动化测试

1.摘要

Rust中的测试函数是用来验证非测试代码是否是按照期望的方式运行的, 测试函数体通常需要执行三种操作:1.设置任何所需的数据或状态;2.运行需要测试的代码;3.断言其结果是我们所期望的。本篇文章主要探讨了Rust自动化测试的几种常见场景。

2.测试函数详解

在Rust项目工程中, 可以对任意函数进行自动化测试, 前提是需要在被测试函数上面加上#[test]注解, 然后运行cargo test命令进行函数自动化测试, Rust会查找所有被#[test]注解的函数并自动进行测试。

先看下面一段代码:

#[test]
fn add_calc() {let result = 1 + 2;assert_eq!(result, 3);
}

在上面的代码中, 我实现了一个加法计算的函数: add_calc(), 将加法结果保存到不可变变量result中, 并使用了assert_eq!宏来断言1+2的结果, assert!宏由标准库提供, 在希望确保测试过程中一些条件为true时非常有用。在函数上方加上了#[test]注解, 表示该函数将执行自动化测试, 运行: cargo test看下结果:

从测试结果中, 可以看到test add_calc ... ok 这行, 表示该函数测试通过了。

现在我修改下断言的结果, 将代码修改为:

#[test]
fn add_calc() {let result = 1 + 2;assert_eq!(result, 4);
}

再次运行cargo test命令, 返回结果如下:

可以看到, 计算的结果是3, 但断言相等的条件是等于4, 因此函数执行失败, add_calc()函数自动化测试不通过。

接下来我们再加入一个函数, 看看在具有多个函数的前提下, 同时具备成功和失败的情况, 代码如下:

#[test]
fn add_calc() {let result = 1 + 2;assert_eq!(result, 3);
}
​
#[test]
fn another_method() {panic!("执行失败,抛出一个异常!")
}

在上面的代码中, 增加了一个名为another_method()的函数, 该函数直接使用panic!抛出一个异常, 直接扮演了函数执行失败的角色, 而上面的add_calc()函数我讲assert_eq!宏修改正确, 将扮演执行成功的角色, 使用cargo test命令看下结果:

可以看到, add_calc()函数测试没问题, 后面用绿色ok表示, 而another_method()函数执行失败, 使用红色的FAILED标记。

3.自定义失败信息

在上面的案例中, 我使用了assert_eq!宏来断言结果, 同样, 也可以向宏传递一个可选的失败信息参数, 可以在测试失败时将自定义的失败信息一并打印出来, 使用自定义信息有个好处, 当测试失败时, 能更好的理解代码到底出了什么问题, 看一段下面的代码:

pub fn make_string(name: &str) -> String {format!("Hello,{}!", name)
}
​
#[test]
fn is_contain_name() {let result = make_string("cargo");assert!(result.contains("cargo"));
}

在这段代码中, 定义了一个函数make_string, 该函数接收一个字符串参数, 并在函数内部通过format!宏格式化字符串后返回, 在函数is_contain_name()中, 传入一个字符串"cargo", assert!会判断make_string()函数返回的字符串中是否会包含"cargo"字符串,如果包含就是成功的,否则就失败, 这里我们能预言结果应该是成功的, 测试一下看看:

结果跟我们预想的一样, 现在再加入一些更详细的变化信息看看, 代码如下:

pub fn make_string(name: &str) -> String {format!("Hello,{}!", name)
}
​
#[test]
fn is_contain_name() {let result = make_string("rustup");assert!(result.contains("cargo"), "make_string中不包含该字符串,值为:`{}`", result);
}

我在assert!宏中加入了变量打印, 假如make_string()函数没有返回预期的结果, 那结果到底是什么,这里我们将能看到失败原因, 测试结果如下:

从结果可以看到, 函数的确测试失败了, 但我们看到了关键信息, 失败的原因是因为make_string()函数返回的字符串内容为:Hello,rustup!,这个结果与断言中的result.contains("cargo")结果是不同的, “Hello,rustup!”字符串中并不包含"cargo"字符串,所以函数测试失败。

4.检查崩溃异常

除了使用断言宏之外, Rust还提供了一个should_panic用来检测程序中的panic,并且提供了一个名为expected的参数用来自定义消息,看一段下面的代码:

pub fn number_calc(value: i32) -> i32 {let ret_value = 40;if value < 0 {panic!("值必须大于0,传参的值为:{}", value)}return ret_value
}
​
#[test]
#[should_panic(expected = "传参不能小于0")]
fn is_contain_name() {let result = number_calc(-1);
}

在number_calc()函数中, 如果判断参数传入的值小于0, 会抛出一个panic, 为了监视是什么原因导致, 在函数is_contain_name()上面使用should_panic进行监控, 并使用expected参数指定自定义消息, 如果遇到传入的参数小于0, 将触发该消息打印, 使用cargo test运行一下看看结果:

从结果可以看到, 的确检测到了panic产生, panic打印了本身的消息, 最后一行shoud_panic也触发了消息, 并打印出失败的原因。

5.使用Result<T, E>测试

先看一段下面的代码:

pub fn number_calc(value: i32) -> i32 {let ret_value = 40;if value < 0 {return 30}return ret_value
}
​
#[test]
fn is_contain_name() -> Result<(), String>{if number_calc(2) == 40 {OK(())}else{Err(String::from("结果不等于40,请检查原因!"))}
}

在上面的代码中, is_contain_name()函数的返回类型现在变为:Result<(), String>, 在函数体中, 不同于调用assert_eq!,现在如果测试通过,将返回Ok(()), 在测试失败时, 返回带有String的Err错误。现在传入参数为2, 将显示正常的结果:

现在我们再传入一个小于0的负值看看,结果如下:

可以看到, 如果使用Result<(), String>接收结果, 当出来错误时, 将返回一个Error,并打印对应的自定义消息。

6.总结

在本篇文章中, 我们使用#[test]注解完成了对指定函数的自动化测试, 使用assert!宏对错误进行断言, 在断言中自定义错误显示消息用于查看更详细的错误原因。使用了should_panic对panci错误进行了监控, 最后使用Result<T, E>替代断言分别完成了代码测试和自定义错误消息打印, 在以后的实际应用中, 可能还会有一些组合测试的场景出现, 到时候再具体问题具体分析。

相关文章:

在Rust中编写自动化测试

1.摘要 Rust中的测试函数是用来验证非测试代码是否是按照期望的方式运行的, 测试函数体通常需要执行三种操作:1.设置任何所需的数据或状态;2.运行需要测试的代码;3.断言其结果是我们所期望的。本篇文章主要探讨了Rust自动化测试的几种常见场景。 2.测试函数详解 在Rust项目工…...

羊大师提问,为什么吃得越咸越容易出现健康问题?

羊大师提问&#xff0c;为什么吃得越咸越容易出现健康问题&#xff1f; 在现代社会中&#xff0c;有一种追求咸味食物的趋势&#xff0c;许多人都钟爱于吃咸味食物。吃咸味食物往往容易导致健康问题&#xff0c;引发各种疾病。那么为什么吃的越咸越容易生病呢&#xff1f; 今…...

linux ld 链接器学习笔记

ld链接器笔记 1. 首先编写一段汇编代码 这里的汇编语法时 AT&T语法,是gcc原生支持的语法,底层使用 gas(gnu assembler) 完成汇编,相较于 Intel x86语法, AT&T 语法要更加古老,因此大多数人更加偏向于使用 Intel 的语法. nasm 编译器支持x86语法.自从2.10版本&#xf…...

栈模拟先序后序中序遍历(非递归遍历)

先序遍历&#xff1a; vector<int> preorderTraversal(TreeNode* u) {stack<TreeNode*>stk;vector<int>res;if(unullptr) return res;while(stk.size()||u){if(u){res.push_back(u->val);//遍历当前结点stk.push(u);//记录当前递归层uu->left;//遍历左…...

linux 内核软中断介绍

在介绍软中断之前&#xff0c;先来介绍一个概念&#xff1a;中断下半部&#xff1a; 为了避免处理复杂的中断嵌套&#xff0c;中断处理程序是在关闭中断的情况下执行的。可是&#xff0c;如果关闭中断的时间太长&#xff0c;可能导致中断请求丢失。例如周期时钟每隔 10 毫秒发送…...

软考:2024年软考高级:软件工程

软考&#xff1a;2024年软考高级: 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &#xff08;1…...

Kubernetes(K8s)_15_CNI

Kubernetes&#xff08;K8s&#xff09;_15_CNI CNI网络模型UnderlayMAC VLANIP VLANDirect Route OverlayVXLAN CNI插件FlannelCalico CNI配置内置实现 CNI CNI(Container Network Interface): 实现容器网络连接的规范 Kubernetes将网络通信可分为: Pod内容器、Pod、Pod与Se…...

python 生成器的作用

1. 生成器 参考&#xff1a; https://www.cainiaojc.com/python/python-generator.html 1.1. 什么是生成器&#xff1f; 在 python 中&#xff0c;一边循环一边计算的机制&#xff0c;称为生成器&#xff1a;generator. 1.2. 生成器有什么优点&#xff1f; 1、节约内存。p…...

第十五届蓝桥杯(Web 应用开发)模拟赛 2 期-大学组(详细分析解答)

目录 1.相不相等 1.1 题目要求 1.2 题目分析 1.3 源代码 2.三行情书 2.1 题目要求 2.2 题目分析 2.3 源代码 3.电影院在线订票 3.1 题目要求 3.2 题目分析 3.3 源代码 4.老虎坤&#xff08;不然违规发不出来&#xff09; 4.1 题目要求 4.2 题目分析 4.3 源代码 …...

图解系列--HTTPS,认证

确保 Web 安全的HTTPS 1.HTTP 的缺点 1.1.通信使用明文可能会被窃听 加密处理防止被窃听 加密的对象可以有这么几个。 (1).通信的加密 HTTP 协议中没有加密机制&#xff0c;但可以通过和 SSL&#xff08;Secure Socket Layer&#xff0c;安全套接层&#xff09;或TLS&#xff…...

element plus中表格的合计属性和例子

在 element plus 表格中&#xff0c;您可以使用 summary-method 属性来指定一个函数&#xff0c;计算表格中列的合计或平均值等。该函数应该返回一个对象&#xff0c;其中包含每个列的合计值。例如&#xff0c;如果您的表格数据是这样的&#xff1a; [{ name: John, age: 20, …...

计网Lesson1笔记

文章目录 几个简单概念计网的发展史阿帕网和RFCTCP/IP 协议互联网协议计网设计OSI 的七层架构TCP/IP 协议簇 几个简单概念 主机(host)&#xff1a;指单个计算机&#xff0c;比如PC&#xff0c;或者其他电子设备。端系统(end system)&#xff1a;指一块区域内的多个主机&#x…...

指针数组以及利用函数指针来实现简易计算器及typedef关键字(指针终篇)

文章目录 &#x1f680;前言&#x1f680;两段有趣的代码✈️typedef关键字 &#x1f680;指针数组&#x1f680;简易计算器的实现 &#x1f680;前言 基于阿辉前两篇博客指针的基础篇和进阶篇对于指针的了解&#xff0c;那么今天阿辉将为大家介绍C语言的指针剩下的部分&#…...

josef JZ-7Y-33静态中间继电器 电压DC220V 板前接线

系列型号&#xff1a; JZ-7Y-201X静态中间继电器&#xff1b;JZ-7J-201X静态中间继电器&#xff1b; JZ-7L-201X静态中间继电器&#xff1b;JZ-7D-201X静态中间继电器&#xff1b; JZ-7Y-201静态中间继电器&#xff1b;JZ-7J-201静态中间继电器&#xff1b; JZ-7L-201静态中…...

Java第二十章 ——多线程

本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 在这之前&#xff0c;首先让我们来了解下在操作系统中进程和线程的区别&#xff1a;   进程&#xff1a;每个进程都有独立的代码和数据空间&#xff08;进程上下文…...

【超强笔记软件】Obsidian实现免费无限流量无套路云同步

【超强笔记软件】Obsidian如何实现免费无限流量无套路云同步&#xff1f; 目录 一、简介 软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步 1 安装并设置Synology Drive套件 2 局域网内同步文件测试 三、内网穿透群…...

【Linux小项目】实现自己的bash

0. bash原理介绍 bash实际上就是一个负责解析输入字符串工具. 我们需要做的事是这些: 手动分割出输入的字符串判断哪些变量是内建命令(自己执行),哪些命令是普通命令(创建子进程执行)实现的功能有: echo export cd 常规指令 输入、输出流重定向 #include<stdio.h> #i…...

客户案例:EDLP助力金融行业打造高效数据防泄露体系

客户背景 某金融机构是一家以金融科技为核心&#xff0c;致力于为客户提供全方位、智能化、便捷化金融服务的综合性企业。公司总部位于南京&#xff0c;业务范围覆盖全国&#xff0c;拥有强大的技术研发团队和优秀的业务精英&#xff0c;为客户提供全方位的金融服务解决方案。 …...

【JavaFX漏扫开发基础】stage窗口/模式/模态

文章目录 stage一、stage窗口二、stage窗口,模式,模态stage模式(5种样式)模态化窗口stage stage其实就是一个窗口,它啥也不是,打开所有windows的程序都会有一个窗口,这个窗口就是javafx里的stage。里面的内容不属于stage,stage就是一个窗口,就这么简单。 Stage is a…...

MySQL进阶知识:锁

目录 前言 全局锁 表级锁 表锁 元数据锁&#xff08;MDL&#xff09; 意向锁 行级锁 行锁 行锁演示 间隙锁/临界锁 演示 前言 MySQL中的锁&#xff0c;按照锁的粒度分&#xff0c;分为以下三类 全局锁&#xff1a;锁定数据库中的所有表。表级锁&#xff1a;每次操…...

OpenClaw安全实践:千问3.5-9B本地化部署方案

OpenClaw安全实践&#xff1a;千问3.5-9B本地化部署方案 1. 为什么选择本地化部署&#xff1f; 去年我在尝试用AI助手处理一些敏感文档时&#xff0c;遇到了一个尴尬的问题——当我需要整理公司内部的技术方案时&#xff0c;既希望AI能帮我快速归纳要点&#xff0c;又担心把文…...

Naive UI 主题色定制实战:从组件覆盖到全局配置

1. 为什么需要定制Naive UI主题色&#xff1f; 当你使用Naive UI开发项目时&#xff0c;默认的绿色主题可能并不符合你的品牌风格。比如我们团队最近接手的一个金融类项目&#xff0c;客户要求整体UI采用深蓝色调&#xff0c;这时候就需要对Naive UI的主题色进行深度定制。主题…...

终极指南:如何用KCN-GenshinServer轻松搭建原神私服

终极指南&#xff1a;如何用KCN-GenshinServer轻松搭建原神私服 【免费下载链接】KCN-GenshinServer 基于GC制作的原神一键GUI多功能服务端。 项目地址: https://gitcode.com/gh_mirrors/kc/KCN-GenshinServer 还在为复杂的命令行配置而头疼吗&#xff1f;KCN-GenshinSe…...

掌握SQL窗口函数,轻松处理复杂数据分析

SQL 窗口函数&#xff08;Window Function&#xff09;是一种强大的分析工具&#xff0c;能够在不缩减原始数据行数的前提下执行复杂计算。这种函数通过对一组相关数据行&#xff08;称为"窗口"&#xff09;进行计算&#xff0c;并将结果直接附加到每一行记录中。窗口…...

.NET 10了,HttpClient还是不能用using吗?我做了一个实验

会突然变成玄学&#xff1a;有的人能跑&#xff0c;有的人会炸&#xff0c;有人说这是一个这是一个“bug”&#xff0c;在某某版本中会修复&#xff08;其实并没有&#xff09;&#xff0c;有人说这是一个feature&#xff0c;设计就是如此……所以我决定做一个实验&#xff0c;…...

实战应用:在快马平台构建带缺陷的微项目,演练测试面试实战题

今天想和大家分享一个特别实用的软件测试学习方法——通过构建带缺陷的微项目来演练测试面试题。这个方法不仅帮助我顺利通过了最近的面试&#xff0c;还让我对测试工作有了更深入的理解。 为什么选择在线书店作为测试项目&#xff1f; 在线书店系统包含了软件测试中最常见的…...

Factory IO + S7-PLCSIM V18 仿真避坑指南:如何解决传感器信号丢失和传送带卡料问题

Factory IO与S7-PLCSIM V18工业仿真实战&#xff1a;传感器优化与传送带故障排除指南 在工业自动化仿真领域&#xff0c;Factory IO与西门子S7-PLCSIM V18的组合已经成为工程师验证智能工厂逻辑的高效工具链。这套解决方案能够完整模拟从物料加工到仓储的完整产线&#xff0c;但…...

ai生成代码如何管理?快马结合gitbash实现智能开发工作流

今天想和大家分享一个高效的工作流&#xff1a;如何用AI生成代码后&#xff0c;通过GitBash进行规范的版本管理。最近在InsCode(快马)平台实践了这个方法&#xff0c;整个过程非常流畅。 AI生成代码阶段 在快马的AI对话区输入需求&#xff1a;“创建一个带有深色模式切换功能的…...

千问3.5-2B保姆级教程:从模型原理到业务集成的全栈技术路径

千问3.5-2B保姆级教程&#xff1a;从模型原理到业务集成的全栈技术路径 1. 认识千问3.5-2B视觉语言模型 千问3.5-2B是Qwen系列中的小型视觉语言模型&#xff0c;它能够同时理解图片内容和处理自然语言。简单来说&#xff0c;这个模型就像是一个能"看懂"图片并回答问…...

新零售系统开发的关键要素

新零售系统开发需要整合线上线下资源&#xff0c;实现数据驱动的智能化运营。以下是核心开发要点&#xff1a;技术架构设计采用微服务架构实现系统模块化&#xff0c;支持高并发场景。前端可选用React/Vue构建跨平台应用&#xff0c;后端推荐Spring Cloud或Node.js。数据库根据…...