Python pytest 执行用例时如何自动加载 yaml 文件

sunzhang · 2023年08月22日 · 最后由 disable 回复于 2023年08月23日 · 3661 次阅读

想要效果:pytest 执行用例的时候,能够获取到配置的用例文件


  • 自动化接口测试中,pytest 执行的代码除了用例文件不一样,其余的代码都是大同小异
  • 所以想通过文件配置,把所有的用例文件配置在一个文件里面
  • 通过循环读取到用例文件路径,然后传给 pytest 执行

想法是好的,结果并不能如愿,我这么做,最后结果只能执行到配置文件中最后一个路径,并不能循环执行

有没有大佬指点一下,谢谢!!!

共收到 4 条回复 时间 点赞

@ddt,你怎么能在一个 def function 外面包一层,for 循环。。。应该要用这种参数化运行的方法

yaml_data_list 是一个数组,里面有几个元素,这个 test_case 的方法,就会被执行几次

想问下你现在是没有 api 层嘛,只有一个执行函数,然后就只用给数据就行了

conftest.py 文件重写 pytest_collect_file

conftest 参考,低配版

import importlib
import inspect
import json
import os
from string import Template
import jinja2
import jsonpath
import pytest
import requests
import yaml


def all_functions():
    """加载debug.py模块"""
    debug_module = importlib.import_module("data.debug")
    all_function = inspect.getmembers(debug_module, inspect.isfunction)
    # print(dict(all_function))
    return dict(all_function)


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):
        import yaml
        yml_raw = self.fspath.open(encoding='utf-8').read()
        yml_var = Template(yml_raw).safe_substitute(os.environ)
        yml_var = jinja2.Template(yml_var).render(**all_functions())
        raw = yaml.safe_load(yml_var)

        for yaml_case in raw:
            name = yaml_case["test"]["name"]
            values = yaml_case["test"]
            yield YamlItem.from_parent(self, name=name, spec=values)


class YamlItem(pytest.Item):
    def __init__(self, name, parent, spec):
        super().__init__(name, parent)
        self.name = name
        self.values = spec
        self.request = self.values.get("request")
        self.validate = self.values.get("validate")
        self.s = requests.session()
        self._obj = None

    def values_render_variable(self, values):
        # 替换测试用例中的关联值
        yaml_test = Template(json.dumps(values)).safe_substitute(os.environ)
        values = yaml.safe_load(yaml_test)
        return values

    def runtest(self):
        values = self.values_render_variable(self.values)
        request_data = values["request"]
        print(request_data)
        response = self.s.request(**request_data)

        self.assert_response(response, self.validate)

        if values.get("extract"):
            for key, value in values.get("extract").items():
                os.environ[key] = jsonpath.jsonpath(response.json(), value)[0]
        self.assert_response(response, values.get("validate"))

    def assert_response(self, response, validate):
        """自定义断言"""
        for i in validate:
            if "eq" in i.keys():
                yaml_result = i.get("eq")[0]
                actual_result = jsonpath.jsonpath(response.json(), yaml_result)
                expect_result = i.get("eq")[1]

                assert actual_result[0] == expect_result

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册