软件单元测试
单元测试目的和意义
对于非正式的软件(其特点是功能比较少,后续也不有新特性加入,不用负责维护),我们可以使用debug单步执行,内存修改,检查对应的观测点是否符合要求来进行单元测试,这种方法速度比较快,使用也比较方便,如果使用单元测试框架编写单元测试用例测试,则效率很低。
但是对于正式商用的软件,往往拥有大量的特性,采用敏捷进行开发,会经过多次迭代,每次迭代都会有新特性加入。而且发布之后也会经常收到用户需求,进行特性的增量开发。如何能保证新加入的特性以及问题修改不会影响到已有的特性。这时编写单元测试用例就比较有作用了。
首先单元测试可以保证代码质量。通过单元测试不但可以对函数正常功能进行测试,而且可以将一些系统测试时很难构造的异常场景都覆盖到。有效的保证代码质量。
其次保证代码的可维护以及可扩展。每次特性变化都编写单元测试用例,这样单元测试用例会覆盖所有的特性,这样的话后续对于代码重构优化、以及新特性代码的加入都可以观察到对老的特性影响。
测试驱动开发(TDD),在正式代码编写前,可以先考虑进行单元测试代码的编写,这样可以保证功能的完备性,并较好的优化代码结构。
单元测试思路和方法
单元测试开始的时间
软件开发过程中,单元测试和编码共属实现阶段,进行动态的单元测试前要先对程序进行静态分析(例如PCLint等)和代码审查。
因为使用动态测试技术要准备测试用例,进行结果记录和分析,工作量大,发现错误太多会降低动态测试效率;所以先使用静态分析和代码审查技术,能充分地发挥人的判断和思维优势,检查出对机器而言很难发现的错误。典型的包括代码和设计规格的一致性,代码逻辑表达式的正确性。一旦发现错误,就知道错误的性质和位置,调试代价较低;
单元测试代码的结构
单元测试一般是对函数级别的测试,测试目的函数的输入输出,检查在特定的输入情况下,对应的输出是否符合期望值。其输入可能是函数的参数,也可能是函数中从其他模块获取的数据。函数的输出可能是返回值、输出参数,也可能是向其他模块提供的数据。
由于单元测试针对程序单元,而程序单元并不是一个独立可运行的程序,往往需要系统API,或者其他模块提供动态库或网络通讯支持,因此,在考虑测试模块时,同时要考虑到它和外界其他模块的联系,用一些辅助模块去模拟与被测模块关联的其他模块。
所以单元测试代码结构上分为两种,一种是桩代码,即模拟其他模块的代码,桩代码可以提供函数接口、初始化数据等信息,用于模拟外部模块接口。另一种是测试代码,测试代码通过调用被测函数观察结果是否符合预期。
若发现对某个函数进行测试时,需要做大量的桩代码来做输入的模拟,或者检查输出时需要检查的都是其他模块中的信息,则说明对应函数的耦合度太高,需要考虑将对应函数的功能和其他模块剥离,其他模块提供的数据作为函数的参数输入,函数参数或返回值输出结果,其他模块从函数外部获取对应的数据。
正式发布的代码结构

单元测试的代码结构

单元测试代码需要和发布代码隔离,不能污染发布代码,不能在发布代码中充斥有大量的单元测试代码,这样不但后续代码开发维护人员理解单元测试用例比较困难,而且容易造成在发布版本中错误的调用了单元代码,出现功能异常。一般可以通过新增加一个单元测试工程,使用工程的编译宏来控制不同的头文件以达到隔离效果。
单元测试用例的设计
单元测试用例设计思路可以从两个方面进行,一个是功能实现相关,即从外部进行设计,考虑对应的模块要实现什么功能,每个功能会有什么输入输出。做到功能覆盖,在发布代码编写前后进行都可以。另一个是内部逻辑相关,即从内部考虑,从发布代码的逻辑分支进行设计,做到分支覆盖。在发布代码编写后进行。
具体对某个单元进行测试时,可以按照优先级,以下步骤进行:
第一步设计基本功能测试用例,检查被测单元至少在需求功能级别能够返回期望的结果;
第二步设计功能正面测试用例,检查被测单元对于设计要求的正确输入需要返回期望结果;
第三步设计功能反面测试用例,检查被测单元对于设计要求的错误输入需要返回期望结果;
最后一步设计性能测试用例, 检查被测单元在大量数据情况下的执行效率。
单元测试的目的是对函数功能的测试,所以测试时并不是需要对所有函数进行测试,需要进行选择,如果对应的函数中有较为复杂的逻辑代码,则必须测试,如果函数中基本上没有什么逻辑,则没有必要测试。
测试代码编写时需要注意代码的可维护性以及可读性,对于重复出现的代码,例如构造初始环境等尽量抽取程函数或者宏,而对于某一项测试尽量做到封装成一条语句。必要时增加注释信息,尽量做到从单元测试代码即可知道要测试什么特性,对应特性输入、输出是什么。
单元测试成本和效率
单元测试不可避免的增加了开发的工作量,但是按定义,单元测试只测试程序单元自身的功能。因此,它不能发现集成错误、性能问题、或者其他系统级别的问题。单元测试只能表明测到的问题,不能表明不存在未测试到的错误。所以单元测试并不能代替系统测试的工作。
单元测试的意义在于对于异常功能的测试,以及对于后续代码维护开发的保障。
相关文章:
软件单元测试
单元测试目的和意义 对于非正式的软件(其特点是功能比较少,后续也不有新特性加入,不用负责维护),我们可以使用debug单步执行,内存修改,检查对应的观测点是否符合要求来进行单元测试,…...
Redis | 集群模式
Redis | 集群模式 随着互联网应用规模的不断扩大,单一节点的数据库性能已经无法满足大规模应用的需求。为了提高数据库的性能和可扩展性,分布式数据库成为了解决方案之一。Redis 作为一个高性能的内存数据库,自然也有了自己的分布式部署方式…...
8.3day04git+数据结构
文章目录 git版本控制学习高性能的单机管理主机的心跳服务算法题 git版本控制学习 一个免费开源,分布式的代码版本控制系统,帮助开发团队维护代码 作用:记录代码内容,切换代码版本,多人开发时高效合并代码内容 安装g…...
04-5_Qt 5.9 C++开发指南_QComboBox和QPlainTextEdit
文章目录 1. 实例功能概述2. 源码2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. 实例功能概述 QComboBox 是下拉列表框组件类,它提供一个下拉列表供用户选择,也可以直接当作一个QLineEdit 用作输入。OComboBox 除了显示可见下拉列表外,每个…...
Sqlserver_Oracle_Mysql_Postgresql不同关系型数据库之主从延迟的理解和实验
关系型数据库主从节点的延迟是否和隔离级别有关联,个人认为两者没有直接关系,主从延迟在关系型数据库中一般和这两个时间有关:事务日志从主节点传输到从节点的时间事务日志在从节点的应用时间 事务日志从主节点传输到从节点的时间࿰…...
Clickhouse学习系列——一条SQL完成gourp by分组与不分组数值计算
笔者在近一两年接触了Clickhouse数据库,在项目中也进行了一些实践,但一直都没有一些技术文章的沉淀,近期打算做个系列,通过一些具体的场景将Clickhouse的用法进行沉淀和分享,供大家参考。 首先我们假设一个Clickhouse数…...
做好“关键基础设施提供商”角色,亚马逊云科技加快生成式AI落地
一场关于生产力的革命已在酝酿之中。全球管理咨询公司麦肯锡在最近的报告《生成式人工智能的经济潜力:下一波生产力浪潮》中指出,生成式AI每年可能为全球经济增加2.6万亿到4.4万亿美元的价值。在几天前的亚马逊云科技纽约峰会中,「生成式AI」…...
如何使用 ChatGPT 规划家居装修
你正在计划家庭装修项目,但不确定从哪里开始?ChatGPT 随时为你提供帮助。从集思广益的设计理念到估算成本,ChatGPT 可以简化你的家居装修规划流程。在本文中,我们将讨论如何使用 ChatGPT 有效地规划家居装修,以便你的项…...
题解 | #1002.Random Nim Game# 2023杭电暑期多校7
1002.Random Nim Game 诈骗博弈题 题目大意 Nim是一种双人数学策略游戏,玩家轮流从不同的堆中移除棋子。在每一轮游戏中,玩家必须至少取出一个棋子,并且可以取出任意数量的棋子,条件是这些棋子都来自同一个棋子堆。走最后一步棋…...
篇九:组合模式:树形结构的力量
篇九:“组合模式:树形结构的力量” 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。 另外有2本不错的关于设计模式的资料,…...
【注册表】windows系统注册表常用修改方案
文章目录 ◆ 修改IE浏览器打印页面参数设置◆气泡屏幕保护◆彩带屏幕保护程序◆过滤IP(适用于WIN2000)◆禁止显示IE的地址栏◆禁止更改IE默认的检查(winnt适用)◆允许DHCP(winnt适用)◆局域网自动断开的时间(winnt适用)◆禁止使用“重置WEB设置”◆禁止更…...
ant-design-vue 4.x升级问题-样式丢失问题
[vue] ant-design-vue 4.x升级问题-样式丢失问题 项目环境问题场景解决方案 该文档是在升级ant-design-vue到4.x版本的时候遇到的问题 项目环境 "vue": "^3.3.4", "ant-design-vue": "^4.0.0", "vite": "^4.4.4&quo…...
【果树农药喷洒机器人】Part3:变量喷药系统工作原理介绍
本专栏介绍:免费专栏,持续更新机器人实战项目,欢迎各位订阅关注。 关注我,带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章! 文章目录 一、变量喷药系统工作原理二、液压通路设计与控制系统封装2.1液压通路…...
GoogLeNet创新点总结
GoogLeNet是一种深度卷积神经网络架构,于2014年由Google团队提出,是ILSVRC(ImageNet Large Scale Visual Recognition Challenge)比赛的冠军模型,其创新点主要集中在以下几个方面: Inception模块&#…...
不同路径1、2、3合集(980. 不同路径 III)
不同路径一 矩形格,左上角 到 右下角。 class Solution {int [] directX new int[]{-1,1,0,0};int [] directY new int[]{0,0,-1,1};int rows;int cols;public int uniquePathsIII(int[][] grid) {if (grid null || grid.length 0 || grid[0].length 0) {ret…...
【云原生】Yaml文件详解
目录 一、YAML 语法格式1.1查看 api 资源版本标签1.2 写一个yaml文件demo1.3 详解k8s中的port 一、YAML 语法格式 Kubernetes 支持 YAML 和 JSON 格式管理资源对象JSON 格式:主要用于 api 接口之间消息的传递YAML格式:用于配置和管理,YAML 是…...
ffmpeg下载安装教程
ffmpeg官网下载地址https://ffmpeg.org/download.html 这里以windows为例,鼠标悬浮到windows图标上,再点击 Windows builds from gyan.dev 或者直接打开 https://www.gyan.dev/ffmpeg/builds/ 下载根据个人需要下载对应版本 解压下载的文件,并复制bin所在目录 新打开一个命令…...
uniapp之当你问起“tab方法触发时eventchange也跟着触发了咋办”时
我相信没有大佬会在这个问题上卡两个小时吧,记下来大家就当看个乐子了。 当时问题就是,点击tab头切换的时候,作为tab滑动事件的eventchange同时触发了,使得接口请求了两次 大概是没睡好,我当时脑子老想着怎么阻止它冒…...
TS 踩坑之路(四)之 Vue3
一、在使用定义默认值withDefaults和defineProps 组合时,默认值设置报错 代码案例 报错信息 不能将类型“{ isBackBtn: false; }”分配给类型“(props: PropsType) > RouteMsgType”。 对象字面量只能指定已知属性,并且“isBackBtn”不在类型“(pro…...
【音视频】edge与chrome在性能上的比较
目录 结论先说 实验 结论 实验机器的cpu配置 用EDGE拉九路编辑 google拉五路就拉不出来了 资源使用情况 edge报错编辑 如果服务器端 性能也满 了,就会不回复;验证方式 手动敲 8081,不回应。 结论先说 实验 用chrome先拉九路&#…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
