数据库测试指南
什么是数据库测试?
数据库测试检查被测数据库的模式,表,触发器等。 它可能涉及使用负载/压力测试创建复杂查询并检查其响应性。 它检查数据的完整性和一致性。
数据库测试在软件测试中很重要,因为它确保接收到并存储到数据库中的数据值和信息有效或无效。 数据库测试有助于避免数据丢失,保存中止的交易数据和防止未经授权的信息访问。 数据库对于任何软件应用程序都很重要,因此测试人员必须具备良好的 SQL 知识才能进行数据库测试。
GUI和数据测试的区别
GUI | 数据测试 |
---|---|
图形用户界面测试或前端测试 | 属于后台测试 |
用户可见部分,如表单,演示文稿,图表,菜单和报告等。 | 通常对用户隐藏的可测试项目 |
关注文本框、下拉菜单等控件,页面跳转、图像和主观体验等。 | 关注架构, 数据库表, 列 , 键和索引, 存储过程, 触发器, 数据库服务器验证, 验证数据重复 |
了解业务需求以及开发工具的使用以及自动化框架和工具的使用。 | 具有数据库服务器和结构化查询语言概念的强大背景。 |
数据库测试的类型
结构测试、功能测试、非功能测试
结构测试
结构数据测试涉及验证数据存储库内的所有元素,这些元素主要用于存储数据,并且不允许最终用户直接操作。 在这些类型的测试中,数据库服务器的验证也是非常重要的考虑因素。 测试人员需掌握SQL查询。
模式(schema)测试
数据库模式是对数据在数据库中如何组织的正式定义。模式测试确保前端和后端之间的模式映射是一致。 因此,我们也可以将模式测试称为映射测试。
最重要检查点:
- 验证与数据库关联的各种模式格式。 很多时候,表的映射格式可能与应用程序的用户界面级中存在的映射格式不兼容。
- 验证在未映射的表/视图/列。
- 验证环境中的异构数据库是否与整个应用程序映射一致。
- 规范化的范式可分为第一范式、第二范式、第三范式、BCNF 范式、第四范式和第五范式。一般来说,逻辑数据库设计应满足第三范式的要求,这是因为满足第三范式的表结构容易维护,且基本满足实际应用的要求。
每当在应用程序的前端执行某个动作时,相应的CRUD(创建、检索、更新和删除)动作会在后端被调用。测试人员必须检查是否调用了正确的动作,以及调用的动作本身是否成功。
- 表的映射,列的映射,以及数据类型的映射。
- 查询数据映射。
- 在用户界面上的每个用户操作都调用了正确的CRUD操作。
- CRUD操作是成功的。
我们还要看一些用于验证数据库模式的有趣工具。
- 与Ant集成的DBUnit非常适合映射测试。
- 通过编写简单查询或代码来检查和查询数据库的模式。
为了测试它:
- 确定数据库运行所基于的要求。样品要求:
- 在创建任何其他字段之前,应先创建主键。
- 外键应该是完全索引的,以便于检索和搜索。
- 字段名以某些字符开始或结束。
- 具有限制条件的字段,即某些值可以或不可以被插入。
- 根据相关性,使用以下方法之一:
- SQL查询DESC<表名>来验证模式。
- 用正则表达式来验证各个字段的名称和它们的值
- 像SchemaCrawler这样的工具
数据库表,列测试
让我们看一下数据库和列测试的各种检查。
- 后端中数据库字段和列的映射是否与前端中的映射兼容。
- 数据库字段和列的长度和命名约定。
- 是否存在任何未使用/未映射的数据库表/列。
- 验证兼容性
- 数据类型
- 字段长
后端数据库列的大小与应用程序前端中的列的数据库列的大小相同。
- 数据库字段是否允许用户按业务需求规范文档的要求提供所需的用户输入。
密钥和索引测试的检查点
- 检查是否需要:主键和外键及其约束(默认值,唯一值等)。
- 检查外键引用是否有效。
- 检查两个表中主键的数据类型和对应的外键是否相同。
- 检查是否已对所有键和索引遵循所需的命名约定。
- 检查所需字段和索引的大小和长度。
- 是否需要聚集索引和非聚集索引
存储过程测试
存储程序或多或少类似于用户定义的函数。这些程序可以通过调用程序/执行程序语句来调用,其输出通常是结果集。
这些过程存储在RDBMS中供应用。
- 白盒测试
使用桩来调用存储程序,然后根据预期值来验证结果。
- 黑盒测试: 从应用程序的前端(UI)执行操作,并检查存储过程的执行情况及其结果。
要为存储过程验证的最重要事项的列表。
- 开发团队是否确实采用了所需要的
- 编码标准惯例
- 异常和错误处理
用于所测试应用程序的所有模块的所有存储过程。
- 开发团队是否通过将所需的输入数据应用于被测应用程序来覆盖所有条件/循环。
- 每当从数据库中的所需表中提取数据时,开发团队是否正确应用了TRIM操作。
- 手动执行存储过程是否为最终用户提供所需结果
- 手动执行存储过程是否确保按正在测试的应用程序的要求更新表字段。
- 执行存储过程是否允许隐式调用所需的触发器。
- 验证是否存在任何未使用的存储过程。
- 验证可以在数据库级别完成的Null条件。
- 验证当被测试数据库为空时,所有存储过程和函数已成功执行。
- 根据被测应用程序的要求验证存储过程模块的整体集成。
一些用于测试存储过程的有趣工具是LINQ,SP Test tool等。
触发器测试
当某个事件发生在某个表上时,一段代码(触发器)自动执行。
例如,新学生加入了学校。该学生正在上2门课:数学和科学。该学生被添加到 "学生表 "中。 一旦该学生被添加到学生表中,触发器可以将他添加到相应的科目表中。
常用的测试方法是,首先独立执行嵌入在触发器中的SQL查询,并记录结果。之后再执行整个触发器比较结果。
- 白盒测试:
桩和驱动用于插入或更新或删除数据,这将导致触发器被调用。在与前端(UI)集成之前,只测试数据库。
- 黑盒测试:
- 从前端插入/删除/更新数据的方式来调用Trigger。
- 直接加载调用触发器的数据,看它是否按预期工作。
重点关注:
- 在触发器的编码阶段是否遵循了所需的编码约定。
- 检查为各个DML事务执行的触发器是否已满足所需条件。
- 触发器是否在执行后正确更新数据。
- 在所测试的应用程序字段中验证所需的更新/插入/删除触发器功能。
数据库服务器验证
- 检查业务要求指定的数据库服务器配置。
- 检查所需用户的授权。
- 检查数据库服务器是否能够满足业务需求规范所指定的最大允许用户事务数量的需求。
功能测试
确保最终用户执行的大多数事务和操作与需求规范一致。
以下是数据库验证需要遵守的基本条件。
- 字段是否必需,同时允许该字段上的NULL值。
- 字段的长度是否足够大?
- 是否所有类似字段在表中都具有相同的名称?
- 数据库中是否存在任何计算字段?
此特定过程是从最终用户角度验证字段映射。 在该特定场景中,测试器将在数据库级执行操作,然后将导航到相关用户界面项以观察并验证是否已经执行了适当的字段验证。
反之亦然条件,其中首先由测试者在用户界面处执行操作,然后从后端验证操作,也被认为是有效选项。
ACID属性
原子性、一致性、隔离性和持久性。DB执行的每个事务都必须遵守这四个属性。
- 原子性意味着一个事务要么失败要么通过。这意味着,即使交易部分失败了,也意味着整个交易都失败了。通常情况下,这被称为 "全有或全无 "规则。
- 一致性: 事务将总是导致数据库的有效状态。
- 隔离性: 如果有多个事务同时被执行,DB的结果/状态应该与它们逐一执行的情况相同。
- 持久性: 一旦事务完成并提交,任何外部因素,如断电或崩溃,都不能改变它。
以下检查很重要
- 数据是否在逻辑上组织良好
- 存储在表中的数据是否正确并且是否符合业务要求。
- 被测应用程序中是否存在任何不必要的数据。
- 数据是否已根据对从用户界面更新的数据的要求进行存储。
- 在将数据插入到测试数据库之前,是否对数据执行了TRIM操作。
- 交易是否已根据业务需求规范执行以及结果是否正确。
- 如果根据业务要求成功执行了事务,是否已正确提交数据。
- 如果最终用户未成功执行事务,则数据是否已成功回滚。
- 在事务尚未成功执行且多个异构数据库参与相关事务的情况下,数据是否已完全回滚。
- 是否已使用系统业务要求指定的所需设计过程执行所有事务。
数据完整性
对于任何CRUD操作,共享数据的更新和最新的值/状态应该出现在所有的表格和屏幕上。
- C Create : 创建 - 当用户 "保存 "任何新事务时,"创建 "操作被执行。
- R Retrieve : 检索 - 当用户 "搜索 "或 "查看 "任何已保存的事务时,会执行 "检索 "操作。
- U Update : 更新 - 当用户'编辑'或'修改'现有的记录,DB的'更新'操作被执行。
- D Delete : 删除 - 当用户从系统中'删除'任何记录时,将执行DB的'删除'操作。
重要检查点
- 检查所有的触发器是否已经到位,以更新参考表记录。
- 检查每个表的主要列中是否存在任何不正确/无效的数据。
- 尝试在表中插入错误的数据,观察是否有任何故障发生。
- 检查如果你试图在插入子表之前插入其父表会发生什么(尝试玩弄主键和外键)。
- 测试如果你删除一条仍然被其他表中的数据引用的记录,是否会发生故障。
- 检查复制服务器和数据库是否处于同步状态。
登录和用户安全
登录和用户安全凭证的验证需要考虑以下事项。
- 应用程序是否阻止用户在应用程序中进一步继续进行操作
- 用户名无效但密码有效
- 有效用户名但密码无效。
- 用户名无效,密码无效。
- 有效的用户名和有效的密码。
- 是否允许用户仅执行业务要求指定的特定操作。
- 数据是否受到未经授权的访问
- 是否使用不同的权限创建了不同的用户角色
- 是否所有用户都按照业务规范的要求对指定的数据库具有所需的访问级别。
- 检查密码,信用卡号等敏感数据是否已加密,而不是作为纯文本存储在数据库中。 确保所有帐户都应具有复杂且不易猜到的密码是很好的做法。
其他功能
比如主从同步、备份恢复、慢查询、调优、安全(ISO IEC 21827、SQL注入等)、EXPLAIN、锁表等
参考资料
- 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- https://www.softwaretestinghelp.com/database-testing-process/#2_Database_Schemas
- https://www.guru99.com/data-testing.html
非功能测试
数据库测试环境中的非功能测试可以根据业务需求分类为各种类别。 这些可以是负载测试, 压力测试 ,安全测试, 可用性测试[兼容性测试等。 在涉及非功能测试的角色时,负载测试以及可在性能测试的范围内进行分组的压力测试有两个特定目的。
风险量化 - 风险量化实际上有助于利益相关者确定在所需负载水平下的各种系统响应时间要求。 这是任何质量保证任务的初衷。 我们需要注意的是,负载测试不能直接降低风险,但通过风险识别和风险量化过程,可以提供纠正机会,并提供可以降低风险的补救措施。
最低系统设备要求 - 我们通过正式测试观察到的理解,最低系统配置将使系统满足利益相关者正式规定的性能期望。 这样可以最大限度地减少无关的硬件,软件和相关的拥有成本。 此特定要求可归类为整体业务优化要求。
负载测试
应清楚地理解和记录任何负载测试的目的。
以下类型的配置是负载测试的必要条件。
- 如果效率不高,最常用的用户事务可能会影响所有其他事务的性能。
- 最终测试套件中应包含至少一个非编辑用户事务,以便可以将此类事务的性能与其他更复杂的事务区分开来。
- 应该包括促进系统核心目标的更重要的交易,因为根据定义,这些交易的负载失败具有最大的影响。
- 应包括至少一个可编辑的事务,以便可以将此类事务的性能与其他事务区分开来。
- 观察大量虚拟用户对所有预期需求的最佳响应时间。
- 观察各种记录的有效时间。
参考: https://github.com/china-testing/python_cn_resouce#性能测试 强烈推荐locust。
参考:https://learn.microsoft.com/zh-cn/azure/data-factory/introduction
压力测试
压力测试强调测试中的应用程序具有大量工作,使得系统失效。这有助于识别系统的故障点。
参考: https://github.com/akopytov/sysbench
常见的问题
- 为了确定数据库事务的状态,可能涉及大量的开销。
解决方案:应整理整个流程规划和时间安排,以避免出现基于时间和成本的问题。
- 在清理旧测试数据后,必须设计新的测试数据。
解决方案:应该掌握测试数据生成的先前计划和方法。
- 需要SQL生成器来转换SQL验证器,以确保SQL查询易于处理所需的数据库测试用例
解决方案:维护SQL查询及其持续更新是整个测试过程的重要组成部分,应该是整个测试策略的一部分。
- 上述先决条件确保数据库测试程序的设置既昂贵又耗时。
解决方案:质量和整个项目进度持续时间之间应该有一个很好的平衡。
数据库测试相关的误区或误解
- 数据库测试需要大量的专业知识,这是一项非常繁琐的工作
现实:有效和高效的数据库测试为整个应用程序提供了长期的功能稳定性,因此有必要在其背后付出艰苦的努力。
- 数据库测试增加了额外的工作瓶颈
现实:相反,数据库测试通过发现隐藏的问题为主要工作增加了更多价值,从而积极地帮助改进整体应用。
- 数据库测试会降低整个开发过程的速度
现实:大量的数据库测试有助于整体提高数据库应用程序的质量。
- 数据库测试可能成本过高
现实:数据库测试的任何支出都是一项长期投资,可以实现应用程序的长期稳定性和稳健性。 因此,数据库测试的开支是必要的。
最佳实践
- 包括元数据和功能数据在内的所有数据都需要根据需求规范文档的映射进行验证。
- 需要验证由/与开发团队协商创建的测试数据的验证。
- 使用手动和自动化程序验证输出数据。
- 部署各种技术,例如原因效果绘图技术,等效分割技术和边界值分析技术,用于生成所需的测试数据条件。
- 还需要验证所需数据库表的引用完整性验证规则。
- 为数据库一致性验证选择默认表值是一个非常重要的概念。是否已在数据库中成功添加日志事件以用于所有必需的登录事件
- 预定的工作是否及时执行?
- 及时备份数据库。
如何测试数据库
- 准备好环境
- 运行测试
- 检查测试结果
- 根据预期结果进行验证
- 报告结果
通常情况下,使用SQL查询来开发测试。最常用的命令是 "选择"。
Select * from <tablename> where <condition>
除了Select之外,SQL还有3种重要的命令类型:
- DDL: 数据定义语言
- DML: 数据操作语言
- DCL:数据控制语言
让我们看看最常用的语句的语法。
数据定义语言 使用CREATE, ALTER, RENAME, DROP和TRUNCATE来处理表(和索引)。
数据操作语言 包括添加、更新和删除记录的语句。
数据控制语言: 处理给用户操作和访问数据的授权问题。Grant和Revoke是使用的两个语句。
Grant 语法:
Grant select/update
On <table name>
To <user id1, user id2…useridn>;
Revoke语法:
Revokeselect/update
on <table name>
from<user id1, user id2…useridn>;
实用技巧
- 自己写查询:
为了准确地测试数据库,测试人员应该有非常好的SQL和DML(数据操作语言)语句的知识。测试人员还应该知道AUT的内部数据库结构。
你可以结合GUI和各自表中的数据验证,以获得更好的覆盖率。如果你使用的是SQL服务器,那么你可以利用SQL查询分析器来编写查询,执行它们并检索结果。
当应用程序的复杂程度较低或中等时,这是测试数据库的最佳和强大的方法。
如果应用程序非常复杂,那么测试人员可能很难或不可能编写所有需要的SQL查询。对于复杂的查询,你可以从开发人员那里得到帮助。我一直推荐这种方法,因为它能给你测试的信心,也能提高你的SQL技能。
- 观察每个表中的数据:
你可以使用CRUD操作的结果进行数据验证。当你知道数据库集成时,这可以通过使用应用程序UI手动完成。但是,当不同的数据库表中有大量的数据时,这可能是一项繁琐的工作。
对于手动数据测试,数据库测试人员必须拥有良好的数据库表结构知识。
- 从开发人员那里获得查询
这是最简单的测试数据库的方法。从GUI中执行任何CRUD操作,并通过执行从开发人员那里获得的相应SQL查询来验证其影响。它既不需要很好的SQL知识,也不需要对应用程序的数据库结构有很好的了解。
但这种方法需要谨慎使用。如果开发人员给出的查询在语义上是错误的,或者不能正确地满足用户的要求,怎么办?这个过程将直接导致数据验证失败。
- 利用数据库自动化测试工具:
有几种工具可用于数据测试过程。你应该根据你的需要选择正确的工具,并对其进行最佳利用。