ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

pytest+yaml+allure接口自动化测试框架03.读取测试用例文件

2021-09-25 13:03:53  阅读:144  来源: 互联网

标签:__ 03 name self pytest yaml allure spec


前言

​ 使用yaml作为测试用例,我们就需要对文件的内容进行读取,常规来说的应该是通过pyyaml对读取到的内容进行数据解析,然后使用pytest parametrize参数化功能进行数据参数化用例测试。但是完事之后,这样的方式好像不是很优雅,写的代码组织起来比较费劲,于是乎,我在pytest的官方文档中,发现了一套更为一套非常优雅的测试执行方式,他们称之为non-python test的测试模式。

具体内容可以查看官方文档,感兴趣的可以去看看:Working with non-python tests — pytest documentation

# content of conftest.py
import pytest


def pytest_collect_file(parent, path):
    if path.ext == ".yaml" and path.basename.startswith("test"):
        return YamlFile.from_parent(parent, fspath=path)


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

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


class YamlItem(pytest.Item):
    def __init__(self, name, parent, spec):
        super().__init__(name, parent)
        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.fspath, 0, f"usecase: {self.name}"


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

可以看到官方文档中以极其优雅的方式通过yaml文件驱动了两个测试用例。我们也将在此基础上进行扩展衍生。

读取yaml文件

​ 我们根据官方文档中的示例文件,在这个基础上进行修改,加入我们的内容。

pytest_collect_file

首先我们修改pytest_collect_file函数中的内容,让他支持yamlyml两种格式的文件内容。因为这两种都可以,官网示例中只有一个。

YamlFile.collect

接下来修改我们的YamlFile.collect方法,这里面就是对读出来的详细内容按照设置的格式进行处理,该存入缓存的放入缓存,该执行测试的时候执行测试。

if not any(k.startswith('test') for k in raw.keys()):
    raise YamlException("{}yaml non test found".format(self.fspath))

通过这个语句我们先判断一下,有没有测试用例,如果没有测试用例我们直接就报错了,不在执行,抛出异常,这个异常需要我们自己封装一下。我们打开common/exceptions.py文件。输入以下内容:

# -*- coding: utf-8 -*-
__author__ = 'wxhou'
__email__ = '1084502012@qq.com'
"""
异常类
"""
from requests.exceptions import RequestException


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

    def __init__(self, value):
        self.value = value

    def __str__(self):
        return "\n".join(
            [
                "usecase execution failed",
                "   spec failed: {}".format(self.value),
                "   For more details, see this the document.",
            ]
        )

这个就是当我们发现yaml文件中没有符合的测试标签内容后抛出的异常类。

然后我们接着先读取全局变量:

if variable := raw.get('variable'):
    for k, v in variable.items():
        cache.set(k, v)

我们把yaml文件中预设的全局变量信息中全部存在我们设置的缓存模块中,这样在测试过程中我们可以随时的去用。

继续读取配置文件。

if config := raw.get('config'):   
    for k, v in config.items():
        cache.set(k, v)

然后我们读取常用的测试信息也放入缓存之中,方便运行过程中随时去调用。

最后我们来处理一下。测试用例部分:

if tests := raw.get('tests'):
    for name, spec in tests.items():
        yield YamlTest.from_parent(self,
                                   name=spec.get('description') or name,
                                   spec=spec)

可以看到,在官方文档中使用了sorted函数进行了再次排序。我这里没有是因为再次排序会破坏用例的结构和顺序。最后输出的时候spec.get('description') or name的写法先获取yaml文件中我们设置的中文标识,如果中文标识不存在则继续使用英文标识。其余和官方文档保持一致。

以上就是做出的改动,我们来看看吧:

import yaml
import pytest
from common.cache import cache
from common.exceptions import YamlException


def pytest_collect_file(parent, path):
    if path.ext in (".yaml", ".yml") and path.basename.startswith("test"):
        return YamlFile.from_parent(parent, fspath=path)


class YamlFile(pytest.File):

    def collect(self):
        raw = yaml.safe_load(self.fspath.open(encoding='utf-8'))
        if not any(k.startswith('test') for k in raw.keys()):
            raise YamlException("{}yaml non test found".format(self.fspath))
        if variable := raw.get('variable'):
            for k, v in variable.items():
                cache.set(k, v)
        if config := raw.get('config'):
            for k, v in config.items():
                cache.set(k, v)
        if tests := raw.get('tests'):
            for name, spec in tests.items():
                yield YamlTest.from_parent(self,
                                           name=spec.get(
                                               'description') or name,
                                           spec=spec)

站在巨人的肩膀上才能看得更远。在pytest non-python tests的内容之上做了一些改动,使得读取文件更加贴合我们定义的yaml文件内容。在精简了很多代码的同时我们也达到了预期的效果。

至此,本章的读取yaml测试文件到此结束。

标签:__,03,name,self,pytest,yaml,allure,spec
来源: https://www.cnblogs.com/wxhou/p/InterfaceYamlFramework03.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有