软件单元测试

单元测试目的和意义

对于非正式的软件(其特点是功能比较少,后续也不有新特性加入,不用负责维护),我们可以使用debug单步执行,内存修改,检查对应的观测点是否符合要求来进行单元测试,这种方法速度比较快,使用也比较方便,如果使用单元测试框架编写单元测试用例测试,则效率很低。
但是对于正式商用的软件,往往拥有大量的特性,采用敏捷进行开发,会经过多次迭代,每次迭代都会有新特性加入。而且发布之后也会经常收到用户需求,进行特性的增量开发。如何能保证新加入的特性以及问题修改不会影响到已有的特性。这时编写单元测试用例就比较有作用了。

首先单元测试可以保证代码质量。通过单元测试不但可以对函数正常功能进行测试,而且可以将一些系统测试时很难构造的异常场景都覆盖到。有效的保证代码质量。
其次保证代码的可维护以及可扩展。每次特性变化都编写单元测试用例,这样单元测试用例会覆盖所有的特性,这样的话后续对于代码重构优化、以及新特性代码的加入都可以观察到对老的特性影响。
测试驱动开发(TDD),在正式代码编写前,可以先考虑进行单元测试代码的编写,这样可以保证功能的完备性,并较好的优化代码结构。

单元测试思路和方法

单元测试开始的时间

软件开发过程中,单元测试和编码共属实现阶段,进行动态的单元测试前要先对程序进行静态分析(例如PCLint等)和代码审查。
因为使用动态测试技术要准备测试用例,进行结果记录和分析,工作量大,发现错误太多会降低动态测试效率;所以先使用静态分析和代码审查技术,能充分地发挥人的判断和思维优势,检查出对机器而言很难发现的错误。典型的包括代码和设计规格的一致性,代码逻辑表达式的正确性。一旦发现错误,就知道错误的性质和位置,调试代价较低;

单元测试代码的结构

单元测试一般是对函数级别的测试,测试目的函数的输入输出,检查在特定的输入情况下,对应的输出是否符合期望值。其输入可能是函数的参数,也可能是函数中从其他模块获取的数据。函数的输出可能是返回值、输出参数,也可能是向其他模块提供的数据。

由于单元测试针对程序单元,而程序单元并不是一个独立可运行的程序,往往需要系统API,或者其他模块提供动态库或网络通讯支持,因此,在考虑测试模块时,同时要考虑到它和外界其他模块的联系,用一些辅助模块去模拟与被测模块关联的其他模块。
所以单元测试代码结构上分为两种,一种是桩代码,即模拟其他模块的代码,桩代码可以提供函数接口、初始化数据等信息,用于模拟外部模块接口。另一种是测试代码,测试代码通过调用被测函数观察结果是否符合预期。
若发现对某个函数进行测试时,需要做大量的桩代码来做输入的模拟,或者检查输出时需要检查的都是其他模块中的信息,则说明对应函数的耦合度太高,需要考虑将对应函数的功能和其他模块剥离,其他模块提供的数据作为函数的参数输入,函数参数或返回值输出结果,其他模块从函数外部获取对应的数据。
正式发布的代码结构
在这里插入图片描述
单元测试的代码结构
在这里插入图片描述
单元测试代码需要和发布代码隔离,不能污染发布代码,不能在发布代码中充斥有大量的单元测试代码,这样不但后续代码开发维护人员理解单元测试用例比较困难,而且容易造成在发布版本中错误的调用了单元代码,出现功能异常。一般可以通过新增加一个单元测试工程,使用工程的编译宏来控制不同的头文件以达到隔离效果。

单元测试用例的设计

单元测试用例设计思路可以从两个方面进行,一个是功能实现相关,即从外部进行设计,考虑对应的模块要实现什么功能,每个功能会有什么输入输出。做到功能覆盖,在发布代码编写前后进行都可以。另一个是内部逻辑相关,即从内部考虑,从发布代码的逻辑分支进行设计,做到分支覆盖。在发布代码编写后进行。
具体对某个单元进行测试时,可以按照优先级,以下步骤进行:
第一步设计基本功能测试用例,检查被测单元至少在需求功能级别能够返回期望的结果;
第二步设计功能正面测试用例,检查被测单元对于设计要求的正确输入需要返回期望结果;
第三步设计功能反面测试用例,检查被测单元对于设计要求的错误输入需要返回期望结果;
最后一步设计性能测试用例, 检查被测单元在大量数据情况下的执行效率。

单元测试的目的是对函数功能的测试,所以测试时并不是需要对所有函数进行测试,需要进行选择,如果对应的函数中有较为复杂的逻辑代码,则必须测试,如果函数中基本上没有什么逻辑,则没有必要测试。
测试代码编写时需要注意代码的可维护性以及可读性,对于重复出现的代码,例如构造初始环境等尽量抽取程函数或者宏,而对于某一项测试尽量做到封装成一条语句。必要时增加注释信息,尽量做到从单元测试代码即可知道要测试什么特性,对应特性输入、输出是什么。

单元测试成本和效率

单元测试不可避免的增加了开发的工作量,但是按定义,单元测试只测试程序单元自身的功能。因此,它不能发现集成错误、性能问题、或者其他系统级别的问题。单元测试只能表明测到的问题,不能表明不存在未测试到的错误。所以单元测试并不能代替系统测试的工作。
单元测试的意义在于对于异常功能的测试,以及对于后续代码维护开发的保障。

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

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

相关文章

把网站改为HTTPS访问方法

HTTPS是使用TSL/SSL加密超文本传输协议的扩展,用于跨网络的安全传输。网站更改为HTTPS,直接在网站形象上可以得到提升,更重要的是您的网站肯定会在排名和提升方面受益。机密信息的交换需要受到保护,以阻止未经授权的访问。 加密&a…

如何通过 4 个简单步骤基于ESP32部署 Arduino 机器学习分类器

步骤 1. 加载数据 为了训练分类器,我们需要一些数据。如果您从零开始并且还没有首选的文件夹结构,我建议您创建一个文件夹来保存您收集的数据。 .csv在此文件夹中,为每个要分类的类创建一个专用文件 ( ),并在每行上放置一个示例。如果这样做,您可以使用下一个函数来加载…

四十八.图卷积网络(GCN)

1.卷积神经网络 CNN 在图像识别等任务中具有重要作用,主要是因为 CNN 利用了图片(信号)在其域中的局部平移不变性。由于图结构不存在平移不变性,所以 CNN 无法直接在图上进行卷积。 1.1局部平移不变性 CNN 之所以能成为图像领域…

类加载机制——双亲委派机制

类加载器分类 类加载器 类加载器(英文:ClassLoader)负责加载 .class 字节码文件,.class 字节码文件在文件开头有特定的文件标识。ClassLoader 只负责 .class 字节码文件的加载,至于它是否可以运行,则由 E…

kafka-事务

1. 事务的5个API // 1初始化事务 void initTransactions();// 2开启事务 void beginTransaction() throws ProducerFencedException;// 3在事务内提交已经消费的偏移量&#xff08;主要用于消费者&#xff09; void sendOffsetsToTransaction(Map<TopicPartition, OffsetAn…

Vue-组件二次封装

本次对el-input进行简单封装进行演示 封装很简单&#xff0c;就给激活样式的边框(主要是功能) 本次封装主要使用到vue自带的几个对象 $attrs&#xff1a;获取绑定在组件上的所有属性$listeners: 获取绑定在组件上的所有函数方法$slots&#xff1a; 获取应用在组件内的所有插槽 …

成功解决Android设备adb连接后显示device unauthorized

一、提出问题 在电脑通过USB连接新的Android设备&#xff0c;想要通过adb来进行一些操作时&#xff0c;却发现命令提示符上在输入下面命令后显示设备未授权的信息也就是"unauthorized" adb devices二、不可行的解决方案 有人提出的解决方案是打开Android设备的开发…

测试开发(一) 使用Vue开发chrome插件

目录 一、引言 二、功能说明 三、【配置】操作演示 四、【请求拦截】演示 不断访问博客&#x

检测前端是否可以ping通后端返回的ip地址

检测前端是否可以ping通后端返回的ip地址 前端检测是否可ping通ip地址&#xff08;PC端&#xff09;前端检测是否可ping通ip地址&#xff08;uniapp小程序端&#xff09; 前端检测是否可ping通ip地址&#xff08;PC端&#xff09; // 前端检测是否可ping通ip地址 ping…

2023年新手如何学剪辑视频 想学视频剪辑如何入门

随着短视频、vlog等媒体形式的兴起&#xff0c;视频剪辑已经成为了热门技能。甚至有人说&#xff0c;不会修图可以&#xff0c;但不能不会剪视频。实际上&#xff0c;随着各种智能软件的发展&#xff0c;视频剪辑已经变得越来越简单。接下来&#xff0c;一起来看看新手如何学剪…

【ChatGPT 指令大全】怎么使用ChatGPT来帮我们写作

在数字化时代&#xff0c;人工智能为我们的生活带来了无数便利和创新。在写作领域&#xff0c;ChatGPT作为一种智能助手&#xff0c;为我们提供了强大的帮助。不论是作文、文章&#xff0c;还是日常函电&#xff0c;ChatGPT都能成为我们的得力助手&#xff0c;快速提供准确的文…

MySQL — MVCC

文章目录 MVCCMVCC 实现原理隐藏字段undo logundo log的用途undo log类型 版本链ReadView MVCC InnoDB是一个多版本的存储引擎。它保留有关已更改行的旧版本的信息&#xff0c;以支持并发和回滚等事务性特性。这些信息存储在undo表空间中的数据结构称为回滚段。InnoDB使用回滚…

培训报名小程序报名功能完善

目录 1 修改数据源2 修改表单3 支付成功时修改状态4 创建报名成功页5 最终的效果总结 目前我们的报名功能已经搭建了一个基础版&#xff0c;后续需要展示用户已经报名的信息&#xff0c;需要添加一个状态来显示用户是否成功付费。 1 修改数据源 打开我们的报名数据源&#xff…

mysql大量数据导入记要

需求描述 在工作中经历过两个项目要对数据库中的数据做大量数据的导出&#xff0c;转换和导入的工作。对于不涉及数据格式转换的导出导入工作&#xff0c;一般都是数据的备份。这个工作一般都由DBA搞定。对于要进行格式转换的工作&#xff0c;一般还是要由程序员参与。除非DBA…

解决ubuntu22卡死问题

解决ubuntu22卡死问题 最近用ubuntu2204做odoo开发&#xff0c;经常卡死&#xff0c;不清楚是什么原因&#xff0c;后来无意中发现pycharm占了50%内存&#xff08;公司电脑&#xff0c;一共8G&#xff09;&#xff0c;然后看了一下交换分区&#xff0c;总共2G&#xff08;默认…

前端中常见的设计模式

1.单例模式 描述&#xff1a;保证一个类仅有实例&#xff0c;并提供一个可以全局访问他的点&#xff0c;它通常用于管理应用程序的全局状态或资源&#xff0c;例如一个唯一的状态管理器。 代码示例&#xff1a; class Singleton {constructor() {if (!Singleton.instance) {…

【基础类】—前端算法类

一、排序 1. 排序方法列表 2. 常见排序方法 快速排序选择排序希尔排序 二、堆栈、队列、链表 堆栈、队列、链表 三、递归 递归 四、波兰式和逆波兰式 理论源码

机器学习笔记之优化算法(十一)梯度下降法:凸函数VS强凸函数

机器学习笔记之优化算法——梯度下降法&#xff1a;凸函数VS强凸函数 引言凸函数&#xff1a;凸函数的定义与判定条件凸函数的一阶条件凸函数的梯度单调性凸函数的二阶条件 强凸函数强凸函数的定义强凸函数的判定条件强凸函数的一阶条件强凸函数的梯度单调性强突函数的二阶条件…

redis的主从复制,哨兵和cluster集群

目录 一、redis的高可用 1&#xff09;redis高可用的概念 2&#xff09;Redis的高可用技术 二、redis主从复制 1&#xff09;主从复制的作用 2&#xff09;主从复制流程 三、redis一主二从的部署 实验组件 实验步骤 环境准备 修改内核参数 安装 Redis 创建redis工…

前后端分离式项目架构流程复盘之宿舍管理系统

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;【&#x1f387;前端】先创建Vue-cli项目&#xff08;版本2.6.10&#xff0c;仅包含babel&#xff09;&#xff0c;请选择此项目并创建 【整理简化项目模板】【&#x1f380;创建路由】…