pytestx重新定义接口框架设计

news2024/12/27 14:54:28

概览

脚手架:

目录:

用例代码:

"""
测试登录到下单流程,需要先启动后端服务
"""

test_data = {
    "查询SKU": {
        "skuName": "电子书"
    },
    "添加购物车": {
        "skuId": 123,
        "skuNum": 2
    },
    "下单": {
        "orderId": 222,
        "payAmount": "0.2"
    },
    "支付": {
        "skuId": 123,
        "price": 0.1,
        "skuNum": 2,
        "totalPrice": 0.2
    },
}
case_vars = dict()


def test(http, login_headers, file_data):
    # 搜索商品
    url = file_data["domain"] + "/api/tasks/mock/searchSku"
    body = test_data["查询SKU"]

    response = http("get", url=url, headers=login_headers, params=body)
    assert response.status_code < 400

    case_vars["skuId"] = response.jsonpath("$.skuId")
    case_vars["skuPrice"] = response.jsonpath("$.price")

    # 添加购物车
    url = file_data["domain"] + "/api/tasks/mock/addCart"
    body = test_data["添加购物车"]
    body["skuId"] = case_vars["skuId"]

    response = http("post", url=url, headers=login_headers, json=body)
    assert response.status_code < 400

    case_vars["skuNum"] = response.jsonpath("$.skuNum")
    case_vars["totalPrice"] = response.jsonpath("$.totalPrice")

    # 下单
    url = file_data["domain"] + "/api/tasks/mock/order"
    body = test_data["下单"]
    body["skuId"] = case_vars["skuId"]
    body["price"] = case_vars["skuPrice"]
    body["skuNum"] = case_vars["skuNum"]
    body["totalPrice"] = case_vars["totalPrice"]

    response = http("post", url=url, headers=login_headers, json=body)
    assert response.status_code < 400

    case_vars["orderId"] = response.jsonpath("$.orderId")

    # 支付
    url = file_data["domain"] + "/api/tasks/mock/pay"
    body = test_data["支付"]
    body["orderId"] = case_vars["orderId"]

    response = http("post", url=url, headers=login_headers, json=body)
    assert response.status_code < 400
    assert response.jsonpath("$.success") == "true"

页面下载脚手架

启动平台前后端服务后,从页面下载脚手架,平台会拉取开源项目tep-project最新代码,打成压缩包,生成下载文件,弹窗下载。

备注:tep startproject demo使用的已封版的1.0.0版本,新框架请访问开源项目tep-project,或者开源平台pytestx

精简目录

目录直观上非常精简,得益于去掉了环境变量、函数等目录,聚焦三大目录:

  • fixtures

  • resources

  • tests

重度使用fixture

fixture原本只能在conftest定义,借助pytest插件扩展识别fixtures目录:

#!/usr/bin/python
# encoding=utf-8

"""
@Author  :  dongfanger
@Date    :  8/14/2020 9:16 AM
@Desc    :  插件
"""
import os

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
RESOURCE_PATH = os.path.join(BASE_DIR, "resources")


def fixture_paths():
    """
    fixture路径,1、项目下的fixtures;2、tep下的fixture;
    :return:
    """
    _fixtures_dir = os.path.join(BASE_DIR, "fixtures")
    paths = []
    # 项目下的fixtures
    for root, _, files in os.walk(_fixtures_dir):
        for file in files:
            if file.startswith("fixture_") and file.endswith(".py"):
                full_path = os.path.join(root, file)
                import_path = full_path.replace(_fixtures_dir, "").replace("\\", ".")
                import_path = import_path.replace("/", ".").replace(".py", "")
                paths.append("fixtures" + import_path)
    return paths


pytest_plugins = fixture_paths()  # +[其他插件]

conftest.py的fixture全部转移至fixtures目录定义。

公共函数消失,统统通过fixture来实现,依赖注入。

包括requests.request封装

#!/usr/bin/python
# encoding=utf-8

import decimal
import json
import time

import jsonpath
import pytest
import requests
import urllib3
from loguru import logger
from requests import Response

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class TepResponse(Response):
    """
    二次封装requests.Response,添加额外方法
    """

    def __init__(self, response):
        super().__init__()
        for k, v in response.__dict__.items():
            self.__dict__[k] = v

    def jsonpath(self, expr):
        """
        此处强制取第一个值,便于简单取值
        如果复杂取值,建议直接jsonpath原生用法
        """
        return jsonpath.jsonpath(self.json(), expr)[0]


@pytest.fixture(scope="session")
def http():
    def inner(method, url, **kwargs):
        template = """\n
    Request URL: {}
    Request Method: {}
    Request Headers: {}
    Request Payload: {}
    Status Code: {}
    Response: {}
    Elapsed: {}
    """
        start = time.process_time()
        response = requests.request(method, url, **kwargs)  # requests.request原生用法
        end = time.process_time()
        elapsed = str(decimal.Decimal("%.3f" % float(end - start))) + "s"
        headers = kwargs.get("headers", {})
        kwargs.pop("headers")
        payload = kwargs
        log = template.format(url, method, json.dumps(headers), json.dumps(payload), response.status_code,
                              response.text,
                              elapsed)
        logger.info(log)
        return TepResponse(response)

    return inner

只是名字换成了http:

http("post", url=url, headers=login_headers, json=body)

因为request是fixture保留关键字。

数据分离

数据支持从文件读取,当然这也是一个fixture:

import json
import os

import pytest
import yaml

from conftest import RESOURCE_PATH


class Resource:
    def __init__(self, path):
        self.path = path

    def get_data(self):
        file_type = self._get_file_type()
        if file_type in [".yml", ".yaml", ".YML", "YAML"]:
            return self._get_yaml_file_data()
        if file_type in [".json", ".JSON"]:
            return self._get_json_file_data()

    def _get_file_type(self):
        return os.path.splitext(self.path)[-1]

    def _get_yaml_file_data(self):
        with open(self.path, encoding="utf8") as f:
            return yaml.load(f.read(), Loader=yaml.FullLoader)

    def _get_json_file_data(self):
        with open(self.path, encoding="utf8") as f:
            return json.load(f)


@pytest.fixture(scope="session")
def file_data():
    file_path = os.path.join(RESOURCE_PATH, "demo.yaml")
    return Resource(file_path).get_data()

也可以放在用例文件中。为什么?“只改数据不动用例代码”,如果没有这种情况,请毫不犹豫将数据放到用例文件中,不要从excel、yaml读取数据,增加无意义的中间转换。从流量回放替代自动化的趋势来看,数据和用例作为整体来维护和运行,会越来越普遍。在使用低代码平台时,测试数据也是写在用例里面,只有少量的公共信息,会抽出来作为变量。测试技术在发展,只有符合当前实际使用需要的,才是最好的。

用例设计

约定大于配置:

  • 数据区域、用例区域分离

  • 用例由步骤组成

  • 步骤分为前置条件、用例体、断言、数据提取

数据区域,接口入参、用例中间变量等:

test_data = {
    "查询SKU": {
        "skuName": "电子书"
    },
    "添加购物车": {
        "skuId": 123,
        "skuNum": 2
    },
    "下单": {
        "orderId": 222,
        "payAmount": "0.2"
    },
    "支付": {
        "skuId": 123,
        "price": 0.1,
        "skuNum": 2,
        "totalPrice": 0.2
    },
}
case_vars = dict()

用例定义,test函数,fixture引用:

def test(http, login_headers, file_data):

步骤:

# 搜索商品
url = file_data["domain"] + "/api/tasks/mock/searchSku"
body = test_data["查询SKU"]

response = http("get", url=url, headers=login_headers, params=body)
assert response.status_code < 400

case_vars["skuId"] = response.jsonpath("$.skuId")
case_vars["skuPrice"] = response.jsonpath("$.price")

每个用例文件单独可运行。不存在用例依赖,复用步骤封装为fixture,以依赖注入方式在各用例中复用。用例一定要解耦,这在任务调度时非常重要。

总结,重新定义目录,重新定义用例组织,重新定义fixture,减少过程代码,专注于用例编写,轻松上手pytest。

跟着pytestx学习接口自动化框架设计,更简单,更稳定,更高效。

https://github.com/dongfanger/pytestx

https://gitee.com/dongfanger/tep-project

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/920861.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

异步I/O优化Python代理程序性能

作为一名爬虫程序员&#xff0c;你是否曾经遇到过需要处理大量网络请求的情况&#xff1f;你是否想要提高你的Python代理程序的性能&#xff0c;让它更快、更高效&#xff1f;别担心&#xff0c;我来给你分享一些关于异步I/O如何优化Python代理程序性能的实用知识。 首先&…

云计算技术应用专业实训室建设方案

一、 云计算技术应用系统概述 云计算技术是一种基于互联网的计算模式&#xff0c;通过将计算资源&#xff08;如服务器、存储、数据库、网络、软件等&#xff09;提供为一种服务&#xff0c;使用户能够按需获取和使用这些资源&#xff0c;而无需拥有和管理实际的物理设备。云计…

使用RAMMap+PoolMon分析Windows内存使用异常问题

1 RAMMap和PoolMon工具简介 RAMMap和PoolMon都是微软Sysinternals的工具&#xff0c;前者可以从使用类型、页列表、进程、文件、优先级&#xff0c;以及物理地址来检查内存的使用情况&#xff0c;但是无法检查尚未提交和分页的进程内存使用情况&#xff1b;后者可以是作为RAMM…

使用haproxy搭建web架构

haproxy HAProxy是一个免费的负载均衡软件&#xff0c;可以运行于大部分主流的Linux操作系统上。 HAProxy提供了可以在七层和四层两种负载均衡能力&#xff0c;它可以提供高可用性、负载均衡、及基于TCP和HTTP应用的代理。适用于负载大的Web站点&#xff0c;在运行在硬件上可…

使用 SQLStudio 进行数据库管理并通过 Docker Compose 进行部署

在现代软件开发中&#xff0c;数据库管理是一个至关重要的环节。SQLStudio 是一个强大的工具&#xff0c;可以帮助开发人员轻松管理数据库&#xff0c;现在改名成SQLynx&#xff0c;我们用的是旧的镜像&#xff0c;本文还是用SQLStudio这个名称。同时&#xff0c;使用 Docker C…

Qt双击某一文件通过自己实现的程序打开,并加载文件显示

双击启动 简述方法一方法二注意 简述 在Windows系统中&#xff0c;双击某类扩展名的文件&#xff0c;通过自己实现的程序打开文件&#xff0c;并正确加载及显示文件。有两种方式可以到达这个目的。 对于系统不知道的扩展名的文件&#xff0c;第一次打开时&#xff0c;需要自行…

ModaHub魔搭社区:WinPlan企业经营垂直大模型数据建模(二)

目录 维度模版管理 录入维度数据 经营指标 创建经营指标 经营指标管理 维度模版管理 创建维度后,可在维度库的左侧栏展示全部启用中的维度,你也可以再次编辑维度模版;如不再需要该维度,可停用,停用后可在停用管理里重新启用或删除。 1)停用:维度停用后,不会出现在…

3个方法学会:恢复指定人微信聊天记录

和朋友吵架后一怒之下把她微信删除了&#xff0c;和好之后又想把聊天记录恢复回来。网上很多方法都是直接恢复所有的微信聊天记录&#xff0c;我想问问&#xff0c;可以只恢复这个朋友的聊天记录吗&#xff1f;有什么方法吗&#xff1f; 朋友之间有一些小摩擦、小争吵是很正常的…

MyCAT命令行监控

9066端口 &#xff0c;用mysql命令行连接 Mysql –utest –ptest –P9066 show help 可显示所有相关管理命令 显示后端物理库连接信息&#xff0c;包括当前连接数&#xff0c;端口 Show backend Show connection 显示当前前端客户端连接情况&#xff0c;已经网络流量信息、…

JavaFX:根据控件内容显示tooltip

如题。当控件为空&#xff0c;没有内容时显示tooltip&#xff0c;反之不显示。示例如下&#xff1a; package ch06;import javafx.application.Application; import javafx.application.Platform; import javafx.beans.value.ObservableValue; import javafx.geometry.VPos; i…

如何将下载的安装包导入PyCharm

1. 下载安装包 这里以pyke为例。下载好之后解压缩&#xff0c;然后放入/Lib/site-packages/pyke-1.1.1 2. 打开PyCharm的终端进行安装 python setup.py install 3. 安装好之后导入即可使用 import pyke

Linux搭建SSLVpn

安装http、ssl服务 编辑http配置文件 修改http的136行&#xff0c;276行以及990行 1、136行将监听端口注释 2、276行和990行修改为自己的域名和要访问的端口 修改http文档最后那部分 新添ssl配置信息&#xff0c;将端口修改为443&#xff08;截图错了server.key应该放在/etc/…

单片机的串口通信

今天&#xff0c;完整地总结一下普中科技的单片机的串口通信的硬件与编程&#xff0c;记录一下以后如果需要也比较方便捡起来。 单片机的串口部分的电路图。开发板上集成了 1 个串口通信电路&#xff0c;是 USB 转串口模块&#xff0c;它既可下载程序也可实现串口通信功能。 对…

【面试题】UDP和TCP有啥区别?

UDP UDP协议全称是用户数据报协议&#xff0c;在网络中它与TCP协议一样用于处理数据包&#xff0c;是一种无连接的协议。在OSI模型中&#xff0c;在第四层——传输层&#xff0c;处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点&#xff0c;也就…

【C++STL基础入门】vector增、删操作

文章目录 前言一、vector迭代器1.1 定义vector迭代器1.2 注意点 二、vector增函数2.1 尾添加示例代码&#xff1a; 2.2 中间添加2.3 效率问题 三、vector删除操作3.1 尾删除3.2 删除指定元素3.3 删除所有 总结 前言 一、vector迭代器 1.1 定义vector迭代器 vector<int>…

30款教育学习类应用评测体验报告

为方便开发者更好地衡量APP在同类产品中的表现和竞争力&#xff0c;有针对性地进行产品优化&#xff0c;软件绿色联盟策划了垂类APP评测体验专题&#xff0c;目前已发布了天气类APP和小说类APP评测体验报告&#xff0c;本期将对教育学习类APP围绕绿标五大标准进行体验评测&…

流程控制之条件判断

一、if单分支结构 准备知识&#xff1a; 查看系统内存&#xff1a;free指令 -m表示以MB的大小显示 mem是系统内存&#xff0c;swap是虚拟内存&#xff0c;需要将系统剩余内存大小过滤出来&#xff0c;之后与100M对比 也可以用awk指令 使用正则表达式过滤&#xff0c;以空格…

vue 简单实验 自定义组件 component

1.代码 <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"components-demo"><button-counter></button-counter> </div> <script> // 创建一个Vue 应用 const ap…

【MySQL】1、MySQL数据库的基本概念

数据库的基本概念 1.数据 1&#xff09;描述事物的符号记录称为数据&#xff1b;数字&#xff0c;文字&#xff0c;图形&#xff0c;图像&#xff0c;声音&#xff0c;档案记录等都是数据 2&#xff09;数据是以“记录”的形式按照统一的格式进行存储的&#xff0c;而不是杂乱…

c++都补了c语言哪些坑?

目录 1.命名空间 1.1 定义 1.2 使用 2.缺省参数 2.1 概念 2.2 分类 3.函数重载 4.引用 4.1 概念 4.2 特性 4.3 常引用 4.4 引用和指针的区别 5.内联函数 1.命名空间 在 C/C 中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将…