前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pytest文档83 - 把收集的 yaml 文件转 Item 用例并运行

pytest文档83 - 把收集的 yaml 文件转 Item 用例并运行

作者头像
上海-悠悠
发布2023-01-03 13:43:11
4980
发布2023-01-03 13:43:11
举报

前言

上一篇通过用例收集钩子 pytest_collect_file 把 yaml 文件收集起来的,仅仅只是收集到用例,还不能执行。 接下来详细讲解,如何把yaml 文件的内容,转成Item 用例去执行。

pytest_collect_file 收集钩子

准备一个待执行的YAML文件内容test_login.yml

代码语言:javascript
复制
name: login case1
request:
    url: http://127.0.0.1:8000/api/v1/login/
    method: POST
    headers:
        Content-Type: application/json
    json:
        username: test
        password: 123456

先在conftest.py 写收集钩子

代码语言:javascript
复制
def pytest_collect_file(file_path: Path, parent):
    # 获取文件.yml 文件,匹配规则
    if file_path.suffix == ".yml" and file_path.name.startswith("test"):
        return pytest.File.from_parent(parent, path=file_path)

如果收集到yaml 文件返回pytest.File.from_parent(parent, path=file_path),在运行的时候会出现报错

代码语言:javascript
复制
============================================ ERRORS ============================================
_____________________________ ERROR collecting case/test_login.yml _____________________________
venv\lib\site-packages\_pytest\runner.py:339: in from_call
    result: Optional[TResult] = func()
venv\lib\site-packages\_pytest\runner.py:370: in <lambda>
    call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
venv\lib\site-packages\_pytest\nodes.py:536: in collect
    raise NotImplementedError("abstract")
E   NotImplementedError: abstract
=================================== short test summary info ====================================
ERROR case/test_login.yml - NotImplementedError: abstract
!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!

报错位置在nodes.py文件里面的collect() 方法,于是找到nodes.py 里面的Collector

代码语言:javascript
复制
class Collector(Node):
    """Collector instances create children through collect() and thus
    iteratively build a tree."""

    class CollectError(Exception):
        """An error during collection, contains a custom message."""

    def collect(self) -> Iterable[Union["Item", "Collector"]]:
        """Return a list of children (items and collectors) for this
        collection node."""
        raise NotImplementedError("abstract")

由于collect() 方法是空的,直接raise 一个异常NotImplementedError("abstract"), 于是我们需要重写collect() 方法

YamlFile 重写collect()

对应一个YamlFile 类,继承ytest.File,重写collect()方法

  • raw 是读取yaml文件的完整内容
  • name=raw.get(‘name’),name参数是设置用例的名称
  • values=raw,values是自定义的一个参数,读取的yaml文件测试数据
代码语言:javascript
复制
class YamlFile(pytest.File):

    def collect(self):
        """返回读取内容的Iterable 可迭代对象"""
        raw = yaml.safe_load(self.fspath.open(encoding='utf-8'))
        print(raw)
        # raw 是读取 yml 数据的内容
        yield pytest.Item.from_parent(self, name=raw.get('name'), values=raw)

再次运行pytest

代码语言:javascript
复制
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

item = <Item login case1>

    def pytest_runtest_call(item: Item) -> None:
        _update_current_test_var(item, "call")
        try:
            del sys.last_type
            del sys.last_value
            del sys.last_traceback
        except AttributeError:
            pass
        try:
>           item.runtest()

venv\lib\site-packages\_pytest\runner.py:167:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Item login case1>

    def runtest(self) -> None:
        """Run the test case for this item.

        Must be implemented by subclasses.

        .. seealso:: :ref:`non-python tests`
        """
>       raise NotImplementedError("runtest must be implemented by Item subclass")
E       NotImplementedError: runtest must be implemented by Item subclass

venv\lib\site-packages\_pytest\nodes.py:733: NotImplementedError

这次出现的报错在runner.py 文件,执行runtest() 方法抛出的异常NotImplementedError("runtest must be implemented by Item subclass") 看到这里,说明用例Item 已经生成了,在执行的时候,没有定义一个执行yaml文件的方法,所以报错了 于是找到nodes.py 里面的 Item(Node)

代码语言:javascript
复制
class Item(Node):
    """A basic test invocation item.

    Note that for a single function there might be multiple test invocation items.
    """

    def runtest(self) -> None:
        """Run the test case for this item.

        Must be implemented by subclasses.

        .. seealso:: :ref:`non-python tests`
        """
        raise NotImplementedError("runtest must be implemented by Item subclass")

接下来就需要重写Item 里面的runtest 去执行用例

重写Item 的runtest

最终看到的一个简版执行yaml文件的接口用例conftest.py 如下

代码语言:javascript
复制
import pytest
import requests
import yaml
from pathlib import Path

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

class YamlFile(pytest.File):

    def collect(self):
        """返回读取内容的Iterable 可迭代对象"""
        raw = yaml.safe_load(self.fspath.open(encoding='utf-8'))
        print(raw)
        # raw 是读取 yml 数据的内容
        yield YamlTest.from_parent(self, name=raw.get('name'), values=raw)

class YamlTest(pytest.Item):
    def __init__(self, name, parent, values):
        super(YamlTest, self).__init__(name, parent)
        self.name = name
        self.values = values
        self.s = requests.session()

    def runtest(self) -> None:
        """运行用例"""
        request_data = self.values["request"]
        response = self.s.request(**request_data)
        print("\n", response.text)

输入pytest就可以看到yaml文件被当成用例去执行了

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 从零开始学自动化测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • pytest_collect_file 收集钩子
  • YamlFile 重写collect()
  • 重写Item 的runtest
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档