首页 > 其他分享 > pytest文档82 - 用例收集钩子 pytest_collect_file 的使用

pytest文档82 - 用例收集钩子 pytest_collect_file 的使用

时间:2022-11-16 23:22:48浏览次数:57  
标签:用例 collect pytest yaml file test path

前言

pytest 提供了一个收集用例的钩子,在用例收集阶段,默认会查找test_*.py 文件或者 *_test.py文件。
如果我们想运行一个非python的文件,比如用yaml 文件写用例,那么就需要改变用例的收集规则。
以最新版pytest 7.2.0版本为例

YAML 测试示例

在 Yaml 文件中指定测试的基本示例, 以下是官方文档上给的一个执行yaml格式的内容作为自定义测试的例子。
相关文档地址https://docs.pytest.org/en/latest/example/nonpython.html
写到conftest.py

# content of conftest.py
import pytest


def pytest_collect_file(parent, file_path):
    if file_path.suffix == ".yaml" and file_path.name.startswith("test"):
        return YamlFile.from_parent(parent, path=file_path)


class YamlFile(pytest.File):
    def collect(self):
        # We need a yaml parser, e.g. PyYAML.
        import yaml

        raw = yaml.safe_load(self.path.open())
        for name, spec in sorted(raw.items()):
            yield YamlItem.from_parent(self, name=name, spec=spec)


class YamlItem(pytest.Item):
    def __init__(self, *, spec, **kwargs):
        super().__init__(**kwargs)
        self.spec = spec

    def runtest(self):
        for name, value in sorted(self.spec.items()):
            # Some custom test execution (dumb example follows).
            if name != value:
                raise YamlException(self, name, value)

    def repr_failure(self, excinfo):
        """Called when self.runtest() raises an exception."""
        if isinstance(excinfo.value, YamlException):
            return "\n".join(
                [
                    "usecase execution failed",
                    "   spec failed: {1!r}: {2!r}".format(*excinfo.value.args),
                    "   no further details known at this point.",
                ]
            )

    def reportinfo(self):
        return self.path, 0, f"usecase: {self.name}"


class YamlException(Exception):
    """Custom exception for error reporting."""

创建一个简单的yaml文件

# test_simple.yaml
ok:
    sub1: sub1

hello:
    world: world
    some: other

如果你已经安装了 PyYAML 或 YAML-parser解析器,那么就可以执行yaml用例

nonpython $ pytest test_simple.yaml
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/nonpython
collected 2 items

test_simple.yaml F.                                                  [100%]

================================= FAILURES =================================
______________________________ usecase: hello ______________________________
usecase execution failed
   spec failed: 'some': 'other'
   no further details known at this point.
========================= short test summary info ==========================
FAILED test_simple.yaml::hello
======================= 1 failed, 1 passed in 0.12s ========================

网上关于 pytest 插件开发的资料非常少,大部分都是停留在使用 pytest 写用例的阶段。
也有一些 pytest+yaml 的封装,最终还是会写的 py 文件去读取 yaml 文件执行用例,并没有达到真正意义上的把 yaml 文件当一个用例去执行。

pytest_collect_file 钩子

先看下pytest_collect_file 钩子的定义

def pytest_collect_file(
    file_path: Path, path: "LEGACY_PATH", parent: "Collector"
) -> "Optional[Collector]":
    """Create a :class:`~pytest.Collector` for the given path, or None if not relevant.

    The new node needs to have the specified ``parent`` as a parent.

    :param file_path: The path to analyze.
    :param path: The path to collect (deprecated).

    .. versionchanged:: 7.0.0
        The ``file_path`` parameter was added as a :class:`pathlib.Path`
        equivalent of the ``path`` parameter. The ``path`` parameter
        has been deprecated.
    """

这里用到了3个参数

  • file_path 它是一个 pathlib.Path 对象, 收集到的文件路径
  • path LEGACY_PATH(合法路径), 收集到的文件路径
  • parent Collector 收集器,用例文件.py 或者 .yml 文件的父目录,也就是 python 的包 Package

v 7.0.0 版本的变更:
在 v 7.0.0 版本后,新增了一个 file_path 参数,它与原来的 path 功能是一样的,原来的 path 参数会被弃用。

我们看下这2个参数变更前和变更后到底用什么区别呢?

def pytest_collect_file(file_path: Path, path, parent):
    # 获取文件.yml 文件,匹配规则
    if file_path.suffix == ".yml" and file_path.name.startswith("test"):
        print(file_path, type(file_path))
        print(path, type(path))
        print(parent, type(parent))
        return YamlFile.from_parent(parent, path=file_path)

运行 pytest -s
看到打印日志

collecting ... D:\demo\demo_x2\case\test_login.yml <class 'pathlib.WindowsPath'>
D:\demo\demo_x2\case\test_login.yml <class '_pytest._py.path.LocalPath'>
<Package case> <class '_pytest.python.Package'>

原来的path参数(path.LocalPath),是通过os模块的path 获取的文件路径
最新的file_path 参数(pathlib.WindowsPath), 是通过pathlib 模块获取的文件路径。
pathlib 是 os模块的升级版,所以这里做了一个细节的优化。

通过pytest_collect_file收集钩子就可以找到.yml后缀,并且以test开头的文件,会被当做用例返回。

pytest_ignore_collect 忽略收集

pytest_collect_file 勾选相反的一个忽略收集钩子pytest_ignore_collect


[docs]@hookspec(firstresult=True)
def pytest_ignore_collect(
    collection_path: Path, path: "LEGACY_PATH", config: "Config"
) -> Optional[bool]:
    """Return True to prevent considering this path for collection.

    This hook is consulted for all files and directories prior to calling
    more specific hooks.

    Stops at first non-None result, see :ref:`firstresult`.

    :param collection_path: The path to analyze.
    :param path: The path to analyze (deprecated).
    :param config: The pytest config object.

    .. versionchanged:: 7.0.0
        The ``collection_path`` parameter was added as a :class:`pathlib.Path`
        equivalent of the ``path`` parameter. The ``path`` parameter
        has been deprecated.
    """

也是传3个参数

  • collection_path 收集到的用例文件路径,pathlib.Path类
  • path 跟 collection_path作用一样,被弃用了
  • config Config的实例

通过返回布尔值判断是否收集该文件
举个例子,当判断用例文件名称是test_login.yml 就不收集

def pytest_ignore_collect(collection_path: Path, path, config):
    # 返回布尔值(会根据返回值为 True 还是 False 来决定是否收集改路径下的用例)
    if collection_path.name == 'test_x.yml':
        return True

运行后不会收集'test_x.yml'文件

标签:用例,collect,pytest,yaml,file,test,path
From: https://www.cnblogs.com/yoyoketang/p/16897902.html

相关文章

  • python源码通过词语标记化器tokenize提取注释并正则匹配测试用例作者名
    提取代码如下importtokenizeimportrewithtokenize.open('readcomment.py')asf:list=[]fortoktype,tok,start,end,lineintokenize.generate_t......
  • pytest文档81 - 如何管理Captured logging日志
    前言pytest自动捕获级别为WARNING或以上的日志消息,并以与捕获的stdout和stderr相同的方式在每个失败测试的各自部分中显示它们。日志显示当输入pytest命令,不带任......
  • pytester
    目录介绍cd到临时文件目录创建文件相关介绍pytester是pytest框架的内置fixture,想使用pytester要在conftest.py或者是用例文件的最上面添加pytest_plugins="pytester"......
  • Collection
    Collection/**Copyright(c)1997,2013,Oracleand/oritsaffiliates.Allrightsreserved.*ORACLEPROPRIETARY/CONFIDENTIAL.Useissubjecttolicensete......
  • Collections 工具类
    packagecom.msb.test01;importjava.util.ArrayList;importjava.util.Collection;importjava.util.Collections;/***@author:liu*日期:14:02:08*描述:IntelliJ......
  • 《JavaSE-第十九章》之Collection
    《JavaSE-第十九章》之Collection前言在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”博客主页:​​KC老衲爱尼姑的博客主页​​​​博主的github,......
  • Linux命令之sar命令用例
    一、命令简介  sar(SystemActivityReporter系统活动情况报告)命令用于收集、报告或保存系统活动信息。sar命令将操作系统中选定的累积活动计数器的内容写入标准输出。会计......
  • pytest_01-pytest简介
    一、pytest单元测试框架(1)什么是单元测试框架单元测试是指在软件开发当中,针对软件的最小单位(函数、方法)进行正确性的检查测试(2)单元测试框架java:junit和tesingpytho......
  • Pytest接口测试框架实战项目搭建(四)—— 业务系统接口请求演示
    一、前言前面相当于已经讲完整体框架搭建了,本篇主要讲述在实际业务系统的接口请求中,如何运用好该接口自动化测试框架。二、步骤演示1、在conf/api_path.py新增需要......
  • idea+maven+springboot如何配置Mybatis-plus并测试简单用例
    用例情况如上图,假设我们需要读取ywj数据库中的dept表中的记录 大致步骤1、首先,需要在对应maven工程的.pom文件中引入相应的依赖,包括mybatis-plus-boot-starter、mysq......