难度指数⭐️⭐️⭐️
#
前言单测覆盖率为应用质量指标化提供解决方案
一口吃不了一个胖子, 由于每个人的认识不一样,要想达到理想的状态,显然是不可能的。此章节主要从实践出发,一步一步带领我们完成一个有效的可复用的单元测试的编写。
#
一、目标#
1.1 质量保障单测是保证项目质量的手段,而不是目的。
通过 mvn test 在每次编译时候,对代码进行测试。以到达可持续集成的目的。这里的关键是在每次服务发布的时候,首先要运行测试用例。 只有这样,我们的单测用例才有价值,才能提前发现问题。
#
1.2 打扫屋子要解决前面的这个问题,就要求我们编写正确的测试用例。因为大多数项目目前的编译脚本都是,跳过单元测试的.
mvn -Dmaven.test.skip=true
, 之所以这样是因为大多数的单测都是为 debug
写的,一旦在编译的时候执行单测用例,
就会编译不通过。所以要想达到可持续集成的目的, 就要先把阻塞应用的单元测试用例给移除。
我们可以通过 @Ignore
来。 当然这不是说不允许你写debug的单测,而是要我们 遵守一个约定, 对那种debug的单测, 必须人工执行的单测
我们要通过 @Ignore
来标记, 避免我们执行单测时候失败。
#
1.3 发挥价值如果做到了 1.1 和 1.2 那么单测的价值有会真正体现出来了。但是这一切的一切的前提是我们要编写出正确的符合规范的单测用例。
#
二、真实案例分享首先这里我们使用到的技术,其实再前面的技术框架中都有列举了,所以这里就不详细说明了。这里就分享几个测试用例。
#
2.1 查询接口测试用例 难度:⭐️对于上图这种仅仅涉及到读的接口,是比较简单的。我们的验证点其实只有两个。
- web接口是否可以调用
- 接口查询条件是否有效
#
2.1.1 启动web服务器随机web端口,执行单测的时候启动一个web容器,用来模拟Web接口测试。
#
2.1.2 编写接口这里就验证了Web的请求,同时可以进度查询条件的校验。当然这里也可以加上返回值类型的校验
看到这里我们能亲身感受到,对于纯粹读的接口测试用例是比较容易编写的。一个项目只用维护一次就好了,开发同学也不会每次都去维护这个用例。 虽然这个用例简单,但是我们能在每次发布完成后自动化的去执行校验。能帮助我们提前发现问题。
#
2.2 读写测试用例 难度:⭐️⭐️像这种读写操作,且涉及到对外部数据调用的接口。我们要使用Mockito技术,对外部对象进行代理,并制定其中的行为。 如下图这个测试用例,看下如何编写测试用例。
首先分析下涉及到的接口。
- saveArrivalOrder 这个接口里面是包含了内部的业务逻辑和外部的数据调用,包含了下面两个外部的接口依赖。
- noticeTransportNodeNote 在保存到货通知单的时候,通知库存增加商品的在途库存数量的
- syncPurchaseOrder 在保存到货通知单的时候,是通知仓储做到货准备的
这个业务中我们只需要验证我们内部的逻辑即可,涉及到外部的调用只需要验证代码即可,并不真的需要仓库和库存系统做 真实的业务处理。所以我们就要针对这两个方法做数据mock我们使用到的技术就是Mockito做对象行为的mock。如下案例。
主要看注释,我们在调用接口的时候,先通过给外部接口最Mockito代理,然后指定动作的出入参数。这个案例,我们可以学会如何使用Mockito做外部接口的代理,整体难度也不是很大。
#
2.3 读写接口(复杂接口) 难度:⭐️⭐️⭐️⭐️ 针对项目中核心流程, 可能并不仅仅是一个接口,而是有依赖关系的多个接口。针对系统核心链路流程,我们是有必要维护些自动化流程的测试用例。然后对每个接口中的出入参数进行校验。当做到这一步的时候 其实我们在发布时候就会更加有底气。敢于去重构代码了。因为在项目迭代发布的过程中,我们会先跑一边单测。只要单测流程能通过,说明这个核心链路的流程问题就不会太大。
当然这里不是说一定没有问题, 而是有问题的几率变小了。如果说出现问题了,我们的自动化流程没有提前发现,那么说明这些场景,我们的单测流程没有覆盖到, 那么这个时候我们再补充我们的自动化流程。
注意这里的自动化流程,跟测试同学的自动化流程是有区别的。开发的自动化流程的测试目标是自身项目的代码,所以我们关于外部接口都是通过Mock来模拟的。而测试同学的 自动化流程,都是走真实的系统调用。
#
2.3.1 业务说明做到业务流程闭环当执行完上面的单测用例,就完成了采购核心链路的自动化流程,就会生成下面单据。
采购单
到货通知单
#
三、可复用能力通过2我们知道如何使用Mockito做对象行为的mock。还有一个点要思考的,这里单独拿出来说。就是测试用例的可复用行。什么叫可复用性呢? 就是说你这个单侧用例,在每次代码提交和编译时候执行,是否会有问题。如果是,且只能运行一次,那么这个就是不合格的。要做到可复用还要考虑两个地方。
#
3.1 接口参数动态生成为什么要动态生成呢? 因为比如我们指定了一个id去作为查询条件,那么当我们这个id被删除的时候,这个测试用例一定是失败的。 这种场景下我们就应该动态去查询一个。如下,我们查询采购单的全链路数据。那么首先我先查询所有的有效的采购单,然后拿出任意一条 作为测试用例的查询条件即可。
上面这个用例只用声明一个测试的bean对象即可。在我们的 src/test/java
包中。