golang 单元测试
一、单元测试
1. 单元测试是什么
单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类、超类、抽象类等中的方法。单元测试就是软件开发中对最小单位进行正确性检验的测试工作。
不同地方对单元测试有的定义可能会有所不同,但有一些基本共识:
- 单元测试是比较底层的,关注代码的局部而不是整体。
- 单元测试是开发人员在写代码时候写的。
- 单元测试需要比其他测试运行得快。
2. 单元测试的意义
- 提高代码质量。代码测试都是为了帮助开发人员发现问题从而解决问题,提高代码质量。
- 尽早发现问题。问题越早发现,解决的难度和成本就越低。
- 保证重构正确性。随着功能的增加,重构(修改老代码)几乎是无法避免的。很多时候我们不敢重构的原因,就是担心其它模块因为依赖它而不工作。有了单元测试,只要在改完代码后运行一下单测就知道改动对整个系统的影响了,从而可以让我们放心的重构代码。
- 简化调试过程。单元测试让我们可以轻松地知道是哪一部分代码出了问题。
- 简化集成过程。由于各个单元已经被测试,在集成过程中进行的后续测试会更加容易。
- 优化代码设计。编写测试用例会迫使开发人员仔细思考代码的设计和必须完成的工作,有利于开发人员加深对代码功能的理解,从而形成更合理的设计和结构。
- 单元测试是最好的文档。单元测试覆盖了接口的所有使用方法,是最好的示例代码。而真正的文档包括注释很有可能和代码不同步,并且看不懂。
3. 单元测试用例编写的原则
3.1 理论原则
- 快。单元测试是回归测试,可以在开发过程的任何时候运行,因此运行速度必须快
- 一致性。代码没有改变的情况下,每次运行得结果应该保持确定且一致
- 原子性。结果只有两种情况:Pass / Fail
- 用例独立。执行顺序不影响;用例间没有状态共享或者依赖关系;用例没有副作用(执行前后环境状态一致)
- 单一职责。一个用例只负责一个场景
- 隔离。功能可能依赖于数据库、web 访问、环境变量、系统时间等;一个单元可能依赖于另一部分代码,用例应该解除这些依赖
- 可读性。用例的名称、变量名等应该具有可读性,直接表现出该测试的目标
- 自动化。单元测试需要全自动执行。测试程序不应该有用户输入;测试结果应该能直接被电脑获取,不应该由人来判断。
3.2 规约原则
在实际编写代码过程中,不同的团队会有不同团队的风格,只要团队内部保持有一定的规约即可,比如:
- 单元测试文件名必须以 xxx_test.go 命名
- 方法必须是 TestXxx 开头,建议风格保持一致(驼峰或者下划线)
- 方法参数必须 t *testing.T
- 测试文件和被测试文件必须在一个包中
3.3 衡量原则
单元测试是要写额外的代码的,这对开发同学的也是一个不小的工作负担,在一些项目中,我们合理的评估单元测试的编写,我认为我们不能走极端,当然理论上来说全写肯定时好的,但是从成本,效率上来说我们必须做出权衡,衡量原则如下:
- 优先编写核心组件和逻辑模块的测试用例
- 逻辑类似的组件如果存在多个,优先编写其中一种逻辑组件的测试用例
- 发现 Bug 时一定先编写测试用例进行 Debug
- 关键 util 工具类要编写测试用例,这些 util 工具适用的很频繁,所以这个原则也叫做热点原则,和第 1 点相呼应。
- 测试用户应该独立,一个文件对应一个,而且不同的测试用例之间不要互相依赖。
- 测试用例的保持更新
4. 单元测试用例设计方法
4.1 规范(规格)导出法
规范(规格)导出法将需求”翻译“成测试用例。
例如,一个函数的设计需求如下:
函数:一个计算平方根的函数 输入: 实数 输出: 实数 要求: 当输入一个 0 或者比 0 大的实数时,返回其正的平方根;当输入一个小于 0 的实数时,显示错误信息“平方根非法—输入之小于 0”,并返回 0;库函数printf()
可以用来输出错误信息。
在这个规范中有 3 个陈述,可以用两个测试用例来对应:
- 测试用例 1:输入 4,输出 2。
- 测试用例 2:输入-1,输出 0。
4.2 等价类划分法
等价类划分法假定某一特定的等价类中的所有值对于测试目的来说是等价的,所以在每个等价类中找一个之作为测试用例。
- 按照 [输入条件][有效等价类][无效等价类] 建立等价类表,列出所有划分出的等价类
- 为每一个等价类规定一个唯一的编号
- 设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖地有效等价类。重复这一步,直到所有的有效等价类都被覆盖为止
- 设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类。重复这一步,直到所有的无效等价类都被覆盖为止
例如,注册邮箱时要求用 6~18 个字符,可使用字母、数字、下划线,需以字母开头。
测试用例:
4.3 边界值分析法
边界值分析法使用与等价类测试方法相同的等价类划分,只是边界值分析假定 错误更多地存在于两个划分的边界上。
边界值测试在软件变得复杂的时候也会变得不实用。边界值测试对于非向量类型的值(如枚举类型的值)也没有意义。
例如,和4.1相同的需求: 划分(ii)的边界为 0 和最大正实数;划分(i)的边界为最小负实数和 0。由此得到以下测试用例:
- 输入 {最小负实数}
- 输入 {绝对值很小的负数}
- 输入 0
- 输入 {绝对值很小的正数}
- 输入 {最大正实数}
4.4 基本路径测试法
基本路径测试法是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。设计出的测试用例要保证在测试中程序的每个可执行语句至少执行一次。
基本路径测试法的基本步骤:
- 程序的控制流图:描述程序控制流的一种图示方法。
- 程序圈复杂度:McCabe 复杂性度量。从程序的环路复杂性可导出程序基本路径集合中的独立路径条数,这是确定程序中每个可执行语句至少执行一次所必须的测试用例数目的上界。
- 导出测试用例:根据圈复杂度和程序结构设计用例数据输入和预期结果。
- 准备测试用例:确保基本路径集中的每一条路径的执行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2019-03-23 Laravel中路由怎么写(二)
2019-03-23 Laravel中路由怎么写(一)
2019-03-23 详解Laravel的目录结构
2017-03-23 使用FFMPeg对视频进行处理