京公网安备 11010802034615号
经营许可证编号:京B2-20210330
永远不要忘记数据库测试 数据库测试的重要性和测试要点说明
译者导读:本文分为三部分,第一部分是第1节,即说明“对数据库测试的根本误解”;第二部分从第2节至倒数第4节,详述“数据库测试测什么”的问题;第三部分是最后3节,引出“数据库测试怎么测”的问题,提出自动部署、自动化测试、持续集成的思路及工具。另,副标题是俺自行添上去的,以明示本文意图。
有许多关于测试驱动开发(Test-Driven Development,缩写为TDD)的书籍。那些书通常关注的是将测试应用于工作单元(units of work)。对于工作单元的理解有许多种不同的方式,通常它表示一个类(class)。正如那些书中所言:编写许多测试,以使那些测试都能通过的方式创建代码。应模拟所有的外部资源,以便你可以只测试这个单元。
这很酷,但不幸的是所有的测试在此刻停止了。因为通常会有些没被测到的查询(手写的或者是由某些ORM工具生成的)。有些程序员使用集成测试来测试那些查询——连接到一个真实的数据库并执行真实的查询来进行测试。这种做法通常意味着在测试快乐路径(happy path)——我已经有了ORM工具,所以它会搞定每件事,我无须费心。
数据库通常是一家公司最有价值的资产。应用程序可以一遍一遍重写。旧的应用程序扔出去,新的应用程序装进来。但是更换应用程序时没人会丢弃满载数据的数据库。而是将数据库小心翼翼地迁移过去。位于多个系统中的许多不同的应用程序会在同一时刻使用同一数据库。这就是为什么拥有充满约束的良好数据库模型是如此重要、以及为什么应谨慎对待数据库的原因。你真的不想破坏数据一致性(consistency),因为这会使你的公司付出高昂的代价。
本文是关于经常被遗忘的数据库测试的。使用真实数据进行集成测试。实际上,它与你所使用的数据库引擎的类型无关紧要。你可以使用PostgreSQL、MySQL、Oracle,或者甚至使用那些有趣的noSQL数据库,例如MongoDB。以下规则可适用于各种数据库和各类应用程序。也许不是全部,例如noSQL数据库就无法强制实施数据完整性(integrity)。
你的应用程序通常是由许多不同的部件组成的。其中有一些<将任何你喜欢的语言放在这里>代码,一些配置文件,一些SQL查询,一些外部系统。测试一个应用程序意味着分别测试每个部件(因为只有这样才更容易找出bug)、以及测试所有部件是如何协作的。数据库就是这些部件的其中之一,而且你应该彻底测试它。
这是首要的、最可怕的错误。根本不测试数据库。你编写了一些使用数据库的代码。你甚至使用一些模拟数据库连接为这些类创建了单元测试。
集成测试怎么样?集成测试应在生产环境下对应用程序进行测试。集成测试背后的唯一想法是,确保应用程序部署到生产环境后可以正常工作。如果你不在生产数据库上测试应用程序,那么你实际上不并不知道应用程序能否工作。你的模拟连接让你可以发送尚未检查以及没有检查的任何查询。模拟连接只返回你所需的数据。
不创建集成测试意味着你实际上没有测试你的应用程序。
我所观察过的大多数团队拥有某种形式的集成测试。通常进行快乐路径测试:有某个ORM工具,我们持久化对象,ORM工具会完成那些工作,真是太酷了,我无须费心。
我从未见过一支对数据库schema(模式/架构)进行测试的团队。想象一下,由于某些针对产品的查询很慢,因此你必须在该数据库中创建某个索引。当下次在新的客户环境中部署此应用程序时,你希望拥有该索引并确认该索引真的就在那里。为什么不编写一个简单的测试来检查该索引的存在呢?
除了索引,还有许多要测试的内容:
当你开发某个应用程序时,你可以从种类繁多的数据库中进行选择。通常你会从中选择那个最好的、那个被团队所熟知的、或者是由管理层所选定的(有时使用一些奇怪的理由)。有时同一应用程序的多个部署会在同一时间使用不同的数据库引擎。有时应用程序会为了能使用不同的数据库引擎进行准备,因此购买此应用程序的客户就可以选择他想要的数据库。
数据库引擎的选择真的与进行产品测试无关。
由于程序员的懒惰,因此他们希望他们的测试可以运行得飞快。他们不想为测试结果等太久。这也就是为什么许多团队使用某些更快的内存数据库(例如HSQLDB)的原因。由于那些内存数据库仅存储在RAM(Random Access Memory,随机存取存储器)内存中,而且在操作时不接触任何硬盘驱动器,因此它们的运行速度要快得多。
还有一条常常被人遗忘的规则:
测试应该使用与生产环境相同的数据库引擎。
许多程序员会使用某个其他引擎。常见的解释很简单:“我们的数据库太慢了,我们应该使用某个内存数据库引擎。”。这并不是个好主意。这样你测试的是该其他引擎,而非你的生产环境中的那个,所以实际上你并没对你的应用程序进行测试。
我曾经遇到过这个问题。我们必须在成功连接数据库后通过设置session变量来优化查询。那个应用程序在生产环境中只使用Oracle数据库。当设置此变量以后,测试失败了。而且是所有的测试都失败了。原来是我不能在HSQLDB内存数据库中设置此变量,因为它根本不存在。因此,我必须编写一段糟糕的代码:在连接后,检查数据库引擎,并由此决定是否设置此变量。
即使你没有任何与混合引擎有关的问题,请记住,当你测试其他非生产环境的数据库引擎时,你恰恰根本没对你的应用程序进行测试。
测试有一个通用的、明确定义的流程。 它非常简单:
若尝试背道而驰,则你会被它所伤。
你察觉在测试之后是没有整理(tidying)的么?
这点非常重要:必须在测试前准备环境,而非测试之后。你无法确保测试将能够清理一切。应用程序可能因为某个错误、网络连接失败而退出,或者应用程序可能崩溃(例如,由于内存不足异常)。该测试如何终止并不重要,真正重要的是该测试运行在为每个测试所准备的相同环境中。
我曾犯过这个错误:有大量的集成测试,它们会在每次测试后清理所有更改。许多程序员正使用调试器来运行这些测试,并且当发现bug后会在中间停止测试。任何在该测试之后运行的测试会得到不可预知的且随机的结果。因为它正运行在已被前一测试所改变的环境中,而且没有为其清理整个环境。
在前面的部分中我提到许多有关准备数据库的内容。我还想补充一点。准备数据库是不够的。当你通过清理某些表、加载配件等等准备好数据库时……还剩下一件事情要做。
在准备完毕后,要检查数据库状态。
你真正需要确保的是你已将一切准备妥当。当出现由于bug所导致的某些数据留下来且未能清理时,这些工作就可以节省你的时间。
这应该是测试前数据库准备的一部分。
每个应用程序都需要某种形式的安装过程。而对于你部署数据库而言,永远是第一次。
程序员往往会通过手工执行某些临时的数据定义语言(DDL,data definition language)查询来改变数据库。他们稍后并没有把那些语句写下来,或是忘记了所做的改动。他们没有更新安装脚本。大多数团队不使用有版本控制的脚本(例如,Ruby on Rails中的Migrations、或者是Java世界中的Liquibase)。
对测试而言最好的方式是,在运行测试套件前重新创建数据库。你不必在每个测试开始前都那么做。只在运行所有测试前运行一次就行了。
是的,宁可事先谨慎有余,不要事后追悔莫及。
外键是提供数据库一致性的基本途径之一。在良好的关系数据库schema中,你应该拥有各种键。如果你没有的话,那么这可能表明你有一个真正的大问题。然而,这取决于数据模型,但是通常缺乏外键是种非常糟糕设计的味道。
测试外键很简单。只需在事先没有在引用表中添加适当的行的情况下,为某个表添加一些行。你应该得到一个错误。然后,你应该从引用表中删除行,你可能得到错误,或没有错误(这取决于该键的定义)。无论如何,你都应该检查一下预期行为。
在良好的数据库设计中,你应该定义一些合理的默认值。通常这些默认值可能是空(null)。即便这些空也应该进行测试。你不能假设,只有你的应用程序将改变此数据库中的数据。\ 两个问题:
在数据库中还有更多约束,不仅只有主键和外键约束。你可能拥有一些唯一的(unique)或不为空的列。你可能约束某列只有很少的值集。你可能想确保价格永远不会低于0。
良好的数据库schema应拥有许多约束。你也应该测试它们。如果你希望你的价格列只能拥有正值,当你尝试向其中插入-1美元时会发生些什么?为什么不测试一下呢?
你不能假设只有你的经过良好测试的应用程序将使用那些数据,而且这些检查是为你防御这些bug的最后一道防线。为什么不测试它是否正常工作?
通常,数据库测试会更改数据库。你可能同时运行多个测试,但是你必须确保那些测试彼此之间没有影响。你必须确保,如果某个测试将一些内容写入数据库,而另一测试将不会读到。
通常,很容易搞得一塌糊涂,因此我小小的忠告是:避免在同一时间运行多个测试。这也意味着,你不应该在多台机器运行相同的测试套件。
当你有许多想运行测试的开发者时,他们每个人应该拥有可用于编写测试的单独的数据库。如果你拥有某种形式的只读数据库,没关系,多台机器可以在同一时间使用这个数据库。但是如果你允许所有程序员使用同一数据库进行测试的情形出现,那么你可能真的会得到不可预知的测试结果。
当程序员在某个测试中发现一个错误时会怎么做?那么,优秀的程序员会尽量修正错误。如果该测试失败仅仅是因为另一程序员在同一个数据库上运行他的测试所导致的话,那么修正此类错误只是在浪费程序员的时间。
优秀的程序员是懒惰的。如果你命令优秀的程序员每次都重复同样的任务,他们会越来越沮丧。优秀的程序员会自动化可重复的事情。
在每个项目中,你必须在测试环境中部署某些东西。做这些会花去多少时间?你真的想为了重新部署应用程序和加载数据库一直浪费你的程序员时间么?
这就是为什么每个项目都应该有个大红按钮的原因。某位程序员可以按下此按钮,然后冲杯咖啡,回去工作,并且几分钟后得知的大红色按钮完成的工作,一切准备就绪。
大红按钮真的会为你节省很多时间。你会说自动化所有工作实在太缓慢。然而,事实并非如此。恰恰相反,就像说测试驱动开发(TDD,Test-Driven Development)很慢一样。在最初的时候比较慢,但随着项目变得更加复杂,由于存在测试或按钮,会为你节省更多的时间。各种各样的大红按钮——你可以用它们部署应用程序、运行测试,以及类似的后方支援。
有时会使用Jenkins(又名Hudson)来做这些。是的,对于此类大红按钮而言这是一款伟大的软件。唯一的事情是,每位程序员应该有其自己的一组工作以便在其自己的环境中部署所有的内容,在其自己的环境中他(或她,当然)可以自由发挥,而不会影响他人,同样也不会受到他人的影响。
有许多数据库测试工具。为了测试整个schema,你可以编写简单的集成测试。对于PostgreSQL有pgTAP,使用TAP插件它可以与Jenkins集成到一起,因此Jenkins可以拥有一项用于测试数据库(包括生产数据库)是否正常的工作。
CDA学员免费下载查看报告全文:2026全球数智化人才指数报告【CDA数据科学研究院】.pdf
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在大数据技术飞速迭代、数字营销竞争日趋激烈的今天,“精准触达、高效转化、成本可控”已成为企业营销的核心诉求。传统广告投放 ...
2026-04-24在游戏行业竞争白热化的当下,用户流失已成为制约游戏生命周期、影响营收增长的核心痛点。据行业报告显示,2024年移动游戏平均次 ...
2026-04-24 很多业务负责人开会常说“我们要数据驱动”,最后却变成“看哪张报表数据多就用哪个”,往往因为缺乏一套结构性的方法去搭建 ...
2026-04-24在Power BI数据可视化分析中,切片器是连接用户与数据的核心交互工具,其核心价值在于帮助使用者快速筛选目标数据、聚焦分析重点 ...
2026-04-23以数为据,以析促优——数据分析结果指导临床技术改进的实践路径 临床技术是医疗服务的核心载体,其水平直接决定患者诊疗效果、 ...
2026-04-23很多数据分析师每天盯着GMV、DAU、转化率,但当被问到“哪些指标是所有企业都需要的”“哪些指标是因行业而异的”“北极星指标和 ...
2026-04-23近日,由 CDA 数据科学研究院重磅发布的《2026 全球数智化人才指数报告》,被中国教育科学研究院官方账号正式收录, ...
2026-04-22在数字化时代,客户每一次点击、浏览、下单、咨询等行为,都在传递其潜在需求与决策倾向——这些按时间顺序串联的行为轨迹,构成 ...
2026-04-22数据是数据分析、建模与业务决策的核心基石,而“数据清洗”作为数据预处理的核心环节,是打通数据从“原始杂乱”到“干净可用” ...
2026-04-22 很多数据分析师每天盯着GMV、转化率、DAU等数字看,但当被问到“什么是指标”“指标和维度有什么区别”“如何搭建一套完整的 ...
2026-04-22在数据分析与业务决策中,数据并非静止不变的数值,而是始终处于动态波动之中——股市收盘价的每日涨跌、企业月度销售额的起伏、 ...
2026-04-21在数据分析领域,当研究涉及多个自变量与多个因变量之间的复杂关联时,多变量一般线性分析(Multivariate General Linear Analys ...
2026-04-21很多数据分析师精通描述性统计,能熟练计算均值、中位数、标准差,但当被问到“用500个样本如何推断10万用户的真实满意度”“这 ...
2026-04-21在数据处理与分析的全流程中,日期数据是贯穿业务场景的核心维度之一——无论是业务报表统计、用户行为追踪,还是风控规则落地、 ...
2026-04-20在机器学习建模全流程中,特征工程是连接原始数据与模型效果的关键环节,而特征重要性分析则是特征工程的“灵魂”——它不仅能帮 ...
2026-04-20很多数据分析师沉迷于复杂的机器学习算法,却忽略了数据分析最基础也最核心的能力——描述性统计。事实上,80%的商业分析问题, ...
2026-04-20在数字化时代,数据已成为企业决策的核心驱动力,数据分析与数据挖掘作为解锁数据价值的关键手段,广泛应用于互联网、金融、医疗 ...
2026-04-17在数据处理、后端开发、报表生成与自动化脚本中,将 SQL 查询结果转换为字符串是一项高频且实用的操作。无论是拼接多行数据为逗 ...
2026-04-17面对一份上万行的销售明细表,要快速回答“哪个地区卖得最好”“哪款产品增长最快”“不同客户类型的购买力如何”——这些看似复 ...
2026-04-17数据分析师一天的工作,80% 的时间围绕表格结构数据展开。从一张销售明细表到一份完整的分析报告,表格结构数据贯穿始终。但你真 ...
2026-04-16