We're sunsetting PodQuest on 2025-07-28. Thank you for your support!
Export Podcast Subscriptions
cover of episode pytest-check - allow multiple failures per test

pytest-check - allow multiple failures per test

2025/5/2
logo of podcast Test & Code

Test & Code

AI Deep Dive Transcript
People
我 (作者)
Topics
我创建了 pytest-check 插件,它允许在单个测试函数中出现多个失败的断言。 传统的测试方法通常在遇到第一个失败的断言时就停止运行,但这在某些情况下会限制我们对测试结果的全面了解。pytest-check 插件则允许测试函数继续运行,并报告所有失败的检查结果,这对于那些需要检查多个条件的测试用例非常有用。 插件提供了两种主要的使用方式:上下文管理器和验证函数。上下文管理器 `with check:` 可以将多个断言语句包含在内,即使其中一些失败,也能继续执行后续的断言。验证函数则提供了一系列类似于 assert 的函数,例如 `equal`、`not equal` 等,方便进行各种类型的比较。 插件会收集所有失败的检查,并在测试报告中显示每个失败检查的伪回溯信息,方便调试。为了避免过多的输出信息影响效率,插件还允许用户设置限制,例如限制回溯信息的显示数量、失败报告的数量以及失败检查的总数。这些限制可以通过命令行标志或配置文件进行设置。 插件的默认设置已经足够高效,但用户可以根据需要调整这些参数。此外,用户还可以根据自己的需求自定义 helper 函数,以扩展插件的功能。 我开发这个插件的初衷是解决在测试中需要检查多个条件的场景。在单元测试中,通常建议每个测试只检查一个条件,但这在实际应用中过于限制。pytest 不仅用于单元测试,也用于大型系统测试,例如测试财务软件的转账功能或测试射频测试设备的波形。在这些场景中,需要检查多个条件,而 pytest-check 插件可以更好地满足这些需求,提供更全面的测试结果。

Deep Dive

Shownotes Transcript

今天我们讨论的是 PyTest Check,一个允许每个测试出现多个失败的插件。欢迎收听 Test & Code。本期节目由 Porkbun.com 赞助,被《今日美国》评为 2023 年至 2025 年的最佳域名注册商。现在,Porkbun 为您的下一个 .app 或 .dev 域名提供特别低价,第一年不到 6 美元,非常适合开发者、网页设计师、工程师或任何科技人员。

.app 和 .dev 域名非常适合您的最新项目。在 .app 上展示您改变世界的应用程序,并使用 .dev 来创建您的博客、文档等等。与往常一样,每个 Pokemon 域名都附带许多免费赠品,例如 SSL 证书、Whois 保护、URL 转发和托管试用版。

凭借这样的优惠,以及全年 365 天由真人提供的个性化支持,难怪如此多的科技人员和爱好者正在从 GoDaddy 等公司转向 Porkbun。要以低于 6 美元的价格获得下一个 .app 或 .dev 域名的第一年使用权,请访问 porkbun.com/testandcode25 或点击您节目说明中的链接。

PyTestCheck 是一个自 2017 年以来就存在的插件。它是我编写的一个插件,目前在顶级 PyTest 插件列表中排名第 35 位。PyTestCheck 是一个允许每个测试出现多个失败的插件。通常情况下,测试函数会在第一个断言失败时失败并停止运行。

对于许多类型的软件测试来说,这完全没问题。但是,有时您可能想要检查多件事情,并且您真的想知道每次检查的结果,即使其中一个失败了。iTestCheck 允许每个测试函数出现多个失败的检查,以便您可以了解问题的全貌。此插件主要有两种使用方法。

您可以混合搭配,在同一个测试文件中同时使用两者。第一种方法是使用上下文管理器。将 check 对象用作上下文管理器。因此,您可以说 with check,然后在 with check 中,您可以拥有大量代码。它将运行该代码,并且任何失败的断言都将停止 with 块,但它们将在测试代码中继续执行。

假设您有三个断言。如果您希望评估所有三个断言,即使其中一些失败了,那么您可以使用 with check 块包装每个断言。

另一种方法是使用验证函数。因此,提供了一系列验证函数,例如 equal、not equal、is、is not、is true、is false。它们的行为有点像 assert 方法,但是您传入参数。例如,对于 equal 方法,您传入两件事,并将它们进行相等性比较。这实际上是我在 2017 年实施的原始方法

我当时已经实施的东西,并且我得到了一些社区的帮助来完成上下文管理器版本。但是您可以混合搭配。您可以在测试中同时使用验证函数和 with check 块。PyTest check 插件将收集所有检查失败,对于一个测试,您可以有多个检查失败。因此,在报告的结尾,就像通常情况下如果出现断言失败一样,您可以看到回溯。

每个失败的检查都会打印一个伪回溯,并且它是可控的。

因此,对于每个失败的检查,都会有一个回溯,然后它也会被报告为失败的检查。因此,它具有伪回溯和检查失败的报告。但是,如果您有很多这样的检查,例如,假设您有三个,这没什么大不了的。但是,如果您正在比较 10,000 个元素向量的每个元素,则不希望打印所有这些元素。因此,您可以限制这些元素。有一些标志可以限制列出的回溯数量、限制报告的失败数量。

然后还可以限制所有失败检查的数量。因此,有一个选项,在一定时间后,或者假设您有一个 10,000 个元素的数组,如果 10 个元素错误,则停止检查。如果您想加快速度,这有助于节省时间。

但是,我已经尝试使默认值非常快速,因此它不是无限的,但它仍然非常有用。但我认为您不会想要 10,000 个回溯。看到这样的东西很烦人。所以我记不清默认值是什么了,但是您当然可以使用标志和设置来更改所有这些值,在您的 .ini 文件中更改它。

我忘记提到的一件事是,这些辅助函数很容易自己创建。因此,如果您想使用辅助函数(验证函数),但是那里有一些您需要的但不存在的东西,则 readme 中有一些关于如何创建自己的辅助函数的示例。还有一些关于如何加快速度的文章。因此,如果您正在使用它,它已经非常快速了,但是如果您真的希望它飞速运行,您可以查看此加速部分。

最后,我想谈谈我为什么首先编写这个插件。每个测试只有一个断言还不够吗?您不应该每个测试只检查一件事情吗?当人们熟悉许多单元测试哲学(只测试一件事情)时,这个问题经常出现。我理解在某些情况下这可能没问题,但我也认为它受到了极大的限制。

此外,PyTest 不仅用于单元测试。我将它用于各种事物的单元测试,也用于大型系统测试。想出一个……

一个简单的例子。这只是一个愚蠢的例子。我从未做过财务会计软件,但让我们编造一些东西。假设我有一些具有多个帐户的东西。我有两个货币帐户,并且我想测试在帐户之间转移货币的函数。假设我有帐户 A 和帐户 B。两个帐户中各有 10 美元。我正在为我的测试设置 given-when-then。给定两个帐户。

A 和 B,每个帐户各有 10 美元。当我将 10 美元从 A 转移到 B 时,A 应该有 0 美元,B 应该有 20 美元。then 语句是 A 应该为 0,B 应该为 20。这是两次检查。那么我如何用一个断言语句来表示呢?

我可以获取 A 和 B 的余额并将它们都放入变量中,然后将这两个变量(例如 bal A 和 bal B)放入元组中,并将其与另一个包含 0 和 20 的元组进行比较。我可以这样做。这是一个检查两个值的断言。我偶尔会这样做。但是,我认为这不是我们思考的自然方式。所以我认为……

我认为检查 A 的余额(应该为零)和检查 B 的余额(应该为 20)这两次检查,如果您按顺序排列它们,则读起来很好。好了,这是一个愚蠢的小例子。对于现实世界的例子,我经常将它用于使用射频测试设备测试波形。所以,

同样也要简化一下,但假设如果在特定频率下以特定电平找到信号,并且特性 x y z 为特定值,则行为是正确的,这大约是五次不同的检查:频率、电平和三个特性

如果某些东西不对劲,我想知道所有值是什么。我想知道频率是多少。我想知道电平是多少。我想知道 XYZ 特性。即使其中一个不对劲,我也想知道所有这些特性。这实际上是我将它整合在一起的原因,是为了拥有一个插件来检查多件事情并报告多个结果。

感谢所有通过 Patreon 或通过 courses.pythontest.com 上的课程学习 PyTest 来支持节目的所有人。我最近做了一个我很兴奋的改变。完整的 PyTest 课程现在是完整的 PyTest 课程包。它曾经是一个大型课程,现在是三个课程。

因为您在 PyTest 之旅的不同阶段确实需要它们。第 1 部分,PyTest Primary Power,提供了一个循序渐进的介绍,涵盖了 PyTest 的超能力,包括夹具、参数化、标记等等。掌握 primary power 并开始工作。第 2 部分,使用 PyTest 进行项目开发,包含调试、模拟、持续集成等战略性主题。第 2 部分非常适合您将 PyTest 应用于工作或开源项目时使用。第

第 3 部分:PyTest Booster Rockets,探索插件(第三方插件和构建您自己的插件),

以及高级参数化。虽然第 3 部分可以在完成其他两部分后立即学习,但最好先使用 pytest 一段时间,然后再探索您可以用它做更多的事情。我还为每个课程的开头添加了新的介绍视频,在结尾添加了祝贺视频,以及可打印的证书。无论如何,我认为新的结构更有意义。所有这些课程都在 courses.pythontest.com 上。今天的节目就到这里。感谢收听。现在,开始测试一些东西吧。