单元测试

2021-02-07 10:50:06 浏览数 (1)

单元测试

单元测试的意义

单测好处:

  • 单元测试使工作完成的更轻松
  • 单元测试使你的设计更好
  • 大大减少花在调试上的时间
  • 能帮助你更好的理解代码

单元测试是什么?

指对软件中最小的可测试单元进行检查和验证,调用被测服务的类或方法,根据类或方法的参数,传入相应的数据,得到一个返回结果,最终断言返回的结果是否符合预期。如果相等,测试通过;如果不相等,测试失败。

所以,单元测试关注的是代码的实现与逻辑。单元测试是最基本的测试,也是测试中的最小单元,它的对象是函数对象,也可以包含输入输出,针对的是函数功能或者函数内部的代码逻辑,并不包含业务逻辑。

该类测试一般由研发人员完成,需要借助单元测试框架,如java的Junit、TestNG,mockito,python的unittest等

好的单元测试准则

1.运行快速

单元测试运行比较频繁,如果打包时候,单元测试运行很慢,会很影响效率。

  • 单个测试小于200ms
  • 单个测试套件小于10s
  • 整个测试小于10分钟

2.一致性

任何时候,同样的输入需要同样的结果。

3.原子性

所有的测试只有两种结果:通过和未通过。不能存在部分测试通过的情况

4.单一职责

一个测试只验证一个行为。

  • 一个方法,多个行为->多个测试
  • 一个行为,多个方法->一个测试(一个行为,多个方法一般指该方法调用private,protected,getters,setters)
  • 多个assert只有在测试一个行为时可以接受

5.独立无耦合

单元测试之间无相互调用

  • 单元测试执行顺序无关
  • 不同顺序无影响

单元测试之间不能共享状态

  • 比如不能共享变量,如果需要,放在setup里

6.隔离外部调用

  • 单元测试需要快速运行,且每次结果一致,所以需要隔离一切对外部的调用
  • 不使用具体的其它真实类(就是不要new)
  • 不读数据库
  • 不读网络
  • 不读外部文件
  • 适当时候可构建相同的内部文件mock
  • 不依赖本地时间
  • 不依赖环境变量

7.自描述

  • 单元测试是开发级文档
  • 单元测试是方法的描述

8.单元测试逻辑

  • 单元测试必须容易读和理解
  • 变量名,方法名,类名
  • 无条件语句,无swith(分解if到多个测试,所有的输入都是已知的,所有的结果都是一定的,可以mock)
  • 无循环语句
  • 无异常捕捉(测试预知的异常,用ExpectedException方法)

9.产品代码

  • 产品代码不能有测试逻辑
  • 测试代码和产品代码要分离
  • 使用依赖注入
  • 不要在产品代码里有任何只供测试的代码

根据上述指导思想和实际实现情况,一般在实现单元测试时有两种不同的实现方式

  • 单层隔离
  • 内部穿透

单层隔离

正常代码分层会分为controller、service、dao等,在单层隔离的思想中,是针对每一层的代码做各自的单元测试,不向下穿透。这样的写法主要是保证单层的业务逻辑固化且正确。

实践过程中,例如针对controller层编写的单元测试需要将对应controller类代码文件外部所有的调用全部mock,包括对应的内部/外部的service。其他层的代码也是如此。(可以参考样例代码中cdo-test-sample-core层的单测代码)

好处

  • 单元测试代码极其轻量,运行速度快
  • 真正符合了单元测试的原则,可以在断网的情况下进行运行,屏蔽服务注册和配置管理,各种中间件的影响
  • 单元测试质量更高

缺点

  • 单元测试的代码量比较大
  • 对于低复杂度的项目比较不友好(例如项目是单纯分层之后的CRUD)

内部穿透(集成测试)

穿透,自然就是从顶层一直调用到底层,为什么还要加上内部二字?就是除了项目内的方法可以穿透,项目外部依赖还是要mock掉。实践过程中,就是单元测试针对controller层编写,但会完整调用service、dao,最终对落地结果进行验证。(可以参考样例代码中cdo-test-sample-api层的单测代码)

好处

  • 代码量相对较小
  • 学习曲线低,穿透的单元测试更偏向黑盒,开发人员构造输入条件,然后从落地结果中验证预期结果

缺点

  • 整体较重,启动spring容器,中间件mock,整体单元测试运行预计需要分钟级别。所以基本是要在ci的时候来执行
代码语言:txt复制
   这两种方法,具体使用哪种合适,应该由项目成员根据项目实际情况自行选择,一般建议核心项目两种执行方法都可以同时执行,具体实施时可以先执行“单层隔离”积累单测用例,再做“内部穿透”。
代码语言:txt复制
   PS:我们一般使用@SpringBootTest注解进行集成测试,使用其它spring test(@WebMvcTest)注解进行特定组件的单元测试。

参考文档:

  • https://howtodoinjava.com/spring-boot2/testing/testing-support/

0 人点赞