前言

Python 的使用不仅在软件开发中不断增加,而且在数据科学、机器学习、数据分析、研究科学、金融以及几乎所有其他行业等领域都在增加。Python 在许多关键领域的发展也伴随着正确、有效和高效地进行软件测试的愿望,以确保程序正确运行并产生正确的结果。 此外,越来越多的软件项目正在拥抱持续集成并包括自动化测试阶段。 探索性手动测试仍然有一席之地,但对日益复杂的项目进行彻底的手动测试是不可行的。 团队需要能够信任持续集成服务器运行的测试,以告诉他们是否可以足够信任他们的软件来发布它。

输入 pytestpytest 是一个强大的 Python 测试工具,可用于所有类型和级别的软件测试。pytest 可供开发团队、质量保证团队、独立测试小组和实践测试驱动开发的个人使用,无论是商业项目还是开源项目。 事实上,互联网上各地的项目都已从 unittestnose 转向 pytest,包括 MozillaDropbox。 为什么? 因为 pytest 提供了强大的功能,例如断言重写、第三方插件模型以及强大而简单的夹具模型,这是任何其他测试框架都无法比拟的。

为什么用 pytest?

pytest 是一个软件测试框架,这意味着 pytest 是一个命令行工具,可以自动查找您编写的测试、运行测试并报告结果。 它有一个好东西库,您可以在测试中使用它们来帮助您更有效地进行测试。 可以通过编写插件或安装第三方插件来扩展。 它可以轻松地与持续集成和 Web 自动化等其他工具集成。

以下是 pytest 优于许多其他测试框架的一些原因:

  • 简单的测试很容易在 pytest 中编写。

  • 复杂的测试仍然很容易编写。

  • 测试易于阅读。

  • 测试易于阅读。(非常重要,它被列出了两次。)

  • 您可以在几秒钟内开始使用。

  • 在测试中使用 assert 进行验证,而不是像 self.assertEqual()self.assertLessThan()

  • 您可以使用 pytest 运行为 unittestnose 编写的测试。

pytest 正在由充满热情且不断发展的社区积极开发和维护。 它具有很强的可扩展性和灵活性,可以轻松融入您的工作流程。 由于它与您的 Python 版本分开安装,因此您可以在多个版本的 Python 上使用相同版本的 pytest。

在测试示例应用程序时学习 pytest

在本书中,您将通过针对示例项目编写测试来学习 pytest,我希望该示例项目具有许多与您在阅读本书后将要测试的应用程序相同的特征。

该示例应用程序称为 CardsCards 是一个带有命令行用户界面的最小任务跟踪应用程序。它与许多其他类型的应用程序有足够的共同点,我希望您可以轻松地了解您在开发针对 Cards 的测试时学到的测试概念如何适用于您现在和将来的项目。

Cards 具有命令行界面 (CLI)。 CLI 通过应用程序编程接口 (API) 与其余代码进行交互。 API 是您指导大部分测试的接口。 API 与数据库控制层交互,数据库控制层与文档数据库 TinyDB 交互。

这不是最复杂的任务管理应用程序,但它足够复杂,可以用它来探索测试。

本书的结构

本书分为三个部分。在 【第 I 部分 “主要功能” 第 1 页】 中,您将安装 pytest 并开始使用 Cards 项目探索其主要功能。 您将学习如何在命令行上运行简单的测试功能。 然后,您将使用 pytest 装置将设置和拆卸代码从测试函数中推出。 您将学习如何使用 pytest 的许多内置设备来帮助解决临时目录等常见测试问题。 您还将学习如何通过参数化将一项测试转变为许多测试用例。 最后,您将学习如何使用标记来运行测试子集。

在 【第 II 部分 “使用项目” 中,第 97 页】,您将了解有关测试项目的一些现实问题,并探索 pytest 的更多功能。 您将首先探索一个简单的测试策略流程并将其应用于 Cards 项目。 您将查看配置文件以及测试项目中涉及的所有其他非测试文件。 您将使用覆盖率分析来查看我们的 Cards 测试漏洞在哪里,并使用模拟来帮助测试用户界面并填补一些覆盖率空白。实际上,所有测试都涉及代码和测试的一些调试,因此您将了解 pytest 帮助我们调试测试失败的一些出色功能。许多项目都利用持续集成(CI)。 Tox 是一个流行的模拟本地 CI 系统的框架。 您将了解如何将 pytesttox 以及托管 CI 系统一起使用。 第二部分还介绍了 Python 搜索路径。 Cards 项目是一个可安装的 Python 包;然而,并非所有测试项目都涉及已安装的软件包。 第二部分的本章着眼于如何告诉 pytest 查找源代码。

在 【第 III 部分 “助推器火箭” 第 195 页】 中,您将把测试提升到一个新的水平。 您将学习如何使用第三方插件来扩展 pytest 的功能,并学习如何构建自己的插件。 您还将学习基于第一部分中所学内容的高级参数化技术。

为什么是第二版?

自 2017 年本书第一版出版以来,Pythonpytest 都发生了变化。 pytest 的更新现已反映在本书中:

  • 新的内置夹具

  • 新标志

  • 添加包范围夹具

书中也反映了 Python 的更新:

  • 采用 f-stringspathlib

  • 添加 dataclasses

另外,自从第一版出版以来,我已经教了很多很多人关于 pytest 的知识,我想我已经学会了如何成为一名更好的老师。 第二版不仅扩展了第一版的内容——从 7 章增加到了 16 章!——而且它以我认为更渐进、更容易理解的方式呈现了这些材料。

那么所有这些新章节都有什么内容呢?

  • 有关参数化、标记、覆盖率、模拟、tox 和持续集成以及第三方插件的更多信息。 所有这些主题都在第一版中涵盖,但在本版中我扩大了覆盖范围。 我将参数化的讨论放到了自己的章节中,并添加了对高级参数化技术的讨论。 我更深入地研究了标记,并提供了如何将数据从标记传递到固定装置的示例(这非常酷)。 我还会带您更深入地了解测试覆盖率、模拟和 CI,并使用和构建您自己的插件来扩展 pytest 的功能。

  • 测试策略的讨论。 第一版的反馈是,这本书对于如何使用 pytest 的机制非常有用,但是 “我要编写什么测试?” 信息有点缺乏。 新的第 7 章 “策略” 第 4 页? 是朝着正确的方向推动要编写的测试。 对测试策略的完整论述本身就是一本书; 然而,本章将帮助您入门。

  • 有关 Python 搜索路径的信息。 许多读者向我询问如何让他们的测试看到他们的测试代码,而第一版没有涵盖它。 本书中的项目 Cards 不存在这个问题,因为它是一个已安装的 Python 包。 然而,许多用户项目是应用程序或脚本或许多其他未安装包的东西。 本章重点关注该问题并提供一些解决方案。

我将有关调试测试失败的信息合并到其自己的一章中。 在上一版中,这些信息遍布全书。 我希望,当您面临截止日期和失败的测试套件时,将这些信息整合到一章中将帮助您快速找到答案并减轻一些压力。

最后,示例项目发生了变化。 第一版使用了一个名为 Tasks 的项目来说明如何使用 pytest。 现在它被称为 Cards。 原因如下:

  • 大声说出来更容易。(试试看。说三遍 “任务”,然后说三遍 “卡片”。对吗?)

  • 新项目本身有所不同,因为它使用 Typer 而不是 Click 来实现命令行功能。 Typer 代码更容易阅读。

  • 该项目还使用 Rich 来格式化输出。 当第一版编写时,Rich 还不存在(Typer 也不存在)。

代码示例也得到了简化。 第一版代码示例的目录结构遵循项目中可能的测试目录的进展,其中删除了大部分项目。 说实话,我认为这对当时的我来说是有道理的。 在这个版本中,它自己的目录中有一个项目,cards_proj,没有测试。 然后,每一章都有测试代码(如果适用),可以在一个项目或某些本地代码上运行。 相信我,我想您会同意现在更容易遵循。

示例代码和在线资源

本书中的示例是使用 Python 3.7+(包括3.10)以及 pytest 6.27.0 编写和测试的。 如果您正在使用更高版本的 pytest 阅读本文,并且想知道这本书是否仍然适用,那么很可能是这样。 本书有些地方依赖于 pytest 7 功能。 但是,由于 pytest 7 非常新,因此我在必要时注意到了与 pytest 6.2 的差异。 我与许多核心 pytest 贡献者合作,以确保本书的内容也适用于 pytest 的未来版本。 在 pythontest.com 和 pragprog.com 上还设置了一个勘误表页面,其中记录了您需要了解的 pytest 和本书未来版本的任何更新。

Cards 项目的源代码以及本书中显示的所有测试的源代码都可以通过本书网页上的链接获得。 您无需下载源代码即可了解测试代码; 测试代码在示例中以可用的形式呈现。 但是要跟随 Cards 项目,或者调整测试示例来测试您自己的项目(给您更多的力量!),您必须转到本书的网页下载该项目。

要了解有关 Python 中软件测试的更多信息,您还可以查看 pythontest.com 和 testandcode.com,这是我运行的讨论该主题的博客和播客。

我已经编程了几十年,没有什么比 pytest 更让我喜欢编写测试代码了。 我希望你能从这本书中学到很多东西,并且希望你最终会像我一样热爱测试代码。