🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快

对于软件测试,我们先按照开发阶段来进行划分,将软件测试分为单元测试、集成测试、系统测试、验收测试,下面我们来聊聊单元测试。

1、什么是单元测试?

在正式阐述什么是单元测试之前,我先给大家分享一个工厂组装手机的例子。

手机组装流水线按照图纸将各个电子元件组装焊接为各个模块组件(如喇叭,听筒,麦克,FPC,按键板,摄像头,LCD等),再将各个模块组件组装成一部完整的手机。

如果一起顺利,在给手机安装系统后就可以正常使用了。但是很不幸,大多数情况下的手机是无法使用的,那么就需要将已经组装好的手机重新拆机,逐个模块排查问题,在每个模块排查中需要对每个电子元件进行检测,通过花费大量的时间和精力才能定位到问题原因。

那么在后续的生产中,如何才能避免这种问题的发生呢?

你可能立即就会想到,为什么不在组装焊接前,就先测试每个要用到的电子元器件呢?这样你就可以先排除有问题的元器件,最大程度地防止组装完成后逐级排查问题的事情发生。

实践也证明,这的确是一个行之有效的好办法。

如果把手机的生产、测试和软件的开发、测试进行类比,你可以发现:

  • 电子元器件就像是软件中的单元,通常是函数或者类,对单个元器件的测试就像是软件测试中的单元测试;
  • 组装完成的功能模块组件如喇叭,听筒,麦克,FPC,按键板,摄像头,LCD等就像是软件中的模块,对功能模块组件的测试就像是软件中的集成测试;
  • 手机全部组装并安装系统就像是软件完成了预发布版本,手机全部组装并安装系统完成后的开机测试就像是软件中的系统测试;

通过这个类比,相信你已经体会到了单元测试对于软件整体质量的重要性,那么单元测试到底是什么呢?

单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。

2、什么是好的单元测试?

好的单元测试应当包含四种特性:正确,清晰,完整,健壮

  • 正确:单元测试是最基础的要求,必须要保证所写的函数或者类实现的功能是正确的,如果实现的功能都不能满足,那就是缺陷!
  • 清晰:单元测试可以帮助其他开发理解函数或者类的实现,所以要求单元测试用例简洁、清晰,需要有良好的可读性
  • 完整:单元测试需要考虑输入与输出组合的各种场景,保证单元测试的覆盖率
  • 健壮:健壮性是最容易被忽略的一项,当被测试的类或者函数被修改内部实现或者添加功能时,一个好的单测应该完全不需要被修改或者只有极少的修改。比如⼀个排序函数的单测实现是完全稳定的,它不应该跟着不同的排序算法的变化

3、怎么写单元测试?

可能大多数的测试人员不会接触到单元测试的编写,因为按照我个人的看法,开发人员根据自己写的代码编写单测用例是最合适不过的,也是最高效的。

虽然我们不需要实际去编写单测用例,但是我们还是需要了解怎么写单元测试。

单元测试的代码结构一般包含三部分:分别是准备、调用与断言

  • 准备:准备部分的⽬的是准备好调⽤所需要的外部环境,如数据,Stub(桩代码),Mock,临时变量,调⽤请求,环境背景变量等等。
  • 调用:调⽤部分则是实际调⽤需要测试⽅法,即函数或者流程本身。
  • 断言:断⾔部分判断调⽤部分的返回结果是否符合预期。

每个单元测试都应该能清晰地分出这三部分,当然有时调⽤断⾔两部分合在⼀起也是⽐较常见的。

4、玩转单元测试

下面我们来聊聊单元测试编写用例的相关知识,首先我们需要了解单元测试的三个重要部分,即驱动程序、桩程序、Mock

驱动程序:驱动程序(Driver)也称作驱动模块,用以模拟被测模块的上级模块,能够调用被测模块。在测试过程中,驱动模块接收测试数据,调用被测模块并把相关的数据传送给被测模块。

简单说就是你负责测试的模块没有main()方法入口,所以需要写一个带main的方法来调用你的模块或方法。这个就是驱动测试

桩程序:桩程序(Stub),也称桩模块,用以模拟被测模块工作过程中所调用的下层模块,即被测模块本身调用的其他关联函数。桩模块由被测模块调用,它们一般只进行很少的数据处理。

桩是指用来代替关联代码或者未实现的代码,为了让测试对象可以正常的执行,其实一般会硬编码一些输入和输出,保证被测模块能够正常运行

Mock:Mock除了保证Stub的功能之外,还可深入的模拟对象之间的交互方式,如:调用了几次、在某种情况下是否会抛出异常以及提供数据断言

接下来我们通过一个实例来学习单元测试用例的编写

# 待测试的方法
def calculator(type):# 调用桩代码获取数据num1 = __stub1()num2 = __stub2()# 调用mockmock_data = __mock_check()# +if type.lower() == 'add':type = 'add'ret = num1+num2assert ret == mock_data[type]print('{} + {} = {}'.format(num1,num2,ret))return ret# -if type.lower() == 'minus':type = 'minus'ret = num1-num2assert ret == mock_data[type]print('{} - {} = {}'.format(num1,num2,ret))return ret# *if type.lower() == 'multiply':type = 'multiply'ret = num1*num2assert ret == mock_data[type]print('{} * {} = {}'.format(num1,num2,ret))return ret# /if type.lower() == 'divide':type = 'divide'if num2 == 0:print('除法分母不能为0')return '除法分母不能为0'else:ret = num1/num2assert ret == mock_data[type]print('{} / {} = {}'.format(num1,num2,ret))return ret# 桩代码1
def __stub1():output = 20print('my stub的值是{}'.format(output))return output# 桩代码2
def __stub2():output = 5print('my stub的值是{}'.format(output))return output# Mock代码 => 提供断言数据
def __mock_check():mock_result = {}mock_result['add'] = 25mock_result['minus'] = 15mock_result['multiply'] = 100mock_result['divide'] = 4return mock_result# 驱动程序
if __name__=="__main__":print(calculator('add'))print(calculator('minus'))print(calculator('multiply'))print(calculator('divide'))

上面提供的是一个简单的单元测试,包含了驱动程序、被测对象、桩程序以及Mock代码

  • 驱动程序__main__作为被测对象的上级模块,运行时调用被测函数calculator
  • 被测函数calculator被调用后,通过桩代码__stub1、__stub2提供测试数据
  • 被测函数calculator通过不同的入参匹配不同的场景,不同场景获取的结果与Mock函数__mock_check进行比对断言,校验结果是否符合预期

被测函数成功返回如下:

my stub的值是20
my stub的值是5
20 + 5 = 25
25

被测函数失败返回如下:

my stub的值是20
Traceback (most recent call last):
my stub的值是5File "/Users/Desktop/demo/unittest_demo/ut_demo.py", line 73, in <module>print(calculator('add'))File "/Users/Desktop/demo/unittest_demo/ut_demo.py", line 21, in calculatorassert ret == mock_data[type]
AssertionError

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。

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

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

相关文章

四款好用的Windows虚拟打印机,文档转PDF

1&#xff0c;Microsoft Print To PDF 2&#xff0c;Foxit Reader PDF Printer 3&#xff0c;Adobe PDF 4&#xff0c;clawPDF 参考文档&#xff1a; https://mp.weixin.qq.com/s/_mt4J2RwhqQE36DRAvc-Rg

《map和set的使用介绍》

引言&#xff1a; 上次我们学习了第一个高阶数据结构—二叉搜索树&#xff0c;趁热打铁&#xff0c;今天我们就再来学习两个数据结构—map和set。 一&#xff1a;序列式容器和关联式容器 前面我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、arra…

PostgreSQL(二十六)分区表管理

目录 一、分区表特点 1、概念&#xff1a; 2、好处&#xff1a; 3、特点&#xff1a; 二、范围分区介绍 1、简介 2、范围分区实验&#xff1a; 三、list分区介绍 1、简介 2、list分区表实验 四、hash分区介绍 1、简介 2、hash分区表实验 五、混合分区介绍 1、简…

概率论中的生日问题,违背直觉?如何计算? 以及从人性金融的角度分析如何违背直觉的?

一、生日问题的概率计算&#xff1a;为何23人就有50%概率撞生日&#xff1f; 1. 问题背景与直觉矛盾 生日问题指&#xff1a;在n个人中&#xff0c;至少有两人生日相同的概率超过50%时&#xff0c;n的最小值是多少&#xff1f; 直觉判断&#xff1a;因一年有365天&#xff0c…

Qt for WebAssembly官方说明文档

链接 Qt for WebAssembly | Qt 5.15

前端自主实现将vue页面转为pdf文件下载

1.vue 转 PDF 在 Vue 项目中将 HTML 页面转换为 PDF 文件是一个常见需求&#xff0c;特别是在需要生成报告或打印页面时。本文将介绍如何使用 html2canvas 和 jspdf 库实现这一功能。 2.安装依赖 首先&#xff0c;我们需要安装两个库&#xff1a;html2canvas 和 jspdf 。可以…

TCP 坚持定时器详解:原理、配置与最佳实践​

一、TCP 坚持定时器基础原理 1.1 坚持定时器的设计目的 TCP 坚持定时器 (TCP Persist Timer) 是 TCP 协议中用于处理接收窗口为零情况的重要机制&#xff0c;其核心设计目的是防止 TCP 连接在窗口更新 ACK 丢失时陷入死锁状态。当 TCP 连接的接收方通告一个窗口大小为 0 的 A…

大厂测开实习和小厂开发实习怎么选

先说选择&#xff0c;这个可以百分百确定选大厂&#xff0c;title很重要。 要想弄清楚那个选择对自己最有利&#xff0c;可以思考下实习的意义是什么&#xff1f; 实习无非就是给简历加分&#xff0c;拿到好offer&#xff0c;高薪offer。 那这就需要思考&#xff0c;简历怎么让…

Unity中的urp和普通的标准渲染管线区别在哪

Unity中的URP&#xff08;Universal Render Pipeline&#xff09;与内置标准渲染管线&#xff08;Built-in Render Pipeline&#xff09;的区别深刻反映了Unity渲染技术的演进方向。以下从架构、性能、功能、工作流等多个维度进行深度分析&#xff1a; 1. 底层架构与设计哲学 标…

Vscode 编写Markdown支持 plantuml书写

1&#xff1a; 下载PlantUml 插件&#xff1a; 2&#xff1a; 安装java https://www.oracle.com/java/technologies/downloads/ 3&#xff1a; 安装Graphviz https://graphviz.org/download/ 4&#xff1a; 下载plantuml.jar https://plantuml.com/zh/download 5&…

设计模式(C++/Qt)-工厂模式

在软件开发中&#xff0c;对象创建是基础但关键的任务——工厂模式提供了一种优雅的解决方案&#xff0c;让您的代码摆脱硬编码的依赖关系 一、为什么需要工厂模式&#xff1f; 在C/Qt开发中&#xff0c;我们经常面临这样的困境&#xff1a; 对象创建逻辑分散在代码各处新增…

Pydantic 模型

本文将详细介绍 Pydantic 模型 和 BaseModel 的核心概念&#xff0c;并通过实际代码示例如何从零开始编写自己的 Pydantic 模型。 1. Pydantic 是什么&#xff1f; Pydantic 是一个 Python 库&#xff0c;主要用于&#xff1a; 数据验证&#xff1a;确保输入数据符合预期的类…

【Unity智能模型系列】MediaPipeUnityPlugin 实现人脸数据获取

目录 一、MediaPipeUnity 简介 二、MediaPipeUnity 的核心组成 1. Graph 构建系统 2. 解决方案类(Solution) 3. 解释注释Annotation 系统 三、MediaPipeUnity 的典型使用流程 四、典型示例解析 1、案例 Face Detection图形人脸检测 2、案例 Face Detection图形人脸检…

iOS App 上架步骤解析:适合资源有限团队的上架流程与注意事项

对于不少创业型或初创阶段的开发团队来说&#xff0c;人员配置紧凑、设备有限是常态。在这种背景下&#xff0c;完成一次合规、高效的iOS应用发布往往不是技术难点&#xff0c;而是流程协同与资源调配的问题。 我们是一支5人团队&#xff0c;开发一款社交类工具型App&#xff…

Redis雪崩、穿透、击穿原理及解决方案

以下是 Redis 缓存穿透、击穿与雪崩的原理及解决方案的深度解析&#xff0c;结合工业级实践整理&#xff1a; &#x1f50d; ‌一、问题原理与区别‌ ‌问题类型‌‌触发条件‌‌核心特征‌‌危害‌‌缓存穿透‌查询‌不存在的数据‌绕过缓存直击数据库&#xff0c;导致无效查…

DFX 动态重构的概念和实现

DFX 动态重构的概念和实现 背景介绍 本文内容当前仅限于XILINX或者和XILINX具有相同结构的FPGA器件。 FPGA 技术提供了在现场进行编程和重新编程的灵活性&#xff0c;而无需通过重新制造流程来实现设计修改。动态功能交换&#xff08;Dynamic Function eXchange, DFX&#x…

hutool 导出数据报错:org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException

Excel 导出报错 org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : The part /docProps/core.xml failed to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marsh…

【学习】win 本地部署qwen3

这里写自定义目录标题 环境搭建下载Ollama安装olama修改模型下载位置&#xff08;可以不设置&#xff09;通过ollama下载/启动模型常用命令其他 环境搭建 下载Ollama 安装olama 默认安装位置是c盘 安装到指定位置使用以下命令 OllamaSetup.exe /DIR"d:\Ollama"修改…

python的__init__.py

在此之前先确认一个概念是否弄清 模块命名空间 1. 目录结构 假设你有以下结构&#xff1a; testpkg/__init__.pyfool.pymaybe.py内容如下&#xff1a; fool.py # testpkg/fool.py class Fool:passmaybe.py # testpkg/maybe.py class Maybe:pass__init__.py &#xff08…

四核 A53+工业级存储:移远 SC200L 与 pSLC SD NAND 如何重构 T-BOX 性能边界?

博客目录 一、移远 SC200L&#xff1a;T-BOX 的 “智慧大脑”二、米客方德 MKDN064GIL-ZA T-BOX&#xff1a;数据安全的坚固堡垒三、深度协同&#xff1a;拓展 T-BOX 应用边界 在车联网浪潮席卷而来的当下&#xff0c;T-BOX 作为汽车与外界交互的核心枢纽&#xff0c;其性能优劣…