关键字 开发-11 yaml文件中添加fixture功能

前言

每一条pytest用例都可以添加fixture的前置功能,只需要在用例的参数中传入在conftest.py文件中写的函数的名称就可以实现每条用例的前置和后置。

1. yaml文件中加入fixture的功能

因为我们实现了动态生成测试用例,所以我们可以直接通过在生成动态用例的时候就传入该fixture函数名。在conftest.py文件中,我们写入fixture函数:

@pytest.fixture()
def run_fixt():
    print('------------用例执行之前---------------')
    yield
    print('------------用例执行之后----------------')

之后在生成用例函数的时候,在函数中加入,用例前置的名称即可实现用例的前置后置功能。

f = create_function_from_parameters(func=execute_yaml_case,
                                                parameters=[
                                                    Parameter('request', Parameter.POSITIONAL_OR_KEYWORD),
                                                    Parameter('requests_session', Parameter.POSITIONAL_OR_KEYWORD),
                                                    Parameter('base_url', Parameter.POSITIONAL_OR_KEYWORD),
                                                    Parameter('run_fixt', Parameter.POSITIONAL_OR_KEYWORD),  # 添加用例前置后置功能
                                                ],
                                                documentation=case_name,
                                                func_name=case_name,
                                                func_filename=f"{self.module.__name__}.py")

运行一下看看是否成功:pytest .\data\test_login.yml -s

上面的方式,我们是在生成用例函数的时候,写死进去的,不是特别灵活,我们可以通过写在yaml文件中的方式,来灵活传入用例前置后置功能。

1.1 在yaml中添加fixtures关键字

首先在,yaml中,添加fixtures的位置有2个,一个是config关键字中,另一个位置是在用例中。在config关键字中,我们在读取config数据的功能模块中添加如下的代码,获取到config下面的fixtures,
并且支持:fixtures:fun_fixtures1,fun_fixtures2或者[fun_fixtures1,fun_fixtures2]

    def run(self):
        # 1.先获取到config中的变量variables
        if not self.raw.get('config'):
            self.raw['config'] = {}
        base_url = self.raw.get('config').get('base_url', None)  # 获取config中base_url
        config_variables = self.raw.get('config').get('variables',{})
        log.info(f'获取到的config中的变量:{config_variables}')

        # 收集config中的fixtures
        config_fixtures = self.raw.get('config').get('fixtures', [])
        # 多个则变成list形式存储
        if isinstance(config_fixtures, str):
            config_fixtures = config_fixtures.split(',')

同理,在测试用例处添加fixtures,并且在获取完用例中的fixtures之后,需要在动态函数生成之前和并config中的fixture,避免重复传入fixtures,影响用例的执行。

        case = {}  # 收集用例名称和执行内容
        for case_name, case_value in self.raw.items():
          log.info(f"用例执行内容case_value: {case_value}")
          if case_name == 'config':
              continue  # 跳过config内容,非用例部分
          if not str(case_name).startswith('test'):
              case_name = 'test_' + str(case_name)
          if isinstance(case_value, list):  # 把测试用例放到用例容器case中
              case[case_name] = case_value
          else:
              case[case_name] = [case_value]  # 以list的形式加入到用例容器中case中
          # 用例中的fixtures
          if 'fixtures' in case[case_name][0]:  # fixtures写在第一个步骤中
              case_raw_fixtures = case[case_name][0].get('fixtures', [])
              case_fixtures = render_template_obj.rend_template_any(case_raw_fixtures, **self.context)
          # 如果有多个,则变成list的形式
          if isinstance(case_fixtures, str):  # fixtures: run_fixt or [run_fixt1, run_fixt2] --> list
              case_fixtures = case_fixtures.split(',')

          # 在动态函数生成之前合并config和case中的fixtures
          fun_fixtures = []
          fun_fixtures.extend(config_fixtures)  # extend()传可迭代对象,append()传一个一个整体(单个元素)
          [fun_fixtures.append(fixt) for fixt in case_fixtures if fixt not in fun_fixtures]

1.2 动态将合并后的fixtures传入到用例函数中

为了动态将fixturs参数传入用例函数中,我们需要单独编写一个动态生成生成动态函数所需要的parameters参数。于是我们写一个函数:function_parameters,并且传入进去,如下所示:

            f = create_function_from_parameters(func=execute_yaml_case,
                                                parameters=self.function_parameters(fun_fixtures),
                                                documentation=case_name,
                                                func_name=case_name,
                                                func_filename=f"{self.module.__name__}.py")
            # 向 module中加入test 函数
            setattr(self.module, case_name, f)


    @staticmethod
    def function_parameters(config_fixtures) -> list:
        # 测试函数的默认请求参数
        function_parameters = [Parameter('request', Parameter.POSITIONAL_OR_KEYWORD),
                               Parameter('base_url', Parameter.POSITIONAL_OR_KEYWORD)]  # # 内置request and base_url fixture
        # 获取传给用例的 fixtures
        if isinstance(config_fixtures, str):
            config_fixtures = [item.strip(' ') for item in config_fixtures.split(',')]
        if not config_fixtures:
            function_parameters.append(Parameter('requests_session', Parameter.POSITIONAL_OR_KEYWORD))
        else:
            if 'requests_function' in config_fixtures:
                function_parameters.append(Parameter('requests_function', Parameter.POSITIONAL_OR_KEYWORD))
            elif 'requests_module' in config_fixtures:
                function_parameters.append(Parameter('requests_module', Parameter.POSITIONAL_OR_KEYWORD))
            else:
                function_parameters.append(Parameter('requests_session', Parameter.POSITIONAL_OR_KEYWORD))  # 自定义的fixtures
            for fixture in config_fixtures:
                if fixture not in ['requests_function', 'requests_module']:
                    function_parameters.append(Parameter(fixture, Parameter.POSITIONAL_OR_KEYWORD))
        return function_parameters

在conftest.py文件中编写2个fixtures函数。

@pytest.fixture()
def run_fixt():
    print('------------用例执行之前---------------')
    yield
    print('------------用例执行之后----------------')


@pytest.fixture()
def config_run_fixt():
    print('------------config_fixtures用例执行之前---------------')
    yield
    print('------------config_fixtures用例执行之后----------------')

在yaml文件中,写入fixtures的关键字:

.\data\test_login.yml

config:
  name: yaml申明变量
  fixtures: config_run_fixt
  variables:
    username: "admin"
    password: "Admin@22"
    email11: ${email1}
    data_int: 222

test_login:
  name: 登录成功
  fixtures: run_fixt
  request:
    url: /api/v1/auth/login
    method: POST
    json:
      username: ${username}
      password: ${password}
  extract:
    code1: $.code
    code2: body.code
    token: $.data.token
    msg: '"message":"(.*?)"'
  validate:
    - eq: [$.code, "000000"]
    - eq: [$.message, OK]

test_login2:
  name: 登录失败
  request:
    url: /api/v1/auth/login
    method: POST
    json:
      username: ${email11}
      password: ${email2()}
      data_value: ${int(str_to_int(34))}

2. 引用fixtures中的返回值

fixtures函数有些会有yield的返回值,那么如何获取?显示步骤如下:

1.将args参数添加到context容器中
2.渲染变量,从context中取出fixtures中的返回值

从图中可以知道,args参数中,有fixtures函数的返回值: 'run_fixt': 'hello word'
于是我们可以将其添加context中,添加进去后,后面就是变量的渲染了。

posted @ 2023-12-11 11:23  dack_deng  阅读(69)  评论(0编辑  收藏  举报