使用功能测试框架自动化测试数据仓库

这篇文章描述了Adobe Audience Manager进行数据仓库测试的挑战,并逐步介绍了我们为解决这些问题而开发的内部功能测试框架。

作为领先的数据管理平台,Adobe Audience Manager每天处理数十亿的实时和批处理事件。然后,这些数据被转化为综合报告,以帮助市场营销人员向正确的受众提供定制体验。

为了确保这些报告的准确性和可靠性,我们必须首先验证数据本身是正确的、完整的和正确的格式。这是通过勤奋的数据仓库测试实现的。然而,测试过程很大程度上是人工操作的,而且由于摄入的数据规模巨大,这是出了名的困难。因此,全面的测试实际上是不可能的,这会降低数据的完整性,并增加错误进入生产环境的风险。

为了应对这些挑战,我们开发了一个功能测试框架,该框架能够为Adobe Audience Manager报告堆栈自动化数据仓库测试。有了这个框架,我们可以支持大规模的详细测试,并以更低的成本轻松地验证每个数据点的准确性和质量。

测试adobeaudience Manager报告堆栈既复杂又不可靠

关于框架要测试的内容的上下文,我们首先将简要介绍Adobe Audience Manager报告堆栈。 (请参见下图。)

管道以从Adobe Audience Manager客户收到的事件日志开始。 这些日志可以存储在S3存储桶中,也可以写入到Snowflake中的表中。Snowflake是一种高效的基于云的数据仓库,我们替代Amazon Redshift进行了迁移,以简化Adobe Audience Manager的大规模报表。

这些雪花表充当我们的报表脚本的输入和输出表,报表脚本基本上是Python脚本,将业务逻辑应用到SQL形式的输入表的数据上。然后将结果返回到输出表,并使用Tableau呈现为报告。

在测试通过这个报告栈的不断增长的数据量时,我们面临以下挑战: 容易出错的手工测试:由于在任何给定时间都有数百万数据点流进Adobe Audience Manager,因此不可能彻底测试每一个数据点。因此,手工测试非常容易出错,而且很容易漏掉重大错误。

不可靠的质量控制:由于手工测试越来越多的数据是不可能的任务,我们几乎无法控制数据的质量和完整性。此外,我们无法访问高质量的测试数据,只能依赖于生产中不可预测的数据。

SQL中的复杂业务逻辑:在特定的应用程序中,大部分业务逻辑存储在SQL中,很少存储在实际的Python脚本中。虽然可以使用单元测试框架轻松地评估脚本,但SQL中的业务逻辑需要更复杂的解决方案。

处理规模的困难:随着我们的受众的增长和对实时业务洞察力的需求的增加,手工测试和确保数据质量的挑战不断加剧。抽样数据进行测试是一种选择,但它不能保证通过报告脚本中所有业务逻辑标准的高质量数据。

鉴于这些挑战只会不断加剧,我们着手开发一种功能测试框架,该框架将自动测试我们的数据仓库堆栈,生成高质量的测试数据并确保每个报告中的数据完整性。

开发功能测试框架

我们主要针对数据库和仓储业务智能(DWBI)用例(尤其是报告)设计了此框架。 简而言之:当给定脚本时,框架将基于种子查询生成测试数据,然后执行测试脚本并验证结果。

为了开发功能测试框架,我们首先定义了测试标准,技术堆栈和测试工作流程。

测试标准

首先,我们检查了当前的挑战,为框架孵化以下测试标准:

验证SQL中的业务逻辑。

确保数据完整性(即准确性、格式和完整性)。

隔离测试环境,以避免影响任何生产作业或同时运行的其他测试实例。

与我们现有的Jenkins管道集成,因此pull请求和注释可以触发功能测试。

技术堆栈

Python, pytest SQLs in YAML file Snowflake Docker

此框架的技术堆栈与要测试的实际报表脚本非常相似。这减少了编写测试的入门障碍,而不是使其成为开发应用程序代码的自然扩展。

该框架是用Python编写的,使用pytest进行断言、设置和删除以及生成XML测试报告。sql存储在一个YAML文件中,该文件运行在Snowflake上。框架还在一个专用的Docker映像中运行,该映像包含执行测试所需的所有依赖项以及脚本。

该框架的一个显著特性是测试与应用程序代码位于同一位置,从而使得任何报告脚本更改都易于开发、测试和审查。此外,测试是并行运行的,以减少运行时并简化整个构建管道。

最后,整个测试环境是自包含的。这意味着除了包含所有必需依赖项的Docker映像外,我们还在Snowflake中创建了单独的数据库和仓库,以便每个测试顺利运行。

测试工作流程

典型的测试工作流从创建特定测试实例的数据库和仓库开始,如下图所示

下一步是用测试数据填充输入表,然后执行报告脚本,它根据专用数据库和仓库中生成的测试数据运行。该脚本完成后,使用验证SQLs对输出表进行验证。最后,将结果发布在XML文件中,并写入可在Docker容器外部访问的挂载卷。

作为我们构建过程的一部分,代码中的任何更改都会自动触发这个工作流,使我们能够尽早地捕获失败,并在它们影响系统或我们的客户之前识别出回归错误。

定义测试框架架构

为了更深入地研究功能测试框架的工作流程,这里是对构建基块的简要说明。

functional_tests_main.py:这是要使用框架的脚本的入口点。 一个警告是我们的报告脚本使用Python 2,该Python 2与用于并行测试的pytest插件不兼容。 因此,我们构建了自己的解决方案,该解决方案通过检查功能测试目录中的测试文件数量来并行执行,然后为每个生成一个单独的子进程。

conftest.py:这个pytest构造是我们在功能测试目录中定义要由测试共享的固定装置和外部插件的地方。 这也是我们定义设置和拆卸方法的地方。

functional_test_runner.py:此脚本具有一个类,可为每个测试创建一个测试对象,并包含运行测试所需的所有依赖关系和属性(例如,其唯一数据库/仓库的详细信息)。

"query_script.yml":这包含用于为输入表生成测试数据以及针对输出表进行验证的SQL。

"test_script.py":此脚本包含带有测试方法和断言的测试文件。 它还负责协调特定测试的流程。 这些文件以test_ *开头,因此pytest自动选择它们以执行。

如上图所示,运行测试从功能测试名开始。然后,对于功能测试目录中的每个测试,将生成一个带有自己的测试文件的独立子进程,并查询YAML文件以同时执行和验证。测试运行后,输出将发布在XML文件中。

示例:运行功能测试框架文件

下图显示了框架内测试文件的示例。

该文件以脚本开头,我们在其中定义要测试的报告脚本的名称。 这有助于框架识别测试将使用的查询文件,并为将为测试创建的数据库和仓库提供唯一的名称。

图像中显示的第一个方法是@ pytest.fixture,在这里我们开始测试设置。 由于scope =” module”,它仅在测试中执行一次。 并且,由于autouse = True,此固定装置将被自动调用。

为了开始运行应用程序脚本,我们通过在Snowflake中创建单个数据库和仓库来准备测试环境。 然后,test_runner.run_seed_data()生成测试表和数据以填充它们。 完成后,报告脚本将启动并针对生成的测试数据运行。

最后,assert exit_code确保报告脚本已在request.addfinalizer(fin)介入处理拆解方法之前运行其进程。 紧随其后的是验证查询,该查询具有单独的测试方法,以帮助我们理解此阶段中的任何失败。

当前,该框架支持三种验证类型:

基于Snowflake查询的预期结果,其中实际结果基于针对输出表运行的不同Snowflake查询。 在要比较的数据是瞬态的情况下,此验证类型很有用。

基于数据恒定的Snowflake查询的预期结果。 例如,如果预期输出表至少具有五行,则预期结果将具有五行。

基于条件雪花查询的预期结果。 例如,它将在周末与工作日运行不同的SQL。 根据条件查询的结果,对单独的一组预期结果和实际结果进行比较。

自动化数据仓库测试的最佳实践

在使用新框架自动化测试的同时,我们解决了一些挑战,最终导致我们遵循以下最佳实践:

并行化以减少执行时间

当报表脚本面临处理大量数据时,自动化可能变得昂贵且耗时。 并行查询可以显着加快运行时间并降低计算成本。 在我们的案例中,我们开发了一种内部解决方案,该解决方案可以检测测试文件的数量,并为每个文件创建一个新的pytest子进程。

生成测试数据

生产测试数据通常是瞬态的,并且对于测试不可靠。 例如,如果客户状态发生变化,则数据可能会过时并落在处理窗口之外。 从头开始创建测试数据可提供更好的控制,并允许重复创建数据并将其重新用于测试。

设置严格的验证查询

当验证查询范围太广时,它们返回的结果可能不准确。 例如,如果验证查询中缺少一列,则测试不会标记该列中的任何意外更改。 添加尽可能多的过滤器可以增强验证查询的有效性,还有助于捕获回归错误。

订购结果集

以任何旧顺序返回的结果集在比较过程中不可避免地会导致误报。 因此,建议在查询中添加ORDER BY子句,以确保始终按升序或降序返回结果集。

隔离测试环境

当同一测试的多个实例同时运行时,表上的读/写可能会相互冲突。 这可能导致错误的测试结果。 通过在每次测试执行时创建唯一的数据库和仓库来隔离测试环境,将防止冲突并保护生产中数据的完整性。

author

石头 磊哥 seven 随便叫

company

thoughtworks

大家好,本人不才,目前依旧混迹于thoughtworks,做着一名看起来像全栈的QA,兴趣爱好前端,目前是thoughtworks 西安QA社区的leader,如果有兴趣分享话题,或者想加入tw,可以找我

roles

QA(营生) dev(front-end dev 兴趣爱好)

联系方式

如果想转载或者高薪挖我 请直接联系我 哈哈

wechat:

qileiwangnan

email:

qileilove@gmail.com