首页 > 其他分享 >pytest处理yml用例嵌套参数关联

pytest处理yml用例嵌套参数关联

时间:2025-01-02 21:02:19浏览次数:3  
标签:case field value 用例 pytest details test data yml

在 YAML 用例中,可以使用占位符来关联嵌套参数。这种方式可以让你在一个地方定义某个参数,然后在其他地方引用它。这在处理复杂的嵌套结构时尤其有用。

以下是如何在 YAML 文件中实现嵌套参数的关联的示例。

1. 更新 YAML 文件

这里我们将定义一个用户的详细信息,并在多个地方引用这些参数。

test_cases.yml

# test_cases.yml
user_details:
  name: "John Doe"
  email: "john.doe@example.com"
  details:
    age: 30
    address:
      city: "New York"
      zip: "10001"
    contacts:
      - type: "phone"
        number: "123-456-7890"
      - type: "email"
        number: "john.doe@example.com"

tests:
  - name: "Create User"
    method: "POST"
    endpoint: "/api/users"
    payload:
      name: ${user_details.name}
      email: ${user_details.email}
      details:
        age: ${user_details.details.age}
        address:
          city: ${user_details.details.address.city}
          zip: ${user_details.details.address.zip}
        contacts: ${user_details.details.contacts}
    expected_status: 201
    id: "user_id"

  - name: "Get User"
    method: "GET"
    endpoint: "/api/users/{user_id}"
    expected_status: 200
    depends_on: "Create User"
    validate:
      field: "details.age"
      condition: "greater_than"
      value: 18

  - name: "Get User City"
    method: "GET"
    endpoint: "/api/users/{user_id}"
    expected_status: 200
    depends_on: "Get User"
    validate:
      field: "details.address.city"
      condition: "equals"
      value: "New York"

  - name: "Get User Phone"
    method: "GET"
    endpoint: "/api/users/{user_id}"
    expected_status: 200
    depends_on: "Get User"
    validate:
      field: "details.contacts.0.number"
      condition: "equals"
      value: "123-456-7890"

2. 处理占位符的代码

你需要在加载 YAML 文件时处理这些占位符。可以使用简单的文本替换来实现。

import yaml
import requests
import pytest
import re

def load_test_cases(file_path):
    """从 YAML 文件加载测试用例。"""
    with open(file_path, 'r') as file:
        data = yaml.safe_load(file)
        return data

def resolve_placeholders(data, context):
    """解析 YAML 数据中的占位符。"""
    if isinstance(data, dict):
        return {key: resolve_placeholders(value, context) for key, value in data.items()}
    elif isinstance(data, list):
        return [resolve_placeholders(item, context) for item in data]
    elif isinstance(data, str) and data.startswith("${") and data.endswith("}"):
        placeholder = data[2:-1]  # 去掉 ${ 和 }
        return context.get(placeholder, data)  # 返回上下文中的值或原字符串
    return data

@pytest.fixture(scope="session")
def base_url():
    return "http://localhost:5000"  # 替换为你的 API 基础 URL

def run_test_case(base_url, test_case, previous_results):
    """执行单个测试用例并验证响应。"""
    url = f"{base_url}{test_case['endpoint']}"
    method = test_case['method']
    expected_status = test_case['expected_status']

    # 替换 URL 中的 {user_id}
    for key in previous_results:
        if f'{{{key}}}' in url:
            url = url.replace(f'{{{key}}}', str(previous_results[key]))

    # 发送请求
    response = requests.request(method, url, json=test_case.get('payload', {}))

    # 断言状态码
    assert response.status_code == expected_status

    # 记录结果
    if 'id' in test_case:
        previous_results[test_case['id']] = response.json().get('id')  # 记录创建结果的 ID

    # 验证返回字段
    if 'validate' in test_case:
        validate_response(response.json(), test_case['validate'])

def validate_response(response_data, validation):
    """验证响应数据中的字段值是否满足特定条件。"""
    field_path = validation['field'].split('.')
    actual_value = response_data

    for field in field_path:
        if isinstance(actual_value, dict) and field in actual_value:
            actual_value = actual_value[field]
        elif isinstance(actual_value, list) and field.isdigit():
            actual_value = actual_value[int(field)]
        else:
            pytest.fail(f"Field '{validation['field']}' not found in response: {response_data}")

    # 执行条件验证
    condition = validation['condition']
    value = validation['value']

    if condition == "equals":
        assert actual_value == value, f"Expected {validation['field']} to be '{value}', but got '{actual_value}'"
    elif condition == "contains":
        assert value in actual_value, f"Expected {validation['field']} to contain '{value}', but got '{actual_value}'"
    elif condition == "greater_than":
        assert actual_value > value, f"Expected {validation['field']} to be greater than '{value}', but got '{actual_value}'"
    elif condition == "less_than":
        assert actual_value < value, f"Expected {validation['field']} to be less than '{value}', but got '{actual_value}'"

def test_api():
    """主测试函数,执行所有测试用例。"""
    data = load_test_cases('test_cases.yml')
    context = data['user_details']  # 获取用户详情作为上下文
    test_cases = data['tests']

    # 解析占位符
    for test_case in test_cases:
        if 'payload' in test_case:
            test_case['payload'] = resolve_placeholders(test_case['payload'], context)

    previous_results = {}
    skip_tests = set()  # 存储需要跳过的测试用例名称

    for test_case in test_cases:
        if 'depends_on' in test_case and test_case['depends_on'] in skip_tests:
            pytest.skip(f"Skipping '{test_case['name']}' due to failure in '{test_case['depends_on']}'.")

        try:
            run_test_case(base_url(), test_case, previous_results)
        except AssertionError as e:
            print(f"Test case '{test_case['name']}' failed: {str(e)}")
            skip_tests.add(test_case['name'])  # 将当前测试标记为跳过

代码解释

  1. YAML 文件

    • 使用 ${} 语法来定义占位符,引用 user_details 中的参数。
  2. 解析占位符

    • 使用 resolve_placeholders 函数递归地解析 YAML 数据中的占位符,查找上下文中的值替换占位符。
  3. 上下文管理

    • test_api 函数中,将 user_details 加载到上下文中,并在解析测试用例的 payload 时引用这些值。

3. 运行测试

确保你已经安装了 pytestrequests 库。可以使用以下命令运行测试:

pytest your_test_script.py

总结

通过这种方式,你可以在 YAML 测试用例中灵活地引用嵌套参数,这样可以提高测试用例的可读性和可维护性。使用占位符可以避免重复定义相同的参数,简化测试用例的管理。

标签:case,field,value,用例,pytest,details,test,data,yml
From: https://blog.csdn.net/weixin_44872675/article/details/144859054

相关文章

  • 【Rust自学】5.2. struct使用例(加打印调试信息)
    对不起我都写到第8章了才发现我忘记发这一篇了,现在补上,不过这可能导致专栏的文章顺序有一点问题,但也只能将就着了。喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)5.2.1.例子需求创建一个函数,计算长方形的面积,长......
  • 用例图
    用例图(UseCaseDiagram)是统一建模语言(UML,UnifiedModelingLanguage)中的一种图表,用于捕捉系统的行为需求,特别是从用户交互的角度来描述系统的功能性。它主要用来展示系统与外部参与者(如用户、其他系统或硬件设备)之间的交互,并标识这些参与者如何通过使用系统提供的服务来实现其......
  • Azure DevOps Server:从测试套件中移除测试用例返回414错误
    问题描述在AzureDevOpsServer(2022之前的多个版本)中,如果测试套件中包含的许多测试用例,当我们批量删除测试用例时,系统会返回414错误,导致不能删除测试用例。解决方案导致上述问题的根源是产品组在设计接口的时候,使用Url的参数传递测试用例ID,如果数据量不大,或者用例工作项ID较小,都不......
  • AIGC安全测试用例与代码
    提示词请以上结合业务需求,生成接口安全测试用例#角色:渗透测试专家#简介:专门从事安全渗透测试的专业人士,具备丰富的行业知识和测试经验,能够全面分析和评估系统的安全性。#技能:-渗透测试-漏洞扫描-安全评估-报告撰写-行业标准遵循#规则:-确保测试过程的合法性......
  • AIGC性能测试用例与脚本
    提示词您是系统架构师,结合以上需求描述与功能点与场景,请编写性能测试用例,按性能测试用例设计原则,输出表格性能测试用例设计原则设计性能测试用例时应遵循一定的原则,以确保测试的覆盖率和有效性。以下是一些关键的设计原则:1.可复现性原则:测试用例应设计得足够详细,以确保在不同......
  • bootstrap.yml与application.yml的区别
    善于观察的小伙伴能看到,为什么项目有的配置文件是bootstrap.yml,bootstrap.properties与application.yml。在springcloud分布式为服务中,作为配置中心来说启动顺序可以被优先加载的,基础配置可以事先写在bootstrap.yml比如:如下配置,要是写在nacos或者springcloud-config里......
  • 手写 PromiseA+ 实现,轻松通过 872 条用例
    手写Promise/A+实现,轻松通过872条用例规范参考:Promise/A+规范-中文版本测试工具:https://github.com/promises-aplus/promises-tests前言从接触Promise到现在,笔者经历了这么个过程:了解各种Promise规范,包括Promise/A+,但对其具体内容不甚了解。研究前人的Promi......
  • pytest 中 record_property的用法,记录用例结果
    一、需求介绍pytest的测试用例是不允许返回值的,即在用例的最后不要写return。但有时需要记录用例的测试结果,做统计测试,需要知道用例最后得到的具体的数值,这个时候就需要一个记录结果的方法。pytest提供了一个记录结果的——>record_property。二、record_property1.作用常用......
  • 19款顶级测试用例管理工具全面解析
    在当今数字化飞速发展的时代,软件测试的重要性日益凸显,而一款优秀的测试用例管理工具能够极大地提升测试效率与质量,帮助团队更高效地发现软件中的问题,确保产品的稳定性和可靠性。本文将为您全面解析19款顶级的测试用例管理工具,带您深入了解它们的特点与优势,助您在众多工具中找到最......
  • 用例图
    对于用例图来说我们需要了解的是什么叫用例图,构成用例图的要素,用例图有哪些重要的元素,各个用例之间的关系。当然最重要的是如何根据需求创建用例图。具体的创建通过一个简单的学生管理的例子说明创建的过程和例子。我的所有例子都是是使用Rose这个软件来画的,现在虽然有新的UML......