研发效能 云原生时代的单元测试

星海后台测试平台 · 2020年07月13日 · 2109 次阅读

1. google 测试分层理论

谷歌三篇论文 Google File System、Google Bigtable、Google MapReduce 引领了大数据整个领域。
Google 软件测试之道 引领了软件测试行业。
测试金字塔,测试分层是这本书两个基本的理论(图片截取自书中):

书中大部分总结都来自谷歌在 2010 年前后谷歌的实践,参考https://testing.googleblog.com/
现在是 2020-07-12,云原生的基础设施和编排能力已经成为企业的标配,结合书中的理论,我们需要重新思考具体业务实践。

2. 单元测试依赖数据库

单元测试要尽量的减少依赖,其中包括对数据库的依赖。表 2.2 中小型测试中推荐使用 Mock 的方式来进行数据库相关的测试。
为什么要减少对外界的依赖?
因为依赖会带来:
依赖构建成本高,不确定性,不稳定性,耗时高等因素,这些因素对小型测试是有害的。

在微服务和代码结构分层的前提下(存储服务 || DAO 层),存储层代码如何进行单元测试呢?
他们通常采用内存数据库作为单元测试数据库,如:H2

步骤:

  • 配置针对单元测试的数据源 mybatis_config_h2_test.xml
  <!-- h2测试库配置 -->
  <environment id="pre">
    <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
      <property name="driver" value="org.h2.Driver"/>
      <property name="url" value="jdbc:h2:mem:test;INIT=runscript from nit.sql'\;"/>
      <property name="username" value=""/>
      <property name="password" value=""/>
      <property name="poolPingEnabled" value="true"/>
      <property name="poolPingQuery" value="SELECT 1+1"/>
      <property name="poolPingConnectionsNotUsedFor" value="0"/>
      <property name="poolMaximumActiveConnections" value="150"/>
      <property name="poolMaximumIdleConnections" value="150"/>
      <property name="poolMaximumCheckoutTime" value="20000"/>
      <property name="poolTimeToWait" value="20000"/>
    </dataSource>
  </environment>
</environments>
  • 单元测试过程中 load 数据源
  • 进行单元测试
    使用内存数据库模拟实际数据库有以下几个问题:

  • 内存数据库无法完全模拟实际数据库的能力,MySQL 、Oracle...

  • 对于一不支持的情况需要进行适配

  • 内存数据库测试通过不能完全认为在实际数据库中没问题

  • 开发同学需要学习 h2 数据库的一些坑,如何规避
    灵魂的拷问:
    为什么用这么大精力构建 “假的” 内存数据库,直接安装 MySQL 不可以吗?

3. 云原生和 DevOps

这 10 年我们经历了什么?

  • 机器配置: 2010 年公司配置的开发机是 8G 内存,终端开发为了加快编译配置 16G 2020 年 32G 内存开发机是标配,另外还配置了研发域 DevCloud 机器 电脑里把 MySQL、Redis、MongoDB....都安装启动也没什么压力。
  • 技术的发展 云原生:基础设施不可变性,利用 docker、镜像能力可以快速构 MySQL,Redis 等依赖 DevOps:将团队的基础设施和流程固化

我们有条件快速、低成本、便捷的构建环境

我们的方案:
抛弃内存数据库,单元测试直接依赖 MySQL、Redis 等数据基础设施
以依赖 MySQL 数据库的单元测试为例:

  • 单元测试直接依赖本地 MySQL 数据库
  • 制作团队基础开发镜像,安装 MySQL 数据
  • 团队成员根据自身开发需求编写数据库脚本
  • DevOps 流程中依赖相同的基础镜像,在基础镜像之上增加编译相关层次

收益:

  • 团队不需要再为 H2 数据库的坑努力
  • 本地调试更加方便
  • 开发环境、编译环境、真实环境(测试、线上)依赖一致,测试更加有效

4. 思考

4.1 复杂度来源

程序要解决的是业务复杂度问题,微服务技术并没有降低业务复杂度,甚至因为微服务之间的依赖提高了复杂度。
真正的业务并不会像迭代 0 中代码编写的那样纯粹,按照文件夹区分单元测试、模块间测试、接口测试。复杂度使得我们在做金字塔底层测试时需要进行很多 Mock

过早进行集成测试测试的成本会很高

4.2 云原生体系下该如何做测试

  • 我们测试对象,后台服务开始云化,云化后该怎么测试?
  • 借助云原生的能力,构建测试基础设施,测试云化后会有什么样的变化?

本文不是挑战测试分层和测试金字塔理论,主要是通过在项目中的一些实践,引发一些思考,欢迎拍砖,一起讨论

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册