筑牢 YMatrix 质量防线:从测试出发(思路篇)

2025-02-24 · 王昊
#技术探讨

前言

随着数据库产品的复杂性和迭代速度的增加,质量问题逐渐成为开发过程中的一大挑战。测试作为确保产品质量的关键环节,不仅能够有效预防潜在缺陷,还能提升开发效率和客户满意度。

本文将从测试的重要性出发,探讨如何通过系统化的测试思路和技巧,筑牢数据库质量防线,通过分享实际案例和测试策略,希望能够为开发者和测试工程师提供有价值的参考,助力在工作中取得更好的成果。

作者 | YMatrix 研发经理 王昊

测试为什么重要?

于公司:是极具价值的商业成功之因

数据库作为一项复杂技术产品,在持续的开发与迭代过程中,产品质量常常出现诸多瑕疵。这些瑕疵在产品进入商业市场后,对客户的满意度、前端实施的顺利性以及后续开发的效率都产生了显著的不利影响。因此,质量问题成为了公司长期面临的挑战,也是商业成功的关键因素。

于个人:是能力的基础,是晋升的关键

公司商业活动的不顺利会直接影响到公司的收入,进而波及到每个人的收入、绩效和成长机会。因此,在开发阶段,每个参与者都需要不断提升质量意识和能力,以对产品质量高度负责的态度,积极投入到质量保证工作中,这是数据库开发人员的基本职责。

在软件开发中,测试是一个不可或缺的环节,其重要性与功能代码开发本身不相上下。在评估工程师的能力时,对待测试工作的态度、实际投入程度、技能技巧以及实施效果,都是极为重要的考量方面。

缺乏测试意识或不会编写测试代码的人相当于毕业生水平;仅能编写单元测试的可视为初级工程师;能够设计并实施完整的端到端测试,实现功能交叉覆盖的属于中级水平;而能够深入理解用户的环境、场景和业务意图,集成多个组件和模块,在接近真实的软硬件环境中实施质量保证的,则达到了高级水平。

思路、技巧和案例

测试实际上是无法穷尽的,所以好的测试应当通过更有条理的思路,覆盖尽可能多的测试信息。我整理了平时常用的几点测试技巧。

  1. 充分交叉组合 充分交叉组合能够增加测试数据量:通过设计更多数据、更多组合、刁钻数据等来增加测试数据量。

以我之前操作的一项测试项目为例,交叉组合前

按照如下思路进行充分交叉组合:

  • 是否分区表

  • 子查询

  • 反面 Case

  • 级联的流

  • 各种数据类型

  • 近 40 个新的 AGG 类型

交叉组合后得到如下结果:

因为交叉组合的思路设计,使得测试的数据量指数级增长,测试结果的准确性更有保障。同学们交叉组合的思路应当不刻意追求行数,而是注重角度全面。

  1. 充足的断言

执行被测函数后要断言结果,包括函数执行结果、成功或失败、对其他组件的影响等,避免逻辑瑕疵,使测试更完整。如下例,断言验证了 mxstart 工具正常工作:

增加了额外断言,确认数据库确实可以查询:

类似的情况,比如 regression 测试里,注意充分检查了每个字段的内容是否符合预期。实际工作中,经常有同学只草草做了个 count 就认为通过,这点要注意避免。如果结果集很大,不想让 out 文件太长,可以用 EXCEPT 来对比实际 vs 预期结果。

  1. 验证测试的有效性

测试是为了程序的“考官”,那么测试文件的“考官”又是谁?

举一个大家常见的bugfix的情况,常规做法是:

【存在bug的版本】 -> 【集中精神分析修复问题】-> 【补个测试case】

但这里非常容易出现疏漏,同学们可以进行如下思考:

这个测试case一定能覆盖所需修复的问题吗?

有没有可能一开始的bug版本也能跑过同样的额case呢?

因此,提供给大家更为精确的流程:

【存在bug的版本】 -> 【补个测试case,过不了】 -> 【修复问题】 -> 【case通过,验证了修复】

修复 bug 时先将其写入测试用例并使其失败,修复后再运行通过,证明修复有效和测试用例有效;review PR 时可通过 revert 代码跑测试来证明修复针对问题。

  1. 将测试循环利用

开发出的测试要运行,还可在本地循环跑以暴露更多问题,尤其对于异步和随机情况。

  • 每次 PR 前要测 - 本地开发
  • 每次开出 PR 后要测 - CI
  • 每次推送到 master 要测 - CI
  • 有些测试可以循环跑 - 本地
  • ...
重现方法:
编辑一个 loop.sh

#!/bin/bash

$@
while [ $? -eq 0 ]; do
    $@
done

一个课后练习

架构设计的测试

请问下面的函数应该如何做单元测试?

func 业务处理1() {
   // 连接数据库,查询表
   xxxxxxxx

   if 出错 {
       // 删除本地文件,退出
   }

   // ssh 连接远程地址,执行命令

   // 发起 rpc 调用,调用其他服务的 api
}

下篇文章将会解答练习题,并通过多个具体的测试场景展开测试工作更多的实操技巧。