筑牢数据库质量防线:从测试出发(实操篇)

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

前言

在上一篇文章“筑牢 YMatrix 质量防线:从测试出发(思路篇)”中,我们深入探讨了软件测试的核心理念,并分享了 4 个实用的测试技巧及其背后的原理。通过一个具体的练习分析,我们巩固了测试的思路与技巧的运用,帮助大家建立起对质量保障的初步认知。

本文将延续上篇的思路,聚焦于测试的实操环节,通过具体的测试场景和案例,您将不仅能够掌握更多的测试技巧,还能够在实际项目中灵活运用这些技巧,从而为 YMatrix 的质量防线添砖加瓦。让我们一起进入测试的实操世界,探索如何通过细致的测试工作,确保软件的稳定性和可靠性。

作者 | YMatrix 研发经理 王昊

架构设计的测试

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

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

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

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

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

根据初步分析,需要认识到这样的业务代码,是无法通过单测解决的。

解决方案:

改进程序结构设计,将业务流程和各种操作模块科学地分解,合理设计接口,就可以灵活地mock任何模块,测试业务流程的同时,不必受到测试运行环境的制约。

㊙️ 以上几点,理解和实施都不难,想要做好秘方就是“别犯懒”

异常注入:gp_inject_fault

内核开发的必备能力

  • 在特定的位置注入异常
  • 严格控制程序运行时序

探索性测试:无尽的沙盒游戏

对于我所工作的数据库行业来说,SQL语法 X 数据类型 X 具体的数据 X 执行顺序 ...... 组成了一个几乎无限大的空间,想要靠固定的测试 case 覆盖全部场景是无法做到的:

探索性测试:

探索性测试的思路:

  1. 引入随机性。

a. 随机的数据类型 b. 随机的列数 c. 随机的索引 d. 随机的数据内容 e. 随机的数据分布 f. 随机的语法结构 g. 随机的名字(数据库名、schema名、表名、字段名,各种合法字符) h. 随机的 segment 个数、布局 i. 随机的端口、磁盘路径 j. 随机的网络延迟,硬件故障 k. ...

  1. 紧抓随机背后的不变的事实,做出断言。

a. 开/关某些功能或优化,期待不影响查询结果。(向量化执行器、索引、GUC、存储引擎...) b. 期待数据行数、内容一致。(kafka、gate vs copy、mxshift...) c. 期待没有 core,日志里没有 panic、datarace,期待进程没有崩溃重启。 d. 期待数据库能正常查询(mxstart、recover、failover),期待没有残留的僵尸进程(mxstop) e. ...

  1. 评估探索性测试的覆盖效果,补齐短板。

  2. 利用随机 case,进行长期疲劳测试,挖掘更多潜在稳定性问题。

利用弹性、廉价且相对稳定可靠的 IT 资源

我们在这里分享一个,使用 AWS 进行标准压测操作的案例。教你如何用一根雪糕的价钱,随时随地调用一定规模的独占 IT 资源。

  1. AWS云主机(重点)

优点:

  • 有国内版本,访问延迟不是问题
  • 网络、性能表现非常稳定
  • 因为硬件式样固定且独占,有利于重复验证,对性能测试更友好
  • Spot instance 巨能省

缺点:

  • 可能被 AWS 自动回收(极少发生),不适用于长期固定使用。
  1. 使用 AWS 云主机需要了解的知识

机器系列

  • t 系列:可以选择非常小的实例,省钱,但是 cpu 有 credit 限制,常用作功能测试,不适合压测。

机器代际

网络/磁盘带宽

  • 在压测时,需要根据测试的场合、预期的压力规划使用的机器类型。

磁盘选择

  • 仔细参阅: https://aws.amazon.com/ebs/volume-types/

  • 重要原则:挂载多块性能一般的磁盘,优于挂载一块超级昂贵的大磁盘。

  • 多块盘的 through put 总和 = 主机的 EBS Bandwidth

  • 定价: https://www.amazonaws.cn/en/ebs/pricing/?nc1=h_ls

  • 最佳实践:多块丐版 gp3(125MB/s+3000IOPS)能够满足大多数场合。

  • 不要再用上一代产品 gp2 了。

  • ec2 机器关机了,EBS 磁盘依然会交钱。

回归:研发工程师应该如何做?

树立认知:测试在 YMatrix 是研发的必修课,而不是选修课。我们作为数据库产品的构建者,虽然不像我们的销售、售前、运维的同学们站在前线,但我们工作是他们向客户传达的最终价值。作为工程师,我们要关注我们的产品的质量,要让我们的构建的产品通过我们前线的同学,为客户真正创造价值,为了达到这个目标,测试一定是我们需要努力下功夫的必修课。

肩负责任:我们应当为社会提供什么样的产品?一个具备基本功能的半成品是远远不够的。作为企业,我们要提供能够为各行业提升生产力的好用工具,作为程序员,我们希望能够为世界留下推动技术进步的代码,我想这是成就一个值得被记住的企业,成为一个值得被记住的程序员所必须要承担的责任。如果研发人员若仅满足于完成功能代码,而不投入时间精力去验证程序的边界情况、与其他模块的组合效果,忽视不稳定的测试,是无法承担起这样的责任。 专心投入:在项目预估和规划时,通常会包含测试和验证所需时间,但在项目截止时,各类测试是否得到了与功能代码同等的关注和时间投入?在我们的实践中,交付一个质量可靠的项目,经常需要投入1/3的工作量,这个比例有时甚至接近50%。讲到这个比例,有些同学可能觉得有点夸张,实际工作中达不到这个比例。其实,测试就像大多数技能,是一定可以通过不断地学习和实践培养的,和我们既然能够掌握成熟的编程技能,软件工程方法,那么只要在日常工作中刻意学习,刻意练习,那么在测试上的技能也一定会得到提高,同时我们的投入也不会浪费,最终一定能够通过更佳的产品质量,让我们的产品通过前线的同学,顺利的为更多客户创造价值。 对于有志于在研发岗位上深耕的同学,以下是我能够分享的一些小建议:

  1. 将测试视为产品的一部分,提高构建测试的投入占比。
  2. 关注自己负责模块的现有测试,这些测试数据哪些类别,还有哪些类别是空白。
  3. 关注测试中的不稳定 case,every flaky test case is a bug,尝试探究和解决这些 case。
  4. 学习和理解你所从事的完整产品有哪些组件,功能。(对于不同组件开发同事来说,方向是不同的)
  5. 了解各个组件分别是如何编译的,整个产品的打包、安装、升级内部过程是怎样的。
  6. 了解各个模块分别是如何测试的,使用什么样的环境,属于哪些测试类别。
  7. 尝试了各种用户场景和案例,了解自己负责的功能以及其他各组件是如何在真实场景下集成运作的。
  8. 学习掌握一定的 CI/CD 技能,学习利用自动化工具和云服务构建测试工程,为自己的项目服务。