单元自测Java 单元测试规范

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

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层的测试则不推荐
Mockitomock提供数据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

         queryUserById_Test_When_IdIsNull_Expect_ToFailed

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java