如何测试你的测试?

211 篇文章 0 订阅
63 篇文章 0 订阅

随着工程师为我们的应用程序开发新功能和优化,Facebook 的代码库每天都会发生变化。如果未经验证,这些变化中的每一项都可能会降低我们为全球数十亿人提供的产品的功能或可靠性。为了降低这种风险,我们维护了一套庞大的自动化回归测试来覆盖各种产品和应用程序。这些测试在开发过程的每个阶段运行,帮助工程师尽早发现回归并防止它们影响我们的产品。

图片

虽然我们使用自动化测试来检测产品质量的回归,但直到最近我们还没有办法自动检测测试本身是否恶化。自动化测试是另一种随着代码库的发展而变得不可靠的软件。不可靠(也称为flaky)测试会产生错误或不确定的信号,从而破坏工程师的信任,从而影响整个回归测试过程的有效性。如果测试有时通过,有时失败,而没有对底层产品或应用程序进行更改,则会迫使工程师花时间寻找甚至可能不存在的问题。这削弱了他们对测试过程的信任。因此,确定测试是否变得不稳定非常重要。

迄今为止,学术研究主要集中在试图确定哪些测试不可靠、哪些测试可靠。然而,软件工程实践表明,所有现实世界的测试在某种程度上都是不稳定的,即使它们是按照最佳工程原理实施的。因此,正确的问题不是某个特定的测试是否不稳定,而是它有多不稳定。为了回答这个问题,我们开发了一种测试不稳定的衡量标准:概率不稳定评分 (the probabilistic flakiness score,简称PFS)。使用这种方法,我们现在可以测试测试来测量和监控其可靠性,从而能够对测试套件质量的任何回归快速做出反应。

图片

PFS 使我们能够量化 Facebook 每个单独测试的不稳定程度,并监控其可靠性随时间的变化。如果我们检测到特定测试在创建后不久就变得不可靠,我们可以引导工程师注意修复它们。该分数是通用的,这意味着它适用于每个回归测试,无论使用哪种编程语言或测试框架。此外,它可以被有效地计算,这使我们能够扩展它以实时监控数百万次测试的可靠性。这种测试不稳定的衡量标准对于普通工程师来说是可以解释和理解的。出于这个原因,PFS 已被许多 Facebook 团队采用来设定测试可靠性目标并推动跨团队努力修复不稳定的测试。 

为什么选择 PFS? 

当测试不稳定时,工程师很快就会学会忽略它并最终删除它,这增加了未来代码更改导致功能或质量下降的风险。几年前,我们创建了一种使用机器学习来预测针对特定代码更改运行哪些测试的方法。当时,我们意识到小型的、有针对性的测试可能有些不稳定,但这是可以容忍的,并且可以通过重试或修改测试轻松解决。

然而,当我们进行更大规模的端到端测试时,可靠性是一个更大的挑战。多次重试非常耗时,并且尝试修改测试要复杂得多。当代码更改时,我们需要一个非常可靠的信号,这样开发人员就不会浪费时间去追查实际上不存在的问题。当时,我们认为真正可靠的测试永远不会显示没有回归的情况。为了知道哪些测试真正可靠,我们需要一种自动化的方法来测试这些测试。

我们着手寻找不显示任何不可靠行为的测试(有时通过,有时不通过)。我们很快意识到没有任何问题——所有端到端测试都存在一定程度的不稳定。总会有一些问题可能会影响测试的可靠性。昨天可靠的测试今天可能会变得不稳定,具体取决于多种因素。这意味着我们还需要持续监控测试的可靠性,以便在测试的不稳定程度超出可容忍范围时发出警报。

最终,我们 PFS 的目标不是断言任何测试都是 100% 可靠的,因为这是不现实的。我们的目标是简单地断言测试足够可靠,并提供一个量表来说明哪些测试不太可靠。 

PFS 如何运作?
30,000 英尺的视野

在没有任何附加信息的情况下,我们必须从表面上看单次测试执行的结果——我们没有基础来判断这个结果是测试不稳定的症状还是测试检测到回归的合理指标。然而,如果我们多次执行特定的测试并且它表现出恒定程度的不稳定,我们可以合理地期望观察到结果的具体分布。

为了测量任何测试的不稳定性,我们开发了一种统计模型,该模型产生的结果分布类似于多次执行显示已知不稳定性的测试时观察到的结果分布。我们用概率编程语言Stan实现了该模型。

只要我们设置假设测试所需的不稳定水平,该模型就可以生成测试结果的分布。然而,在使用该模型时,我们知道具体的真实测试的最新测试结果,并希望估计该测试所表现出的不稳定程度。允许我们反转模型的过程称为贝叶斯推理。它是由概率编程语言运行时非常有效地实现的,因此我们不需要太担心它。

哪些因素会影响测试结果

为了更好地理解我们的统计(定量)模型,我们将首先考虑一个更简单的定性模型。简化模型隔离了影响测试结果的三个主要因素:

1.测试是否失败绝对取决于被测试的代码和定义测试本身的代码。测试结果对代码版本的依赖性是可取的。测试完全有可能有无效的断言,尽管此类测试通常会很快被识别、修复或删除。

2.许多全面的、更端到端的测试也依赖于生产中部署的服务才能正常运行。其中一些甚至检查被测代码与这些服务的兼容性。正如被测代码的行为取决于功能门控和各种配置一样,执行此代码的测试结果也是如此。因此,测试结果对世界状况的依赖常常是不可避免的,有时也是可取的。

3.最后,我们还有一个垃圾桶(rubbish bin)。任何影响测试结果的其他因素都属于这一类。特别是,有许多影响测试执行的非确定性因素,例如竞争条件、随机性的使用或通过网络进行通信时的虚假故障。我们称之为垃圾箱片状,这正是我们想要测量和理解的。

在上述定性模型中,测试结果对最后一个因素的敏感程度构成了我们对片状性的度量。从概念上讲,如果测试的结果是可微分的,我们可以将我们的不稳定分数写如下。

图片

不幸的是,测试的结果是二元的,我们无法计算上面的偏导数。我们必须找到另一种方法来量化特定测试结果对片状因子的敏感度。

测试结果不对称

在我们构建统计模型的早期尝试中,我们偶然发现了一个有趣的问题:基础数学在替换通过和失败的测试结果方面是对称的。根据我们自己的软件工程经验,我们知道这现在反映了开发人员如何看待测试的脆弱性。我们进行了以下实证观察:

通过测试表明不存在相应的回归,而失败仅仅是再次运行测试的提示。

这种处理通过和失败测试结果的不对称是软件开发的一个特性。虽然工程师倾向于相信通过的测试结果,但他们经常在同一版本的代码上多次重试失败的测试,并认为失败后通过的结果是不稳定的。对于这种行为为何普遍存在,我们没有一个很好的理论解释。

结合上述观察结果,我们可以编写测试不稳定的统计度量,即概率不稳定分数,如下所示。

图片

直观上,分数衡量了测试失败的可能性,前提是如果重试任意次数,它可以在相同版本的代码和相同的世界状态下通过。根据我们的经验观察,如果测试可以在任意次数的重试后通过,那么在同一版本的代码和世界状态上观察到的任何失败都必须被视为不稳定。

在上面的公式中,我们使用条件概率,它捕获了在满足特定条件(任何观察到的失败都是片状的)的情况下发生特定事件(测试失败)的概率的概念。

统计模型

为了设计我们的统计模型,我们假设 PFS 是每个测试的固有属性 - 换句话说,每个测试都有一个类似的数字,我们的目标是根据观察到的测试结果序列来估计它。在我们的模型中,每个测试都不是由一个而是由两个这样的数字参数化:

1.不良状态的概率,衡量由于被测代码版本或世界状态(原文用语:the state of the world)而导致测试失败的频率。

2.良好状态下的失败概率,等于 PFS。

图片

该模型不能让我们预测特定测试的未来结果,也不能判断特定的失败是否是由代码版本、世界状态或不稳定引起的。然而,它确实让我们评估以特定的不稳定程度为特征的测试产生给定测试结果序列的可能性有多大。

我们可以在一个非常简单的例子中看到该模型的实际应用。考虑在代码 的版本和世界状态 w1 下运行的特定测试。如果第一次尝试通过,根据观察到的测试结果的不对称性,我们就完成了;我们不会重试通过测试执行。但是,如果第一次尝试失败,我们会重试一次。我们将第二次尝试视为测试的最终结果,无论它是通过还是失败 - 我们不能无限期地重试测试,在本示例中,为了简单起见,我们设置了一次重试的限制。

图片

请注意,当我们重试测试时,它必须在同一版本的代码上执行,但它可能会观察到不同的世界状态。然而,由于这两次尝试发生的时间非常接近,因此它们观察到世界不同状态的可能性极小。事实上,我们的测试基础设施有意识地努力确保特定测试的所有重试都观察到非常相似的世界状态。例如,我们将所有尝试(attempts)固定到同一版本的配置或外部服务。因此,在我们的模型中,我们假设观察到的世界状态在尝试之间不会改变。

将所有难题放在一起,我们可以根据测试的两个参数计算出观察到可能的测试结果的可能性有多大:

  • pb— 不良状态的概率

  • pf — 良好状态下发生故障的概率

测量flakiness

该模型使我们能够评估观察特定测试结果序列的概率,前提是所讨论的测试具有两个参数的特定值。然而,这些参数的值是事先未知的。我们需要以某种方式反转模型,以便根据观察到的测试结果序列来估计它们。

图片


我们使用条形图表示特定测试的一系列最新结果,其中绿色或红色条的高度分别计算在特定版本的代码和世界状态下发生的通过或失败的尝试次数。
贝叶斯定理可以解决这个问题。

图片

我们在统计建模环境Stan(编者注:Stan 是最先进的统计建模和高性能统计计算平台。用户依靠 Stan 在社会科学、生物科学、物理科学、工程学和商业领域进行统计建模、数据分析和预测。)中表达了模型,它实现了最先进的贝叶斯推理算法。这使我们能够有效地将特定测试的最近观察到的测试结果序列转换为两个参数的分布。

图片

请注意,我们的模型不是生成 PFS 的点估计,而是生成整个后验分布。这让我们可以量化我们对片状分数估计的信心:

  • 当分布很窄并且集中在特定的片状分数周围时,我们可以相信该估计,因为片状的真实程度与我们的估计显著不同的可能性极小。

  • 当分布很宽或具有多个不同的局部最大值时,这表明我们的模型无法自信地估计特定测试的片状性,因此我们必须考虑更多的测试结果来评估测试的片状性。

下面,我们介绍了4个真实世界测试(real-world tests)的示例,以及一系列最新结果和描述每个测试行为的两个参数的估计值。这些示例表明,通过我们的统计模型测量的不稳定程度与开发人员对特定测试的一系列最新结果的期望相符。请注意,该模型正确捕获了完美确定性测试中断的情况(例如,由于全局配置在一段时间内发生变化),在这种情况下,尽管观察到了许多失败,但测试的 PFS 接近于零。

图片

我们如何使用 PFS?

PFS 为我们提供了测试不稳定的衡量标准:

  • 普遍适用于任何测试

  • 仅基于观察到的结果序列,这意味着它无需任何自定义即可工作,并且适用于以任何编程语言或测试框架实现的测试

  • 表明人们对特定测试的估计不稳定程度的信心程度

自 2018 年中期首次部署以来,PFS 已实现多种用途。

胡萝卜和大棒(Carrot and a stick)

PFS 是我们针对不可靠测试对开发人员体验产生负面影响的第二大武器,仅次于资源密集型重试。

根据持续集成系统正常运行期间产生的测试结果,我们持续计算并维护所有测试的最新得分值。请注意,为了使用我们的统计模型计算 PFS,我们不需要额外的测试运行。相反,当开发人员向代码库提交更改并让持续集成系统对其进行测试时,我们可以利用正常情况下已经发生的情况。通过将统计模型拟合到特定测试结果的历史记录来计算分数只需几分之一秒,因此可以针对每个测试以及每次产生新结果时完成。

我们在特定于测试的仪表板上显示 PFS 的历史值,以便开发人员可以找到分数发生变化的时间,并更轻松地识别其根本原因。

图片

为了保持我们庞大的测试套件的可靠性,我们不仅依靠测试作者的善意,还依靠激励结构。当特定测试的不稳定度下降并开始走高时,我们会为该测试的声明所有者(无论是个人还是团队)创建一张票证。显着恶化和/或未按时修复的测试被标记为片状,这使得它们没有资格进行基于变更的测试。因此,我们的持续集成系统不会选择此类测试来运行可能影响它们的更改。这通常足以激励测试作者提高特定测试的可靠性,因为他们严重依赖测试来执行与其他开发人员更改我们的整体代码库的合同。

图片

通过这种方式,我们将 PFS 用作胡萝卜加大棒,既鼓励测试作者保持测试的可靠性,又惩罚那些让测试恶化到对其他工程师的生产力产生负面影响的人。相同的代码库。PFS 帮助我们解决自然紧张并在测试作者和更改代码库的开发人员之间建立社会契约。虽然前者被迫保持测试相当可靠,但后者必须解决可靠测试在代码更改中发现的任何问题。

衡量标准就是信任

随着时间的推移,随着 PFS 获得可信度并被更广泛地接受为反映开发人员对测试脆弱性看法的衡量标准,我们看到大型团队使用它来设定目标并推动测试可靠性改进工作。这是工程师对 PFS 出色工作的信任程度的最好证明。

PFS 是基于所有测试都在某种程度上不稳定的假设而开发的。当它用于推动组织范围内对测试质量的投资时,由于多种原因,这一点很重要。该分数有助于识别大多数不稳定的测试,从而将开发人员的时间分配给那些经过改进后最能降低观察到的不稳定总体水平的测试。虽然它不一定告诉您改进测试需要做多少工作,但它确实告诉您预期的回报。

PFS 还有助于确定何时应该停止测试质量改进工作。由于所有测试都是不稳定的,投入人力资源来提高测试可靠性最终会导致回报递减。每个测试框架和测试环境都会带来固有的脆弱性,无法通过改进测试来降低这种脆弱性。PFS 让我们能够将特定测试框架中表达的真实测试的不稳定程度与使用相同框架实现的最简单的测试的不稳定程度进行比较。当这两个分数收敛时,就表明无法使测试变得更加可靠 - 除非决定改进框架本身。我们观察到,这种有效的不稳定下限根据所讨论的测试框架而变化。对于单元测试,它远低于 1%,而对于某些端到端测试框架,它达到 10%。

关于测试框架本身造成的部分测试不稳定的观察已经得到了另一个证实。最近在测试脆弱性领域的一个项目导致了新的内部端到端测试框架的开发,这使得编写不可靠的测试变得极其困难,并且其本身几乎不会造成脆弱性。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

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

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值