​我们是这样将单元测试作为工程文化一部分的!

以下为作者观点:

单元测试是软件开发中一项重要的实践,它涉及单独测试代码的各个单元或组件,以确保它们按预期运行。通过编写全面的单元测试,Instawork 工程师可以提高代码质量、增强对软件的信心并减少用户的错误。我们的持续集成 (CI) 管道每天执行超过100万次测试,因为我们的工程师了解为其代码编写有意义的测试的好处。

对于 Instawork 来说,其结果是打造了一个强大的平台,高质量的代码为我们的用户带来了无缝的体验。我们编写的每一个测试都为我们的软件构建了一个安全网,使我们的工程团队能够对平台进行更大、更大胆的改进。

在这篇文章中,我们将探讨单元测试的重要性,描述如何确保更改经过充分的单元测试,提供编写有效单元测试的技巧,并深入研究用于消除测试中的不稳定性的技术。

为什么要编写单元测试

在软件工程领域,出于多种原因,软件测试和 QA 是必需的实践。然而,单元测试提供了标准测试之外的多种好处:

  • 回归预防:单元测试有助于防止回归错误,方法是在代码库发生更改时重新测试代码组件的功能。这可确保之前正常工作的功能继续按预期运行,包括通过测试用户功能可能无法发现的行为。

  • 代码文档:当对代码库中特定类或函数的行为感到困惑时,可以检查与其关联的单元测试。单元测试可以深入了解各个代码组件的预期行为。我们还发现它们有助于 Instawork 团队新工程师的入职。

  • 代码维护:重构或基于现有代码进行构建通常比编写代码更困难。工程师需要考虑他们所做的修改是否会无意中改变现有行为。有了全面的单元测试作为安全网,确保这些行为保持不变,更改就会容易得多。

  • 避免代码不稳定:由于我们为用户提供的功能,Instawork 的业务逻辑通常与日期和时间相关联。我们增强单元测试的方法之一是针对特定的“危险”日期和时间运行任何新的或修改后的测试 - 比如夏令时转换和新年前后。稍后将详细介绍我们如何做到这一点。

在 Instawork,我们的工程师编写了超过 30,000 个 Python 单元测试,因为每个人都知道我们从中获得的好处。然而,我们不仅仅依靠这种文化来确保单元测试的持续添加和维护。

我们如何确保单元测试随变更而添加

确保单元测试保持最新状态的最有效方法是使其成为工程文化的重要组成部分。在 Instawork,所有工程师都了解单元测试的重要性,并及时了解我们用于单元测试的技术和工具。我们公司的价值观是“像主人一样行事”,这强调了编写单元测试等战略性工作的重要性,意味着我们都认识到它为构建高质量产品带来的价值。

除了依靠人力之外,我们还使用pytest-cov和Sonarcloud测量代码库的单元测试覆盖率。Sonarcloud 特别适用于测量每个 PR 的覆盖率,并使用新代码行和修改代码行的覆盖率来修饰 PR 注释。这与理解单元测试重要性的文化相结合,意味着工程师可以使用工具来确保他们的更改得到适当的测试。

图片

我们发现使用 Sonarcloud 设置此工作流程的一些有用技巧:

  • 确保在使用 Sonarcloud 分析之前将覆盖率报告导出为标准 Cobertura 格式 XML 文件

  • Sonar Scanner 需要传递拉取请求密钥和分支,以便正确修饰 PR 评论。我们使用 CircleCI 来自动化这些流程,并找到对此有用的标准变量。

  • 为了减少对 CI 运行时间的影响(特别是对于大型代码库),我们发现只测量与所做更改相关的测试的覆盖率会有所帮助。考虑使用pytest-testmon之类的工具来实现这一点。

编写有效单元测试的技巧

1.保持简单
有时说起来容易做起来难。保持单元测试小而简洁的几种方法是:

  • 使用工厂创建通用对象,而无需大量样板 — 在 pytest 中我们使用factory_boy,大多数语言至少有一个库来编写测试工厂

  • 避免重复实现逻辑 — 测试实现不应具有测试随机参数和输出的转换逻辑,而是使用你知道输出的常量参数

2.使用 AI 帮助进行初始实施

在 Instawork,我们发现使用Github Copilot可以节省编写有效测试的时间。只需命名测试并让它确定实施,根据需要进行更改以测试额外的假设或更改输入。遵循下一个建议会更有效

3.为测试赋予有意义的名称

在检查测试结果时,没有工程师希望看到test_save或被test_validation视为失败的测试 - 这就需要查看测试以确切了解它们正在做什么。尝试使用更详细的名称来表明可能出现的问题,例如test_save_fires_creation_event或test_email_address_validation

4.确保测试可读性

有时,经验丰富的工程师和初学者可以阅读测试,以了解有关代码片段的接口和行为的更多信息。如果不清楚测试验证的内容,则可能需要重构。

5.模拟外部接口,但尝试使用内部组件运行测试

在 Instawork,我们使用pytest-xdist并行运行测试,它还可以与 Django 配合使用,以确保线程之间的数据库隔离。我们还创建了一个简单的 pytest 装置,以确保测试可以单独使用 OpenSearch 索引。

6.测试应该是确定性的

不稳定的测试是所有工程师的痛点。这在 Instawork 中引起了很大的关注,因此我们开始通过特殊检查更直接地解决这个问题。

减少不稳定(flaky)

大型工程团队面临的主要问题之一是不可避免的不稳定测试(flaky test)。在有效的 CI 管道中,单元测试需要传入代码库来合并和部署更改,如果不加以解决,不稳定测试可能会使开发效率陷入停滞!

许多组织选择通过在所有管道中多次重新运行测试失败来解决不稳定问题,但我们发现这在 Instawork 中还不够,因为:

  • 这无助于解决测试中日期/时间问题导致的不稳定问题,例如测试在一天中的特定时间或一周中的特定日子失败

  • 不稳定的测试可能表明代码不稳定,需要工程团队真正解决,并且可能会影响产品质量

  • 忽视不稳定性会导致开发周期中出现糟糕的单元测试和可接受的问题。最终,这将导致管道由于不稳定性而需要重新运行,而开发人员不确定他们的更改是否破坏了测试,或者测试本身是否编写得不好。

我们尝试的一种方法是通过在关键日期和时间运行新的和修改后的测试来检查一般和基于时间的不稳定情况:

  • 今年12月31日凌晨12 点

  • 明年1月1日上午6点

  • 下一个夏令时转换前一天中午12 点

  • 下一个夏令时转换日下午6点

图片

PR测试管道高级视图

在创建此作业时,我们确实注意到它可能会以某些方式错误地将测试识别为不稳定的:

  • 我们不需要冻结时间,而是需要从冻结日期开始计时,这可以使用freezegun 的 tick参数来实现。这是因为有些测试依赖于对象的创建/修改日期进行排序。

  • 使用工厂时要小心,因为它们可以在运行 pytest 装置之前初始化,我们发现 Factory Boy 就是这种情况。我们使用LazyAttribute类来修复工厂中的这个问题。

  • 由于 Python 的线程和多处理实现,冻结时间可能会导致这些问题。因此,我们不会冻结这些库的时间。

因此,我们确实看到了不稳定因素的减少,但在 PR 推送中多次运行单元测试会增加成本,这意味着我们现在仅在 PR 请求时运行它,而不是作为我们通常的 CI 流程的一部分。如果应用程序由于特殊日期和时间而遇到不稳定测试的意外问题,可能需要考虑采用类似的方法。

单元测试对于我们工程部门来说

是一项至关重要的实践

在 Instawork,我们相信全面而强大的单元测试可以构建可靠的软件。编写单元测试可以让我们的工程师有信心避免潜在的回归,无需阅读实现即可深入了解代码单元,并简化重构和改进代码的流程。

我们以保持高水平的代码覆盖率而自豪,并通过文化和测量新代码覆盖率将其作为我们工程流程的重点。对我们来说,单元测试证明了我们对业务持久成功的承诺。

单元测试是对我们代码库长期成功的一项投资。我们建议将单元测试作为一项必要且有益的练习融入到工程团队的文化中,而不是在每个开发任务结束时添加的额外任务。不要将测试视为用户故事末尾附加的繁重任务,而应将其视为软件开发中不可或缺且有益的一部分。

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到实施工程师的项目案例时,以下是一个示例: 项目名称:部署企业级网络解决方案 项目描述:该项目旨在为一家中型企业设计和部署一个全新的网络解决方案,以提高网络性能、安全性和可靠性。 项目步骤: 1. 需求分析:与客户合作,了解他们的业务需求和网络要求。收集信息并制定详细的需求规格说明书。 2. 网络设计:基于客户需求,设计网络拓扑结构、IP地址规划、网络设备选型等。确保网络能够满足客户的需求。 3. 硬件采购:根据设计方案,与供应商合作采购所需的网络设备和硬件。 4. 网络配置:配置网络设备,包括交换机、路由器、防火墙等。确保设备按照设计要求进行正确配置。 5. 网络测试:对新部署的网络进行测试,包括性能测试、安全性测试和可靠性测试。确保网络正常运行。 6. 系统集成:将新网络与现有系统进行集成,确保各个系统之间的正常通信和协作。 7. 培训和支持:为客户提供培训,使其能够熟练使用新的网络解决方案。并提供后期支持和维护服务。 该项目案例展示了实施工程师在设计和部署企业级网络解决方案中的角色和职责。实施工程师需要与客户合作,了解需求,并根据需求设计和配置网络设备。他们还需要进行测试和集成工作,确保网络正常运行,并为客户提供培训和支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值