关键字 开发-04 yaml文件定义变量与引用变量

前言:上篇使用jinja2模板渲染数据是在读取yaml文件的时候,进行渲染。这种肯定不是关键字框架的渲染的方式。正常我们想要的而是在yaml文件中写入我们想要渲染的数据,然后读取之后渲染到测试yaml用例中。

1. 在yaml文件中引入变量

由于变量在yaml中先声明,后引用,所以不能直接渲染整个yaml。

解决的方法是:先读取yaml,转dict , 再获取config的数据并对其进行收集,最后再进行jinja2对测试用例的数据的渲染。

import yaml
from jinja2 import Template
from pathlib import Path

def read_yaml(file_path: Path):
    """
    读取 yaml 数据,转 python 类型
    :param file_path:
    :return: dict
    """
    with open(file_path, 'r', encoding='utf-8') as fp:
        read_yml_data = yaml.safe_load(fp) # 读到的是dict

    return {
        'config': read_yml_data.get('config') if read_yml_data.get('config') else {},
        'data': [[key, value] for key, value in read_yml_data.items() if key != 'config']
    }

if __name__ == '__main__':
    file_path = Path(__file__).parent.parent.joinpath('data', 'login.yml')
    res = read_yaml(file_path)
    print(res)
    print(res['config'])
    print(res['data'])
    print(dict(res['data']))
    print(type(res))  # -->dict
"""利用反射运行关键字"""
import jinja2
import json
from requests import Response
class RunByKey:
    def __init__(self, session, config: dict = None):
        self.session = session
        self.config = config # 获取yaml config 配置
        self.context = {}  # 变量容器
        self.yaml_variables = {}  # 用例变量

    @staticmethod
    def name(value):
        print(f'用例名称:{value}')

    def request(self, request_data: dict):
        print(f"执行request: {request_data}")
        res = self.session.send_request(**request_data)
        return res

    def run(self, data: dict):
        # 1.先获取到config中的变量variables
        config_variables = self.config.get('variables', {}) if self.config else {}
        print('获取到的config中的变量:', config_variables)
        # 2.更新到变量容器中
        self.context.update(config_variables)
        for key, value in data.items():
            if hasattr(self, key):
                # 执行的request前,需要替换的数据
                print(f'渲染之前的数据:{value}')
                t2 = jinja2.Template(json.dumps(value), # dict-->str
                                     variable_start_string='${',
                                     variable_end_string='}')
                value = json.loads(t2.render(**self.context))  # str-->dict
                print(f'渲染之后的数据:{value}')
                res = getattr(self, key)(value)  # 按关键字执行
                print(f"=========当前的key:{key}")
                if key == "request":
                    print(f"执行结果:{res.text}")
            else:
                print(f"关键字未定义: {key}")

2. yaml文件中引用函数和其他变量

上面写到,yaml文件中引用config中给定的变量,如果我需要引用函数或其他地方的变量呢,比如下面的yaml文件。

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

test_login:
  name: 登录成功
  request:
    url: /api/v1/auth/login
    method: POST
    json:
      username: ${username}
      password: ${password}

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

2.1 动态获取变量和对象

我们首先要知道一个方法和2个内置函数:

  • my_builtins.__dict__ 会以字典类型返回当前位置的全部函数、变量、类等。
  • locals() 函数会以字典类型返回当前位置的全部局部变量。
  • globals() 函数会以字典类型返回当前位置的全部全局变量。
    于是我们可以写一个my_builtins.py,并获取他的全部对象,函数和变量。
utils/my_builtins.py
"""
定义一些内置函数,让yaml文件去加载并渲染
"""

password_my_builtins = "admin@password"
email1 = "123456@163.com"

def email2():
    return "54321@11.com"

def admin_username():
    return "qq@163.com"

if __name__ == '__main__':
    print(globals())

于是我们修改RunByKey下的run方法:

    def run(self, data: dict):
        # 1.先获取到config中的变量variables
        config_variables = self.config.get('variables', {}) if self.config else {}
        print('获取到的config中的变量:', config_variables)
        # 2.先渲染config_variables
        # self.context.update(config_variables), 这个时候就需要先渲染再更新到变量容器中
        self.context.update(__builtins__)
        self.context.update(my_builtins.__dict__)  # 更新内置函数和my_builtins 内置变量、函数
        t1 = jinja2.Template(json.dumps(config_variables),
                            variable_start_string='${',
                            variable_end_string='}')
        config_vars = json.loads(t1.render(**self.context))
        # 3.更新到变量容器中
        self.context.update(config_vars)
        for key, value in data.items():
            if hasattr(self, key):
                # 执行的request前,需要替换的数据
                print(f'渲染之前的数据:{value}')
                t2 = jinja2.Template(json.dumps(value), # dict-->str
                                     variable_start_string='${',
                                     variable_end_string='}')
                value = json.loads(t2.render(**self.context))  # str-->dict
                print(f'渲染之后的数据:{value}')
                res = getattr(self, key)(value)  # 按关键字执行
                print(f"=========当前的key:{key}")
                if key == "request":
                    print(f"执行结果:{res.text}")
            else:
                print(f"关键字未定义: {key}")

运行测试看看: pytest .\test_login.py -s

发现,渲染成功了。

posted @ 2023-11-25 14:49  dack_deng  阅读(3609)  评论(2编辑  收藏  举报