CSDN【top1】Pytest接口测试框架实战项目搭建

news2024/11/24 23:05:06

一、前言

  想想之前玩的框架,做的项目都是把数据用例冗余到一起的,不符合数据用例分离的思想,所以准备基于pytest搭建个测试框架,支持数据用例分离,接下来会用一系列文章逐步介绍整个框架是怎么搭建起来的。

二、项目结构概览

  •  conf:存放接口路径、域名等信息
  • data:1、存放.json文件(接口的请求头或请求体信息),即测试数据;2、存放.yaml文件(用户信息 比如账号密码)
  • log:日志文件
  • report:allure测试报告
  • testcase:测试用例
  • tools:常用方法
  • conftest.py:用于处理登录的文件
  • excute.py:用于执行项目的文件

三、照葫芦画瓢

1、新建python项目后,建个testcase文件夹

  /testcase下面创建个case,比如test_case1.py,里面随意写些内容,主要用于调试excute.py的执行是否正常,要注意的是.py文件要用test开头,因为用的是pytest框架。

2、新建excute.py,源码如下

  这里我就不演示了,执行成功后会在report文件夹下面生成测试报告

# -*- coding:utf-8 -*-
'''
@Date:2022/10/5  20:30
@Author:一加一
'''

import pytest
import os


if __name__ == '__main__':
    # pytest执行脚本并生成测试结果文件到report/tmp目录下
    pytest.main(['-s','--alluredir','report/tmp'])

    # 将report/tmp目录下的结果文件生成html类型的测试报告文件到report/html目录下
    # -o report/html --clean 是为了清空已有的测试报告再生成
    os.system(r'allure generate report/tmp -o report/html --clean')

Pytest接口测试框架实战项目搭建(二)—— tools公共方法封装

一、前言

  在项目中我们要频繁地用到log日志、request请求方法、断言等,所以我们可以把这些常用的方法封装成日志,下面将逐个文件讲述下,不会讲太细,但会把源码贴出来,还有一点要说的是公共方法如果看不懂的话可以不用纠结,知道用处以及清楚在实际业务中怎么调用公共方法就行了。

二、tools目录展示

  公共方法封装不会涉及到业务代码。

 三、common.py

  该文件需要导入封装好的日志方法,因为在接口请求时要把日志打印出来,后续脚本有问题可方便排查,tools.logger在下面会贴源码

  知识点一:注意.json()转换,根据实际业务需求进行封装

'''
@Date:2022/10/1  8:18
@Author:一加一
'''
import requests
from tools.logger import log # 导入封装的logger方法


class Common:
    '''封装通用接口'''

    #request-post请求,适用Content-Type:application/x-www-form-urlencoded,即表单传参,类似some=data&xxx=xxx 的形式
    def r_post_form(url,headers,data):
        log.info("请求参数为:{},{}".format(url,data))
        res = requests.post(url,headers=headers,data=data).json()
        log.info("响应结果为:{}".format(res))
        return res

    #request-post请求,适用'Content-Type': 'application/json',即json传参
    def r_post(url,headers,json):
        log.info("请求参数为:{},{}".format(url, json))
        res = requests.post(url,headers=headers,json=json).json()
        log.info("响应结果为:{}".format(res))
        return res

    # request-post请求,适用'Content-Type': 'application/json',即json传参——请求时不转换成json,适配s统一登录系统接口请求
    def r_s_post(url, headers, json):
        log.info("请求参数为:{},{}".format(url, json))
        res = requests.post(url, headers=headers, json=json)
        log.info("响应结果为:{}".format(res.text))
        return res

    #request-get请求
    def r_get(url,heasers,json):
        log.info("请求参数为:{},{}".format(url, json))
        res = requests.get(url,headers=heasers,json=json)
        log.info("响应结果为:{}".format(res))
        return res

    #断言:s统一登录系统的message=操作成功
    def assert_s_code_message(res_json):
        code = res_json['code']
        message = res_json['message']
        assert code == '200' and message == '操作成功'

    # 断言:业务系统的message=请求成功
    def assert_tg_code_message(res_json):
        code = res_json['code']
        message = res_json['message']
        assert code == '200' and message == '请求成功'

四、logger.py

1、logger.py源码如下

知识点一:

应该大多数的日志都是用的内置的logging库,但是该框架使用的是loguru库,所以需要安装下 pip3 install loguru

知识点二:

  1.os.path.abspath 作用: 获取当前脚本的完整路径

  2.os.path.dirname 功能:去掉文件名,返回目录

  3.os.path.join() 连接 两个或更多的路径名组件

知识点三:

  .format():用于格式化方法,即用来控制字符串和变量的显示效果,增强了字符串格式化的功能

'''
@Date:2022/9/30  20:49
@Author:一加一
'''

# -*- coding:utf-8 -*-
from loguru import logger
from datetime import datetime
from conf.setting import *


class Logger:
    '''
    loguru封装日志记录器
    '''

    def __new__(cls, *args, **kwargs):
        '''
        1.os.path.abspath    作用: 获取当前脚本的完整路径
        2.os.path.dirname 功能:去掉文件名,返回目录
        3.os.path.join() 连接两个或更多的路径名组件
        :param args:
        :param kwargs:
        :return:
        '''

        log_name = datetime.now().strftime("%Y-%m-%d")    # 以时间命名日志文件,格式为"年-月-日"
        sink = os.path.join(LOG_PATH,"{}.log".format(log_name)) # 日志记录文件路径
        level = "DEBUG"  # 记录的最低日志级别为DEBUG
        encoding = "utf-8"  # 写入日志文件时编码格式为utf-8
        enqueue = True # 多线程多进程时保证线程安全
        rotation = "500MB" # 日志文件最大为500MB,超过则新建文件记录日志
        retention = "1 week"    # 日志保留时长为一星期,超时则清除
        logger.add(
            sink=sink, level=level, encoding=encoding,
            enqueue=enqueue, rotation=rotation, retention=retention
        )
        return logger

log = Logger()

 2、直接执行该文件,会在log文件夹生成一个.log文件,如下图

 3、该文件需要导入目录文件设置,即conf.setting,主要用于读取LOG_PATH

'''
@Date:2022/10/3  20:56
@Author:一加一
'''

import os

'''管理文件存放路径'''

BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

REPORT_PATH = os.path.join(BASE_PATH,'report') #报告存放的目录

CASE_PATH = os.path.join(BASE_PATH,'testcase') #测试用例的目录

CASE_DATA_PATH = os.path.join(BASE_PATH,'data') #测试数据的目录

LOG_PATH = os.path.join(BASE_PATH,"log")

CONFIG_FILE = os.path.join(BASE_PATH,'conf','config.ini') #配置文件的目录

LOGIN_DATA_YAML_FILE = os.path.join(BASE_PATH, 'data', 'userInfo.yaml') #配置文件的目录

五、operate_config.py

1、该文件主要是读取配置文件,即读取conf/config.ini,这里先贴上operate_config.py源码,后面用到该方法会提及

  读取配置文件主要是为了适配公司的多个测试环境,如若有需要切换环境,则直接改配置文件即可

# -*- coding:utf-8 -*-

import yaml
import configparser
from conf.setting import CONFIG_FILE,LOGIN_DATA_YAML_FILE

def get_yaml(goal):
    with open(LOGIN_DATA_YAML_FILE, encoding='utf-8') as f:
        yaml_log = yaml.load(f, Loader=yaml.FullLoader)
    goal_list = yaml_log.keys()
    if goal in goal_list:
        return yaml_log[goal]
    else:
        print('不存在的配置')

class OperateConfig:
    def __init__(self):
        self.config = configparser.ConfigParser()  # 调用外部的读取配置文件的方法
        self.config.read(CONFIG_FILE, encoding='GBK')

    def get_node_value(self,node, name):
        value = self.config.get(node, name)
        return value

    def set_node_value(self,section,node,name):
        """写入配置文件"""
        self.config.set(section,node,name)  # 修改指定section 的option
        self.config.write(open(CONFIG_FILE, 'w'))

2、conf/config.ini源码如下

  因为涉及到公司敏感信息,所以用xxx代替了,配置文件主要存储登录系统和业务系统的接口域名

[ENV]
env = QA1

[QA1]
y_api_url = https://qa1-api.y.cn
s_api_url = https://qa-s-xxx.cn

[QA2]
y_api_url = https://qa2-api.y.cn
s_api_url = https://qa-s-xxx.cn

六、operate_json.py

1、该文件主要封装对.json文件的读取或修改操作,用于接口请求时要读取请求体或请求头,又或者往请求体里插入变量字段,源码如下

'''
@Date:2022/10/2  8:18
@Author:一加一
'''

import json
import os
from conf.setting import CASE_DATA_PATH

data_path = os.path.join(CASE_DATA_PATH, "test.json")

class OperationJson:
    def __init__(self, file_names=None):
        if file_names:
            self.file_name = file_names
        else:
            self.file_name = data_path

    def open_json(self):
        """打开json文件
        :return:返回json文件数据
        """
        with open(self.file_name, 'r',encoding='utf-8') as fp:
            data = json.load(fp)
            return data
            fp.close()

    def key_get_data(self, key1, key2=None):
        """通过key值获取数据
        :param key1:
        :param key2:
        :return:
        """
        if key2 is None:
            data = self.open_json()[key1]
        else:
            data = self.open_json()[key1][key2]
        return data

    def write_data(self, w_data, key1, key2=None):
        """修改json数据
        :param w_data: 修改后的数据
        :param key1: 要修改的键值1
        :param key2: 要修改的键值2
        :return:
        """
        data_dict = self.open_json()
        if key2 is None:
            data_dict[key1] = w_data
        else:
            data_dict[key1][key2] = w_data
        with open(self.file_name, 'w',encoding='utf-8') as fp:
            fp.write(json.dumps(data_dict, ensure_ascii=False, sort_keys=False, indent=2))  # 对写入的json数据进行格式化
            fp.close()

    def write_datas(self, w_data, key1, key2,key3=None):
        """修改json数据
        :param w_data: 修改后的数据
        :param key1: 要修改的键值1
        :param key2: 要修改的键值2
        :param key3: 要修改的键值3
        :return:
        """
        data_dict = self.open_json()
        if key3 is None and key2 is None:
            data_dict[key1] = w_data
        elif key3 is None and key2 is not None:
            data_dict[key1][key2] = w_data
        else:
            data_dict[key1][key2][key3] = w_data
        with open(self.file_name, 'w',encoding='utf-8') as fp:
            fp.write(json.dumps(data_dict, ensure_ascii=False, sort_keys=False, indent=2))  # 对写入的json数据进行格式化
            fp.close()


if __name__ == "__main__":
    #file_name = "test.json"
    a = OperationJson()
    b = a.key_get_data("login_header")
    #print(type(b))
    print(b)

 2、文件里加了调试代码,直接执行该文件后效果如下图

调试代码说明:

1)定义数据路径变量
data_path = os.path.join(CASE_DATA_PATH, "test.json")
2)文件作为脚本直接执行,调用OperationJson的key_get_data方法获取test.json里名为“login_header”的josn串数据
if __name__ == "__main__":
    a = OperationJson()
    b = a.key_get_data("login_header")
    print(b)

 3、如果要修改json数组的话,需要加下标,如下

重点:学习资料  

600g的学习资料懂的都懂

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

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

相关文章

[附源码]计算机毕业设计springboot高校体育场馆管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

TMA三均线股票期货高频交易策略的R语言实现

趋势交易策略是至今应用最广泛以及最重要的投资策略之一,它的研究手段种类繁多,所运用的分析工具也纷繁复杂,其特长在于捕捉市场运动的大方向。股指期货市场瞬息万变,结合趋势分析方法,量化投资策略能够得到更有效的应…

项目使用smart-doc+Torna自动化创建api文档

首先部署Torna,我这里是用docker部署的 准备工作:1 docker 环境 2 torna 所需的sql脚本(可以去github 找最新的) DROP TABLE IF EXISTS compose_additional_page; CREATE TABLE IF NOT EXISTS compose_additional_page (id bigi…

jupyter使用教程及python语法基础

前言 上回说到搭建jupyter环境,今天的文章主要就是熟悉jupyter上的基本操作,以及python的一些基础语法。 正文 1、熟悉jupyter界面使用方法 通过命令行进入jupyter后,选择python3。 进去之后就是如下界面,要熟悉以下操作。当…

SAP ABAP——数据类型(二)【TYPES自定义数据类型详解】

💬个人网站:【芒果个人日志】​​​​​​ 💬原文地址:SAP ABAP——数据类型(二)【TYPES自定义数据类型详解】 - 芒果个人日志 (wyz-math.cn) 💂作者简介: THUNDER王,一名…

python学习笔记(11)---(模块与包)

第九章 模块与包 1.模块(modules) (1)概念:将实现某一特定功能的代码放置在一个文件中,以便于其他程序进行导入使用,可以避免函数名、变量名的冲突,该文件称为模块,拓展…

RtspServer之LibRtsp解决闪退 新增鉴权(用户名密码登录)

编程语言:C 目标平台:arm(hi3519)注:因为代码是纯C语言按道理可以移植到各种平台 基础库:librtsp(存在功能补全,有一定的bug) 因为项目需求需要在海思平台实现IPC…

C++ Reference: Standard C++ Library reference: Containers: list: list: crend

C官网参考链接&#xff1a;https://cplusplus.com/reference/list/list/crend/ 公有成员函数 <list> std::list::crend const_reverse_iterator crend() const noexcept; 返回反向结束的常量反向迭代器 返回一个const_reverse_iterator&#xff0c;指向容器中第一个元素…

领悟《信号与系统》之 采样定理

采样定理采样定理一、采样定理结论二、奈奎斯特间隔和频率计算公式及例题&#xff1a;三、信号自然采样&#xff08;脉冲采样&#xff09;四、信号理想采样&#xff08;冲激采样&#xff09;采样定理 连续时间信号也叫模拟信号。在一定条件之下&#xff0c;模拟信号可以用该信…

LDAP客户端操作方法

本文章简单介绍LDAP Admin客户端的使用方法&#xff0c;客户端工具地址为&#xff1a; https://download.csdn.net/download/u013896064/87209312 1、前提 我使用的是Ubuntu的虚拟机安装了一个LDAP服务&#xff0c;初始化完成并配置好密码&#xff0c;本次例子里面我使用的U…

nodejs+vue音乐网站与分享平台

目 录 摘 要 I 1 绪论 1 1.1研究背景 1 1.2研究现状 1 1.3研究内容 2 2 系统关键技术 3 2.1 Spring Boot框架 3 2.2 JAVA技术 3 2.3 MYSQL数据库 4 2.4 B/S结构 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2经济可行性…

Windows OpenGL 图像色彩替换

目录 一.OpenGL 图像色彩替换 1.原始图片2.效果演示 二.OpenGL 图像色彩替换源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 OpenGL…

[附源码]计算机毕业设计JAVA网上花店系统

[附源码]计算机毕业设计JAVA网上花店系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

SpringBoot基于若依项目工时统计成本核算管理源码带文字教程

该系统是前后端分离的架构&#xff0c;前端使用Vue2&#xff0c;后端使用SpringBoot2。 技术架构 技术框架&#xff1a;SpringBoot2.0.0 Mybatis1.3.2 Shiro swagger-ui jpa lombok Vue2 Mysql5.7 运行环境&#xff1a;jdk8 IntelliJ IDEA maven 宝塔面板 本地搭建文…

MySQL数据库行级锁之间隙锁、临键锁

间隙锁 默认情况下&#xff0c;InnoDB在 REPEATABLE READ事务隔离级别运行&#xff0c;InnoDB使用 next-key 锁进行搜索和索引扫描&#xff0c;以防止幻读。 索引上的等值查询(唯一索引)&#xff0c;给不存在的记录加锁时, 优化为间隙锁 。索引上的等值查询(非唯一普通索引)&…

数据字典功能

我们在项目中会有很多的下拉框,这些下拉框都有一个特点,就是键值对的存在 实现方案: 直接硬编码写在html代码中, 缺点:新增修改需要修改代码为每个下拉框都设计一个表&#xff0c;然后提供CRUD功能 , 缺点 : 很多表,很多重复的CRUD代码使用数据字典的方式 ,使用字典类型表和字…

CTFHUB-web-SQL注入

整数型注入 字符型注入 得到数据库名 sqli http://challenge-f7a63a00793e62c6.sandbox.ctfhub.com:10800/?id-1 union select 1,database() 爆sqli数据库的数据表 爆flag表的所有列&#xff1a; http://challenge-f7a63a00793e62c6.sandbox.ctfhub.com:10800/?id-1 union s…

[Azkaban] No active executors found分析

启动AzkabanWebServer报如下错误: 点击进入 ActiveExecutors.setupExecutors发现调用的是 loadExecutors()继续深入 private ImmutableSet<Executor> loadExecutors() throws ExecutorManagerException {logger.info("Initializing executors from database.&q…

window 下 达梦数据库的备份和还原

DM 提供的各种工具进行备份还原与恢复的操作&#xff0c;包括 DIsql工具、DMRMAN 工具、图形化客户端管理工具 MANAGER 和 CONSOLE。 DIsql 工具用于执 行联机的数据备份与数据还原&#xff0c;包括数、归档备份据库备份、表空间备份与还原、表备份与 还原&#xff1b; DMRMA…

docker-compose安装nacos

文章目录一、安装nacos1.docker-compose.yml2.nacos数据库表结构3.docker-compose 构建运行4.检查nacos日志6.测试访问&#xff1a;TODO:二、nacos为注册中心&#xff1a;项目测试1.新建maven项目&#xff1a;2.配置pom.xml3.配置application.properties4.激活服务发现客户端5.…