目录
1、前言
1.1 定义
1.2 单元测试CheckList
1.3 测试模型
1.3.1 冰淇淋模型
1.3.2 金字塔模型
1.4 为什么要做单元测试
1.5单元测试编码规则
1.6 单元测试用例的设计要素
2、测试框架介绍
3、单元测试开发规范
3.1 注意事项
3.2 命名规范
3.3 输入数据规范
3.4 结果校验规范
1、前言
1.1 定义
单元测试(unit testing),是指对软件中的最小可测单元进行检查和验证。单元测试中的单元,可以是C语言中的一个函数,可以是Java语言中的一个类或者方法,图形化软件中的一个窗口或一个菜单。
总的来说,单元就是一个最小的被测功能模块。(来自百度百科)
我们做单元测试的目的,就是要验证代码里最小的功能模块,确保它的运行结果是正确的,经得起考验的。就好像一辆汽车,它的每个小零件都需要不断打磨和测试,才能放心的组装在一起,整车质量才能有所保障。
1.2 单元测试CheckList
- 符合单元测试命名规范
- 符合单元测试结果断言校验
- 排除敏感用户数据进行测试
- 需检查存在的越权风险(数据、端口)
- 覆盖完整的业务场景(正例、反例)
- 需可重复执行,结果一致
- 执行时间短
- 存在测试价值和方便定位问题
- 需通过单元测试
- 需通过要求的代码覆盖率
- 需不影响项目构建和运行
1.3 测试模型
1.3.1 冰淇淋模型
传统的冰淇淋模型也是目前很多团队的主要测试手段。这里面包含了大量的手工测试,端到端的自动化测试,以及极少量的单元测试。这种测试方法造成的后果是,随着业务逻辑越来越复杂,手工回归测试的时间越来越长,可以会被漏测的风险越来越大,质量很难把控。自动化测试一旦失败,调用链路中到底是哪里出的问题,需要花费更大的精力去排查。单元测试又少的可怜,基本起不到作用。
1.3.2 金字塔模型
Mike Cohn 在他的著作《Succeeding with Agile》一书中提出了“测试金字塔”的概念。金字塔模型告诉搭建测试是需要分层的,同时也让大家能够直接的感受到,每一层都需要投入多少测试精力,以及每一层测试的效率和所消耗的成本。
越是底层的测试,关联性越小,我们只需要关注单个方法的逻辑,简单的单元测试就很容易做到100%的代码覆盖,这也是最快的最节省资源成本的做法。越往上层,多个单元的集成测试涉及到的业务逻辑越复杂,任何一个分支的测试效率会更低,遇到问题更难以排查,所消耗的资源成本,时间成本更大。
我们的底层越牢,越可靠,上层越不容易出现问题。因此传统的冰淇淋模型要向金字塔模型转化,我们可以形象的称之为“冰淇淋融化了”(让我想起了某酸奶0.0)。也就是说,最顶部的手工回归测试,需要向下融化,优先考虑做全面的单元测试,单元测试覆盖不了的,再进行分层,做服务端的集成测试,集成测试无法覆盖,最后放在UI层。
测试方法 | 类型 | 描述 | 基准 |
单元测试 | 白盒子测试 | 主要测试单元内部的数据结构、逻辑关系、异常处理 | 逻辑覆盖率 |
集成测试 | 灰盒子测试 | 主要测试模块间的接口数据传递关系,以及组合功能 | 接口测试 |
系统测试 | 黑盒子测试 | 主要测试整个系统是否符合业务需求 | 需求覆盖率 |
白盒子测试: 又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,即清楚盒子内部的东西以及里面是如何运作的。“白盒”法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。“白盒”法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。贯穿程序的独立路径数是天文数字。
灰盒测试:是介于白盒测试与黑盒测试之间的一种测试,灰盒测试多用于集成测试阶段,不仅关注输出、输入的正确性,同时也关注程序内部的情况。灰盒测试不像白盒那样详细、完整,但又比黑盒测试更关注程序的内部逻辑,常常是通过一些表征性的现象、事件、标志来判断内部的运行状态。
黑盒测试:它是通过测试来检测每个功能是否都能正常使用。在测试中,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行测试。
——来源百度百科
1.4 为什么要做单元测试
有效的单元测试是敏捷开发的基石,是软件测试的基础。
单元测试是每个软件项目不可以或缺的环节,能帮助项目验证代码的主要逻辑,及时发现项目代码变更影响,从而减少SIT、UAT测试上的bug。单元测试覆盖率越少,系统测试阶段暴露bug会越多,解决成本也会越高,代码变更影藏风险越高。
图
1.5单元测试编码规则
单元测试应考虑的各种场景下测试条件,应该遵循BCDE原则,以保证模块交付质量。
- B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
- C:Correct,正确的输入,并得到预期结果。
- D:Design,与需求设计文档相结合,来编写单元测试。
- E:Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期流程
1.6 单元测试用例的设计要素
从设计覆盖角度,条件组合>最小线性无关路径>条件>分支>语句。
将内部逻辑与外部请求分开测试
对服务边界(interface)的输入和输出进行严格验证
一定具备断言的能力
适时使用 setup 和 teardown
原子性,所有的测试只有两种结果:成功和失败(为什么我每次还多一个,代码报错...)
避免随机结果
避免测试中的逻辑,即不包含if、switch、for、while等
不要保护起来,try……catch……
每个用例只测试一个关注点
断言(assertion):是一种在程序中的一阶逻辑(如:一个结果为真或假的逻辑判断式),目的为了表示与验证软件开发者预期的结果——当程序执行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止执行,并给出错误信息。
——来源百度百科
2、测试框架介绍
测试框架 | 类型 | 特点 | 备注 |
Junit | 单侧框架+断言 | 主流单元测试框架 | 项目组使用,更轻量,满足大部分需求 |
Spring Test | 容器测试 | 支持进行启动Spring容器相关的接口和Service测试,容器只启动一次避免重复加载,支持动态加载Bean,支持数据库测试回滚。 | 非容器相关配置,filter、controller层的测试,则不推荐 |
Mockito | mock | 提供数据mock和依赖管理,不需要启动容器,即可方便做方法的测试。 | 推荐 |
AssertJ | 断言 | 支持流式处理断言框架,断言丰富 | 项目组使用 |
现阶段理解不深,接触的不多,先整理这些,后期如果有更深的认知,再补充!
3、单元测试开发规范
3.1 注意事项
启动前排除非业务代码的类,如bean、controller、unit、configuration等。
不推荐使用 spring test 来单元测试,如果有必要用则应该保证单元测试只有一次容器启动,否则会影响项目构建商户时间。
不建议在构造函数中进行初始化,或者在单元测试方法做一些统一初始化,可以使用 @Before @BeforeClass 进行替代。
DAO层及远程调用尽量mock掉。
不建议使用catch进行判断,断言方式有时候并不能达到预期,异常处理案例请参考Demo
私有方法单测覆盖一般情况可通过反射(powerMockito Whitebox,incokeMethod)进行测试,一般情况下不建议去mock私有方法去验证业务方法,不容易保证业务逻辑正确性。
3.2 命名规范
一般情况下我们开发的业务系统会有不少的业务层的代码,其中就一个service类的业务方法都有很多个,每个方法都可能返回数种结果。如果我们想要完整的开发单元测试,可能一个service类的单元测试方法会有数十个之多,如果不进行命名规范的管理,会造成命名的混乱,造成的单元测试阅读质量下降,从而影响单元测试维护。
3.3 输入数据规范
避免使用敏感用户数据来进行测试,避免出现数据泄漏。
考虑边界数据应该准确有效。
一个方法的测试数据应该有正例数据和反例数据。
3.4 结果校验规范
有实际返回,必须要有断言方法来验证结果。
无返回则可以不考虑使用验证结果,但可以验证内部方法执行次数和抛出异常。
不允许通过打印日志来确认一些结果(个人不是很理解)。
涉及特殊格式json/xml等可以断言框架结果验证方式,不可以只做简单结果判断验证
涉及文件流处理的,建议使用数据类型和大小的结果验证。
单元测试案例通过
单元测试结果代码覆盖率达到要求(新增行100%)
测试类命名规范
比如 UserService 对应测试类 /src/test/java/ 所在源 class 同一层级包下;
比如 com.xxx.UserService 对应的测试类是 com.xxx.UserServiceTest
测试方法命名规范
推荐使用以下方法命名,方法名应该符合 方法名+条件+结果 对单元测试方法进行命名,需要注意单测函数式 public、无入参和无返回的函数命名。
<SourceMethodName>对应的源方法名,后面加Test标识是单元测试方法。
<Condition>名字应该准备描述正例和反例的入参或其他条件。
建议参考以下标识符,如:
- 正例条件:RequesetParamisValid
- 反例条件:NameisBlank(名字为空)、TypeEqualPublic(类型是公共类型)、CardNoisinvalid(卡号无效)、AgeRatherThan(年龄大于30岁)等
而<Behavior>是业务方法期望返回的结果,建议使用以下标识,如:
ToSuccess(成功)、Tofailed(失败)、ThrowException/ThrowXxException(抛出异常)等。
综上单元测试方法命名样例:
com.xxx.UserServiceTest.queryUserById
正例:
queryUserById_Test_When_RequestParamIsValid_Expect_ToSuccess
反例:
queryUserById_Test_When_NameIsBlank_Expect_ToFailed
queryUserById_Test_When_NotFoundUser_Expect_ToFailed文章来源:https://www.toymoban.com/news/detail-610964.html
queryUserById_Test_When_IdIsNull_Expect_ToFailed文章来源地址https://www.toymoban.com/news/detail-610964.html
到了这里,关于单元自测Java 单元测试规范的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!