详解在Pytest中忽略测试目录的三种方法

关注开源优测不迷路

大数据测试过程、策略及挑战

测试框架原理,构建成功的基石

在自动化测试工作之前,你应该知道的10条建议

在自动化测试中,重要的不是工具

你是否曾因无关或过时的代码导致测试失败?

这可能会增加调试和故障排除的难度,还会造成不必要的测试执行时间。或者你有正在开发中的代码,还不适合进行测试。

在这些情况下,你可能想从测试套件中排除某些测试。但在 Pytest 中该怎么做呢?你当然可以在相关目录中运行 pytest,但这效率并不高。

好消息是,忽略测试目录完全可行,而且非常简单!

借助 Pytest,通过命令行选项、标记和配置文件,跳过目录和测试变得轻而易举。这不仅能确保测试顺利执行,还能让你的测试套件更精简,加速持续集成 / 持续交付(CI/CD)流程。

在本文中,你将学习如何使用 Pytest 的忽略目录功能,通过不同方法高效地从测试套件中排除不必要的测试。

你将学到什么

本文将教会你:

  • 如何使用各种选项(如命令行标志和配置文件)在 Pytest 中忽略测试目录

  • 如何使用标记忽略单个测试


理解 Pytest 中的测试收集机制

在探讨核心内容之前,让我们先了解一下 Pytest 是如何收集测试的。

Pytest 会从项目的根目录开始,对所有后续目录进行递归搜索,查找与配置模式匹配的文件和目录。具体如下:

  • 它会识别以 “test” 或 “tests” 为前缀的目录。你可以通过配置文件(如 pytest.ini)中的 testpaths 变量来定义测试目录。如果你需要复习一下 pytest.ini,可以查看这篇指南。

  • 搜索范围会扩展到名称与测试模式匹配的文件(例如 test_*.py 或 *_test.py)。

  • Pytest 会识别具有指定名称的函数或类,例如函数名以 test_* 开头,或者类名以 Test* 开头且包含测试方法。

  • 夹具对于准备测试环境至关重要,可通过初始化变量、资源并执行设置和清理操作来实现。你可以在 conftest.py 中使用 @pytest.fixture 装饰器来定义夹具。

这些约定是 Pytest 定位测试目录的默认模式。

如果你的项目目录和名称与这些约定不符,可能会遇到 “Collected 0 items” 错误。

你还可以使用自定义模式更改 Pytest 的默认测试发现规则,例如:

[pytest]python_files = check_*.py
python_classes = Check
python_functions = *_check

为什么要在 Pytest 中忽略目录?

那么,为什么要在 Pytest 中忽略目录呢?为什么不让测试框架自行处理呢?

想想看,大型项目通常包含 1000 多个测试(例如单元测试、集成测试、功能测试、回归测试、冒烟测试、端到端测试),而你需要分析某些特定测试的结果。或者你正在开发一个小功能,不需要运行整个测试套件。

当你运行 pytest 时,它会收集所有测试,这包括仍在开发中的测试、针对即将开发模块的测试,或者与当前任务无关的测试。这会使你的测试套件变得臃肿,运行速度变慢。

你可以根据 Pytest 标记来运行测试,但每次都为每个标记重复操作会很麻烦。此外,通过命令行进行选择性测试执行也具有挑战性。

这时,Pytest 的忽略目录功能就派上用场了,它可以让你干净利落地排除不必要的测试,使其不被执行。

  • 加快测试执行速度:通过排除不必要的目录,你可以减少 Pytest 需要发现和运行的测试数量。这可以显著缩短整体测试设置和执行时间,还能加快 CI/CD 流程,为你节省成本。

  • 聚焦测试:忽略目录可以让你专注于测试项目的核心和相关部分,使测试执行更有针对性。

  • 使测试输出更简洁:忽略目录有助于保持测试结果输出的简洁和有条理。你可以避免测试报告中充斥着无关信息。

  • 简化维护工作:忽略特定目录可以更轻松地维护和更新测试。你可以将测试工作集中在项目的特定区域,而不受无关文件的干扰。

采用这一功能不仅可以优化测试策略,还有助于实现更高效、快速的开发过程。

在了解了忽略目录的好处后,让我们通过一个简单的例子来探讨如何在 Pytest 中实现这一功能。

实际示例

我们的示例代码结构如下:

.├── .gitignore
├── README.md
├── pytest.ini
├── requirements.txt
├── tests
│   ├── __init__.py
│   ├── in_progress
│   │   └── test_in_progress_modules.py
│   ├── upcoming_modules
│   │   └── test_upcoming_modules.py
│   └── test_converter.py
└── src└── converter.py
示例代码

我们的示例代码是一个简单的度量单位转换器。

src/converter.py

def centimeter_to_meter(c: float) -> float:"""厘米转米的函数"""return c / 100def meter_to_centimeter(m: float) -> float:"""米转厘米的函数"""return m * 100def foot_to_inch(f: float) -> float:"""英尺转英寸的函数"""return f * 12def inch_to_foot(i: float) -> float:"""英寸转英尺的函数"""return i / 12def meter_to_millimeter(i: float) -> float:"""米转毫米的函数开发中"""# return i / 12

这里有四个用于转换米、厘米、英尺和英寸的方法,还有一个正在开发中的函数。


测试代码

tests/test_converter.py

from src.converter import (centimeter_to_meter,meter_to_centimeter,foot_to_inch,inch_to_foot,
)
import pytestdef test_centimeter_to_meter():assert centimeter_to_meter(100) == 1def test_meter_to_centimeter():assert meter_to_centimeter(1) == 100def test_foot_to_inch():assert foot_to_inch(1) == 12def test_inch_to_foot():assert inch_to_foot(12) == 1@pytest.mark.skip(reason="Function not implemented yet")
def test_millimeter_to_centimeter():assert millimeter_to_centimeter(10) == 1@pytest.mark.xfail(reason="Function expected to fail")
def test_centimeter_to_millimeter():assert centimeter_to_millimeter(10) == 1

注意,我们在 test_millimeter_to_centimeter() 函数上使用了 @pytest.mark.skip 标记,因为目标函数尚未完成。

此外,我们在 test_centimeter_to_millimeter() 函数上标记了 @pytest.mark.xfail,因为我们还没有开发 centimeter_to_millimeter() 函数,预计该测试会失败,或者可能存在需要解决的 bug。

为了模拟测试排除,让我们创建一个in_progress 文件夹,用于存放仍在开发中的测试,再创建一个 upcoming_modules 文件夹,用于存放我们计划不久后开发的函数的测试。

tests/in_progress/test_in_progress_modules.py

# 此目录包含正在开发中的模块的测试。# 开发尚未完成。因此我们可以跳过这个目录。
def test_meter_to_millimeter():pass

tests/upcoming_modules/test_upcoming_modules.py

# 即将开发的函数def test_kilometer_to_meter():pass# 即将开发的函数
def test_meter_to_kilometer():pass

在 Pytest 中忽略目录 / 测试的三种方法

使用命令行选项

跳过不需要的测试目录最简单的方法是使用 Pytest 的 --ignore 命令行选项。这个选项允许你在测试期间排除特定的目录。

对于我们的示例代码,你可以这样编写命令行命令:

pytest --ignore=tests/in_progress --ignore=tests/upcoming_modules

要忽略目录中的某些文件,你可以使用以下命令行命令:

pytest --ignore=tests/in_progress/test_in_progress_modules.py

这里,我们只忽略了 tests/in_progress 目录中的 test_in_progress_modules.py 文件。

这种方法适用于你只想临时忽略某个特定目录的情况。但显然,它不是永久排除目录的最佳选择,而且每次都要记住这些命令会很麻烦。

使用配置文件

当需要排除多个目录时,选择配置文件是比编写冗长的命令行指令更方便的方法。

利用 Pytest 的默认配置文件 pytest.ini,你可以轻松指定要忽略的目录,如下所示:

[pytest]testpaths =testsintegration
addopts = -v # 指定要忽略的目录
norecursedirs =  tests/in_progress tests/upcoming_modules

这里我们使用了 norecursedirs 关键字来忽略目录。但你也可以使用 addopts 关键字来实现相同的效果。

addopts = --ignore=tests/in_progress --ignore=tests/upcoming_modules

要忽略目录中的某些文件,你可以使用:

addopts = --ignore=tests/in_progress/test_in_progress_modules.py

这里,我们只忽略了 tests/in_progress 目录中的 test_in_progress_modules.py 文件。

当你需要永久从测试中排除目录时,这种方法很有用。

除了 pytest.ini,你还可以使用其他配置文件,如 setup.cfgtox.ini 和 pyproject.toml 来定义 Pytest 配置。以下指南展示了如何使用各种文件定义 Pytest 配置。

使用标记(针对单个测试)

标记是对测试进行分类和定制的便捷工具。作为注解,标记可以附加到函数、方法或类上,为你的测试提供额外的信息。

要处理单个测试,你可以应用 @pytest.mark.skip 或 @pytest.mark.xfail 等标记。

@pytest.mark.skip 装饰器表示跳过该测试,而 @pytest.mark.xfail 标记表示该测试预计会失败。

在我们的示例代码中:

tests/test_converter.py

import pytest@pytest.mark.skip(reason="Function not implemented yet")
def test_millimeter_to_centimeter():assert millimeter_to_centimeter(10) == 1@pytest.mark.xfail(reason="Function expected to fail")
def test_centimeter_to_millimeter():assert centimeter_to_millimeter(10) == 1

这使你可以根据自己的需求控制特定测试的行为。

当你需要经常忽略某些测试或目录时,我建议使用配置文件。这种方法可以避免每次都输入冗长的命令行指令。然而,当需要忽略单个测试时,使用标记是最佳选择。

你还可以应用自定义标记,如 @pytest.mark.smoke@pytest.mark.regression 或 @pytest.mark.slow 来对你的测试进行分类,

运行测试

你可以使用以下命令运行测试:

pytest

或者,你也可以通过命令行命令忽略目录:

pytest -v --ignore=tests/in_progress --ignore=tests/upcoming_modules

这两种方法会产生相同的输出:

pytest-ignore-directory-example-result

你会看到有 1 个测试被跳过,1 个测试预计会失败,这对应了我们测试代码中前面提到的测试。此外,tests/in_progress 和 tests/upcoming_modules 目录被忽略了,因为我们通过命令行或配置文件指示 Pytest 这样做。


为代码覆盖率忽略文件

Pytest 覆盖率报告提供了已验证代码的百分比度量。要生成覆盖率报告,你可以使用 pytest-cov 或 coverage 插件,它们可以在终端中生成报告,也可以生成美观的 HTML 文件,甚至可以在你的 GitHub 仓库上显示一个漂亮的徽章。

许多公司在拉取请求(PR)或持续集成(CI)过程中要求进行覆盖率报告检查。你可能会认为覆盖率报告只是衡量代码质量的一种表面指标,但它是确保你编写的代码有良好测试覆盖率的好方法。

如果你需要从覆盖率报告中排除特定的目录或文件,可以打开 .coveragerc 文件。使用 omit 关键字指定你要忽略的目录或文件。以下是一个示例:

[run]omit =# 忽略 /in_progress 目录下的所有内容/in_progress/*# 忽略这个单个文件tests/simple_tests.py

在上述配置中,我们排除了整个 /in_progress/* 目录以及测试文件 tests/simple_tests.py。请注意,这些路径是相对于项目根目录的。

这种灵活性使你能够根据项目的特定需求自定义覆盖率报告。这篇关于 Pytest 代码覆盖率的综合教程将教你如何实现代码覆盖率。

忽略目录时的常见问题

在忽略目录时,你可能会遇到以下挑战:

  • 遗漏重要测试:在不检查目录内测试的情况下忽略目录,可能会导致排除关键测试,从而将潜在的 “有缺陷代码” 发布到生产环境中。

  • 测试碎片化:忽略目录可能会导致测试过程出现中断或漏洞。在为了提高效率而排除不必要的测试和确保全面的测试覆盖之间取得平衡至关重要。

  • 保持配置一致性:在协作的 CI/CD 环境中,确保不同开发环境中被忽略目录的配置一致至关重要。

  • 目录结构变化:当项目结构频繁变化时,被忽略的目录可能会带来挑战。在这种情况下,可能需要调整测试配置以适应不断变化的项目布局。

  • 复杂的配置管理:随着被忽略目录数量的增加,管理配置文件和命令行参数可能会变得更加复杂。有效地应对这种复杂性对于保持简化的测试过程至关重要。


忽略目录的最佳实践

让我们来了解一些在忽略目录时应遵循的技巧和方法:

  • 利用配置文件:当需要永久排除目录时,选择配置文件。这样可以确保每次运行测试时自动排除不必要的目录,而不像命令行命令那样容易被忘记或输入错误。

  • 记录被忽略的目录:清楚地记录为什么要忽略某些目录。为从测试中排除特定目录提供详细的解释,为团队提供有价值的上下文信息。

  • 保持 CI/CD 管道的一致性:通过采用标准配置来标记被忽略的目录,确保 CI/CD 管道的一致性。这种方法可以提高测试的可靠性和可重复性。

  • 考虑测试依赖关系:注意不同目录中测试之间的依赖关系。忽略一个目录可能会对其他目录中的测试产生影响。理想情况下,测试应该是独立且分离的。如果你需要共享夹具,可以在本地目录中创建一个 conftest.py 文件并进行共享。

  • 定期审查和更新:随着项目的发展,某些目录可能会重新变得与测试相关。定期审查和更新被忽略目录的列表,以使其与项目不断变化的需求保持一致。

通过采用这些最佳实践,你可以有效地利用 Pytest 的忽略目录功能,确保维护一个强大而全面的测试套件。


总结

我们对 Pytest 忽略目录功能的探索就到这里。

本文简要介绍了在 Pytest 中忽略目录的方法,并强调了它在开发过程中的好处。通过一个实际示例,你了解了如何通过不同的方法(命令行、配置文件和标记)使用 Pytest 的忽略目录功能。你深入探讨了从代码覆盖率中排除测试的细节,提及了忽略目录相关的常见问题,并分享了一些提高目录排除效率的宝贵最佳实践。

本文提供了三种在测试执行期间忽略目录的方法。如果你只想在单次测试运行中排除某个目录,选择命令行命令是理想的。如果你想永久从测试中排除目录,使用配置文件是正确的选择。此外,标记为轻松跳过单个测试提供了便捷的工具。

希望这些见解能让你更有信心,利用 Pytest 的忽略目录选项来提升测试执行效率!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/70637.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL Server查询计划操作符(7.3)——查询计划相关操作符(6)

7.3. 查询计划相关操作符 48)Key Lookup:该操作符对一个有簇索引的表进行书签查找。参数列包含簇索引的名字和用于查找簇索引中数据行的簇键。该操作符总是伴随一个Nested Loops操作符。如果其参数列中出现WITH PREFETCH子句,则查询处理器已决定使用异步预取(预读,read-ah…

Python Pandas(5):Pandas Excel 文件操作

Pandas 提供了丰富的 Excel 文件操作功能,帮助我们方便地读取和写入 .xls 和 .xlsx 文件,支持多表单、索引、列选择等复杂操作,是数据分析中必备的工具。 操作方法说明读取 Excel 文件pd.read_excel()读取 Excel 文件,返回 DataF…

基于钉钉API的连接器实现:企业数据集成与自动化管理

文章目录 概要背景与需求钉钉API概述连接器实现小结 概要 在当今数字化时代,企业面临着海量数据的管理与整合挑战。钉钉作为国内广泛使用的办公协作平台,提供了丰富的API接口,支持企业进行数据集成与自动化管理。本文将介绍如何通过钉钉API实…

第六届MathorCup高校数学建模挑战赛-A题:淡水养殖池塘水华发生及池水自净化研究

目录 摘要 1 问题的重述 2 问题的分析 2.1 问题一的分析 2.2 问题二的分析 2.3 问题三的分析 2.4 问题四的分析 2.5 问题五的分析 3. 问题的假设 4. 符号说明 5. 模型的建立与求解 5.1 问题一的建模与求解 5.1.1 分析对象与指标的选取 5.1.2 折线图分析 5.1.3 相关性分析 5.1.4…

方舟字节码原理剖析:架构、特性与实践应用

方舟字节码原理剖析:架构、特性与实践应用 一、引言 在当今软件行业高速发展的大背景下,应用程序的性能、开发效率以及跨平台兼容性成为了开发者们关注的核心要素。编译器作为软件开发流程中的关键工具,其性能和特性直接影响着软件的质量和…

如何在Android Studio中开发一个简单的Android应用?

Android Studio是开发Android应用的官方集成开发环境(IDE),它提供了许多强大的功能,使得开发者能够高效地创建Android应用。如果你是Android开发的初学者,本文将引导你如何在Android Studio中开发一个简单的Android应用…

使用 JFreeChart 创建动态图表:从入门到实战

文章目录 前言一、JFreeChart 简介二、环境准备三、 创建第一个折线图四、自定义图表样式4.1 设置背景色4.2 设置折线颜色4.3 设置字体(解决中文乱码)4.4 设置横坐标的标签宽度和方向 五、导出图表六、实战:动态生成日报图表总结 前言 在数据…

vue.js v-model实现原理

在 vue.js 3中,通过 v-model 指令可以方便实现表单元素数据双向绑定。实现 v-model 指令元素并不神奇,本质上是一种语法糖。实现原理其实是 v-bind 和 v-on 这两个指令。 v-bind 指令会将表单元素的 value 属性与一个变量绑定,简写为 :属性名…

Formality:探针(Probe Point)的设置与使用

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一般情况下,verify命令会对参考设计和实现设计所有匹配的比较点各自进行验证,但有些时候为了调试,可能需要验证参考设计和实现设…

idea如何使用AI编程提升效率-在IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤-卓伊凡

idea如何使用AI编程提升效率-在IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤-卓伊凡 问题 idea编译器 安装copilot AI工具 实际操作 在 IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤如下: 打开 IntelliJ IDEA: 打开你的 IntelliJ IDEA 应用…

【计算机网络】TCP/IP 网络模型有哪几层?

目录 应用层 传输层 网络层 网络接口层 总结 为什么要有 TCP/IP 网络模型? 对于同一台设备上的进程间通信,有很多种方式,比如有管道、消息队列、共享内存、信号等方式,而对于不同设备上的进程间通信,就需要网络通…

Spring Boot: 使用 @Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ

Spring Boot: 使用 Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ 在微服务架构中,确保消息的可靠性和一致性非常重要,尤其是在涉及到分布式事务的场景中。本文将演示如何使用 Spring Boot 的事务机制和 TransactionSynchron…

c/c++蓝桥杯经典编程题100道(14)矩阵转置

矩阵转置 ->返回c/c蓝桥杯经典编程题100道-目录 目录 矩阵转置 一、题型解释 二、例题问题描述 三、C语言实现 解法1:使用额外空间(难度★) 解法2:原地转置(仅限方阵,难度★★) 四、…

整合 Redis 分布式锁:从数据结构到缓存问题解决方案

引言 在现代分布式系统中,Redis 作为高性能的键值存储系统,广泛应用于缓存、消息队列、实时计数器等多种场景。然而,在高并发和分布式环境下,如何有效地管理和控制资源访问成为一个关键问题。Redis 分布式锁正是为了解决这一问题…

(done) openMP学习 (Day10: Tasks 原语)

url: https://dazuozcy.github.io/posts/introdution-to-openmp-intel/#19-%E6%8A%80%E8%83%BD%E8%AE%AD%E7%BB%83%E9%93%BE%E8%A1%A8%E5%92%8Copenmp 本章节内容仅提供引入,关于 task 更详细的细节请看 openMP 手册或者源材料 Day9 介绍了一个优化链表遍历的粗糙方…

《代码随想录第二十八天》——回溯算法理论基础、组合问题、组合总和III、电话号码的字母组合

《代码随想录第二十八天》——回溯算法理论基础、组合问题、组合总和III、电话号码的字母组合 本篇文章的所有内容仅基于C撰写。 1. 基础知识 1.1 概念 回溯是递归的副产品,它也是遍历树的一种方式,其本质是穷举。它并不高效,但是比暴力循…

网站快速收录策略:提升爬虫抓取效率

本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/102.html 要实现网站快速收录并提升爬虫抓取效率,可以从以下几个方面入手: 一、优化网站结构与内容 清晰的网站结构 设计简洁明了的网站导航,确保爬虫…

群晖安装Gitea

安装Docker Docker运行Gitea 上传gitea包,下载地址:https://download.csdn.net/download/hmxm6/90360455 打开docker 点击印象,点击新增,从文件添加 点击启动 可根据情况,进行高级设置,没有就下一步 点击应…

ES6 中函数参数的默认值

ES6 引入了函数参数的默认值(Default Parameters)功能,允许在函数定义时为某些参数提供默认值。当调用函数时,如果这些参数没有传递值(或传递的值为 undefined),则会使用默认值。 1. 基本语法 …

SAP ABAP调用DeepSeek API大模型接口

搜索了一下DeepSeek,发现有人已经实现了SAP的对接, 不登录网页,SAP如何使用DeepSeek快速编程,ABAP起飞啦~ 按照对应的注册流程和方法。总算做出了第一个能够直连DeepSeek的API abap程序。 效果不错。 report ZTOOL_ABAP_CALL_D…