pytest:hooks

pytest运行的整个过程中, 充满了各种Hook函数

覆写Hook函数虽然无法改变pytest的执行流程, 但可以实现用户自定义行为

比如collection阶段, 可以不局限于test开头的模块和方法; run阶段, 可以过滤特殊的方法

官网中描述了以下几种hook函数

  • Bootstrapping hooks, 启动pytest时引入
  • Initialization hooks, 初始化插件, 及conftest.py文件
  • Test running hooks, 执行case时调用
  • Collection hooks, 从目录/文件中发现testcase
  • Reporting hooks, 报告相关
  • Debugging/Interaction hooks, 特殊hook函数, 异常交互相关

解析yml文件, 从中提取接口参数, 并执行接口测试

import pytest
import sys
import requests

def pytest_collect_file(path, parent):
"""
    定义yml后缀, 且以unit开头的文件, 将被诹
    :param path: 文件全路径
    :param parent: session
    :return: collector
"""
    if path.ext == ".yml" and path.basename.startswith("unit"):
        return YamlFile(path, parent)

class YamlFile(pytest.File):

    def collect(self):
        '''
        collector调用collect方法, 会从文件中提取Item对象, 即testcase
        :return: [Items]
        '''
        import yaml
        raw = yaml.safe_load(self.fspath.open())
        for name, attrs in raw.items():
            yield YamlItem(name, self, attrs)

class YamlItem(pytest.Item):
    def __init__(self, name, parent, attrs):
        super(YamlItem, self).__init__(name, parent)
        self.attrs = attrs

    def setup(self):
        '''
        Item 对象的初始化步骤, 同样还有teardown方法, 这里省略
        :return:
        '''
        if 'setup' in self.attrs:
            for action, args in self.attrs['setup'].items():
                getattr(sys.modules['builtins'], action)(args)

    def runtest(self):
        '''
        执行Item对象时, 会调用runtest方法
        所以这里定义具体的测试行为
        :return:
        '''
        try:
            url = self.attrs['body']['url']
            data = self.attrs['body']['data']
            expected = self.attrs['expected']

            resp = requests.get(url, params=data)
            actual = resp.json()

            for key, value in expected.items():
                assert actual['args'][key] == value
        except KeyError:
            raise YamlException(self.name)

class YamlException(Exception):
    pass
my_get_request:
  body:
    url: https://httpbin.org/get
    data:
      keyword: cucumber
  setup:
    print: setup step
  expected:
    keyword: cucumber

执行 pytest即可查看运行结果

相关类介绍

解析命令行参数, 以及ini文件, 将结果传递给Config

addoption(self, *opts, **attrs)

group.addoption(
    "--maxfail",
    metavar="num",
    action="store",
    type=int,
    dest="maxfail",
    default=0,
    help="exit after first num failures or errors.",
)

addini(self, name, help, type=None, default=None)

parser.addini(
    "python_files",
    type="args",
    default=["test_*.py", "*_test.py"],
    help="glob-style file patterns for Python test module discovery",
)

记录命令行的参数option, 以及ini属性

getoption(self, name, default=notset, skip=False)

getini(self, name)

包含config, testsfailed, testscollected等属性

即testcase, 继承自Node, 基本属性如下

    def __init__(
        self, name, parent=None, config=None, session=None, fspath=None, nodeid=None
    ):
        #: a unique name within the scope of the parent node
        self.name = name

        #: the parent collector node.

        self.parent = parent

        #: the pytest config object
        self.config = config or parent.config

        #: the session this node is part of
        self.session = session or parent.session

        #: filesystem path where this node was collected from (can be None)
        self.fspath = fspath or getattr(parent, "fspath", None)

        #: keywords/markers collected from all scopes
        self.keywords = NodeKeywords(self)

        #: the marker objects belonging to this node
        self.own_markers = []

        #: allow adding of extra keywords to use for matching
        self.extra_keyword_matches = set()

        # used for storing artificial fixturedefs for direct parametrization
        self._name2pseudofixturedef = {}

Initialization hooks

通过Parser注册命令行参数, 以及添加ini-stype属性

命令行解析完成后, 初始化conftest.py文件时执行

def pytest_addoption(parser):
    parser.addoption(
        "--season",
        dest="seasion",
        default="summer",
    )

def pytest_configure(config):
    print("season ==> {}".format(config.getoption("seasion")))
===============================
season ==> summer

测试进程结束前执行

会话创建时, 尚未收集testcase, 比configure阶段晚

整个测试完成后执行

Test running hooks

所有的testcase都被封装成pytest.Item对象

collection阶段完成后, 启动测试任务时调用

执行单条用例, 比pytest_runtest_setup()早

location = (filename, linenum, testname)

Collection hooks

pytest采取一定规则, 去特定目录和文件中检索testcase, 而Collection hooks可以定义这些规则

执行collection操作

如果返回True, 则忽略掉path路径, 优先执行

开始扫描目录, 如何处理目录下的文件, 及子目录

汇总测试文件, 作为collection Node, 用于后续提取testcase

从已收集的文件中提取出用例, 并封装成item

向测试方法传递参数, 形成多次调用效果

所有的测试用例收集完毕后调用, 可以再次过滤或者对它们重新排序

Original: https://blog.csdn.net/weixin_44129801/article/details/122315911
Author: Lion…
Title: pytest:hooks

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/775056/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球