使用python+pytest+requests完成自动化接口测试(包括html报告的生成和日志记录以及层级的封装(包括调用Json文件))

一、API的选择

我们进行接口测试需要API文档和系统,我们选择JSONPlaceholder免费API,因为它是一个非常适合进行接口测试、API 测试和学习的工具。它免费、易于使用、无需认证,能够快速帮助开发者模拟常见的接口操作(增、删、改、查)。尤其对于我你们学习接口测试的初学开发者来说,它是一个理想的选择。

注意:这个API网站当我们发送请求时他不会真的实现我们的请求,他只会会虚拟实现我们的请求,并不会真的修改服务器数据。

二、环境的准备

在开始编写测试代码之前,我们需要先配置好环境。这包括安装所需的Python库并准备好相应的配置文件。

安装Python依赖

首先,确保你已经安装了Python。然后使用pip来安装所需的库。

pip install requests pytest

三、利用requests发送增删改查请求并用pytest测试用例管理框架管理测试用例

在接口自动化测试中,我们需要通过HTTP协议与服务器进行交互。requests库提供了多种方法来发送HTTP请求,常用的有GETPOSTPUTDELETE等。接下来,我们将分别讲解如何使用requests发送这些请求。

数据准备:

首先我们先确定我们的文件层级关系

project/
│
├── init.py         #里面存放一些初始化数据如URL   
├── test_practice.py   测试用例主要代码书写位置
test_log.log        # 日志文件(这里我使用vscode写代码所以我把日志文件放在了和项目目录同级,
#pyCharm可能需要和test_practice.py同级放置)
├── data_test.json  #存放参数化测试数据

init.py文件中我们放入url和单次运行测试用例所需的如下数据:

url="http://jsonplaceholder.typicode.com/posts/"

#data_updata为修改请求时用的数据
data_updata={
    "id":1,
    "title": 'updata',
    "body": 'bar',
    "userId": 1
  }

#data_add为增加请求时用的数据
data_add={
    "id":1,
    "title": 'updata',
    "body": 'bar',
    "userId": 1
  }

data_test.json文件中我们放入参数化执行测试用例时所需的数据 ,参数化时我们批量加入三组数据,201为响应状态码用于后期断言(就是判断是否请求成功)时用,如过返回的状态码是201则为成功,不同的请求拥有不同的响应状态码,都是由API文档规定的。

{"data":[
    [{"title": "updata1","body": "bar","userId": 1},201],
    [{"title": "updata2","body": "bar","userId": 2},201],
    [{"title": "updata3","body": "bar","userId": 3},201]
    ]
}

1、get查询

用requests进行接口测试其实很简单,就是头文件包含requests然后,调用它的不同方法,输入不同参数,它就会返回一个结果他就是响应报文,我们定义一个变量接收受它,然后用报文的不同数据进行断言或查看来判断接口是否正常。

# 查询全部数据
def test_get_all_information():
    #init是文件名,init.url表示该文件下的url变量
    res=requests.get(init.url)
    #输入他的响应体报文
    print(res.json())
    assert res.status_code==200


# 查询指定数据
def test_get_information():
    #url的书写方法可以用基本的字符串拼接
    res=requests.get(init.url+"/100")
    print(res.json())
    assert res.status_code==200

2、post新增

这一块包括发送一个post请求和批量发送post请求,post请求时我们需要传入我们要添加的数据这和利用postman进行接口测试是一样的,这里是以函数参数的方式发送数据的。

批量发送post请求时我们需要@pytest.mark.parametrize()来修饰测试方法。@pytest.mark.parametrize()它的参数由两部分构成,一是你需要传给下面测试方法的参数我们用"参数,参数"这种形式来书写,另一部分是我们要传入的测试数据,测试数据里的数据和第一部分里定义的参数一一对应,例如我的第一部分定义的参数有两个一个是新增请求的数据,一个是响应状态码,我的数据就是 [{"title": "updata1","body": "bar","userId": 1},201],中括号里的是新增请求的数据,201是状态码。然后其他的就和单个进行post请求一模一样了,不同的是断言时我们不用在直接写201,而是用code参数代替。这其实也是一个封装。

# 添加数据
def test_post_information():
    res=requests.post(init.url,data=data_add)
    print(res.json())
    assert res.status_code==201


# 参数化批量添加数据
@pytest.mark.parametrize("Placeholder_data,code",test_data)
def test_many_post_information(Placeholder_data,code):
    res=requests.post(init.url,data=Placeholder_data)
    print(res.json())
    assert res.status_code==code
    #assert res.json()==Placeholder_data

你运行完数据后会发现返回的数据 res.json()和我们传入的数据不一致,这是因为服务器对我们的数据做了自适应修改,我们传入的数据可能不利于它存储所以他会做改变,不同服务器有不同特性,JSONPlaceholder服务器就会在我们发送put修改请求时给我们返回的数据加一个字段id。

3、put修改

put修改和post基本一致,也需要我们发送修改新数据,不同的一点是你需要指定你要修改的数据是那个,你可以在url上+"/1"来指定你所要修改的是id为1的参数。

# 修改数据
def test_put_information():
  res=requests.put(init.url+"/1",data=test_data)
  
  print(res.status_code)
  assert res.status_code==200
  print(res.json())
  #print(type(res.json()["id"]))
  #print(type(test_data[0][0]["userId"]))
  # assert res.json()==test_data

4、delete删除,

delete请求方法不需要我们传入数据。如何响应状态码为200,说明我们删除成功。

# 删除数据
def test_delete_information():
    res=requests.delete(init.url+"/99")
    assert res.status_code==200

四、日志的生成

在生成日志时我们需要包含logging库,然后定义一个setup_logging函数在初始化日志的等级,日志的生成格式,以及日志问价的文件名位置,打开方式,以及编码方式。然后调用该函数在执行测试用例之前。我们还需要在不同的请求方法中通过使用logging.info来写入日志数据,例如我们在assert res.status_code==200后面加上logging.info("GET 请求成功"),就表示当断言成功完成时我们在日志种写入"GET 请求成功"的数据。如果你想你的日志详细些,就多加入一些数据输出,但是一般我们日志需要写的详细一点,每一步都写日志有助于后期我们排查问题。

import pytest
import requests
import json
import init
import logging

# 配置日志
def setup_logging():
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler("test_log.log",mode='a',encoding="utf-8"),
            # logging.StreamHandler()
        ]
    )

setup_logging()


data=json.load(open("./data_test.json",mode="r",encoding="utf-8"))

# 数据准备
# print(type(data))
test_data=data["data"]
# print(test_data)
data_updata=init.data_updata
data_add=init.data_add


# 查询全部数据
def test_get_all_information():
    logging.info(f"发送 GET 请求到 {init.url}")
    res=requests.get(init.url)
    # 记录请求和响应的内容
    logging.info(f"请求URL: {res.request.url}")
    logging.info(f"响应状态码: {res.status_code}")
    logging.info(f"响应数据: {res.text[:200]}")  # 仅输出前200个字符
    print(res.json())
    assert res.status_code==200
    logging.info("GET 请求成功")

# 参数化批量添加数据
@pytest.mark.parametrize("Placeholder_data,code",test_data)
def test_many_post_information(Placeholder_data,code):
    logging.info(f"发送 POST 请求到 {init.url},数据:{Placeholder_data}")
    res=requests.post(init.url,data=Placeholder_data)
    logging.info(f"请求URL: {res.request.url}")
    logging.info(f"请求数据: {Placeholder_data}")
    logging.info(f"响应状态码: {res.status_code}")
    logging.info(f"响应数据: {res.json()}")
    print(res.json())
    assert res.status_code==code
    logging.info("POST 请求成功")

# 添加数据
def test_post_information():
    logging.info(f"发送 POST 请求到 {init.url},数据:{data_add}")
    res=requests.post(init.url,data=data_add)
    logging.info(f"请求URL: {res.request.url}")
    logging.info(f"请求数据: {data}")
    logging.info(f"响应状态码: {res.status_code}")
    logging.info(f"响应数据: {res.json()}")
    print(res.json())
    assert res.status_code==201
    logging.info("POST 请求成功")

# 修改数据
def test_put_information():
    logging.info(f"发送 PUT 请求到 {init.url},数据:{test_data}")
    res=requests.put(init.url+"/1",data=test_data)
    logging.info(f"请求URL: {res.request.url}")
    logging.info(f"请求数据: {test_data}")
    logging.info(f"响应状态码: {res.status_code}")
    logging.info(f"响应数据: {res.json()}")
    print(res.status_code)
    assert res.status_code==200
    logging.info("PUT 请求成功")
    # print(res.json())
    # print(type(res.json()["id"]))
    print(type(test_data[0][0]["userId"]))
    # assert res.json()==test_data

# 查询指定数据
def test_get_information():
    logging.info(f"发送 GET 请求到 {init.url}")
    res=requests.get(init.url+"/100")
    logging.info(f"请求URL: {res.request.url}")
    logging.info(f"响应状态码: {res.status_code}")
    logging.info(f"响应数据: {res.json()}")
    print(res.json())
    assert res.status_code==200
    logging.info("GET 请求成功")

# 删除数据
def test_delete_information():
    logging.info(f"发送 DELETE 请求到 {init.url}")
    res=requests.delete(init.url+"/99")
    logging.info(f"请求URL: {res.request.url}")
    logging.info(f"响应状态码: {res.status_code}")
    logging.info(f"响应数据: {res.json()}")
    assert res.status_code==200
    logging.info("DELETE 请求成功")


if __name__ == "__main__":
    test_get_all_information()
    # test_many_post_information(Placeholder_data,code)
    test_post_information()
    test_put_information()
    test_get_information()
    test_delete_information()

logging.shutdown()

很奇怪的是当我用pytest命令行来运行测试用例时,我的测试用例成功执行完毕,但是 我的logging.log日志文件中并没有日志生成,会报UnicodeDecodeError: 'gbk' codec can't decode byte 0xaf in position 44: illegal multibyte sequence的错,我尝试了很多方法都失败了,但是当我用if __name__ == "__main__":运行日志时,就可以成功生成日志文件,如下图,不知是什么原因有知道的小伙伴可以评论区告诉我,非常感谢

五、生成html格式的测试报告

安装 pytest-html 插件

首先,确保你安装了 pytest-html 插件。如果没有安装,可以使用以下命令进行安装:

pip install pytest-html

使用 pytest-html 生成 HTML 测试报告

在运行测试时,可以通过 --html 选项来生成 HTML 格式的测试报告。例如,以下命令会生成一个名为 report.html 的 HTML 报告:

pytest --html=report.html --self-contained-html
  • --html=report.html:指定生成报告的文件名和路径。
  • --self-contained-html:生成一个独立的 HTML 文件,所有的 CSS 和 JavaScript 都会嵌入到 HTML 文件中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高等数学学习笔记 ☞ 不定积分的积分方法

1. 第一换元积分法 1. 基础概念:形如的过程,称为第一换元积分法。 2. 核心思想:通过对被积函数的观察(把被积函数的形式与积分表的积分公式进行比较),把外部的部分项拿到的内部(求原函数), 然后进行拼凑,…

win32汇编环境,窗口程序中基础列表框的应用举例

;运行效果 ;win32汇编环境,窗口程序中基础列表框的应用举例 ;比如在窗口程序中生成列表框,增加子项,删除某项,取得指定项内容等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>>>>>>>>>>>…

Jmeter配置服务代理器 Proxy(二)

1.创建脚本记录器 2.配置:Jmeter代理、端口、记录目标等 3.配置谷歌浏览器代理 浏览器配置代理的详细教程可参考:使用whistle代理-CSDN博客 4.启动Jmeter记录器 点击ok后弹出这个界面,生成了证书: 5.给浏览器安装Jmeter代理的证书…

红日-VulnStack靶场一

http://vulnstack.qiyuanxuetang.net/vuln/ 一、环境部署 win7(被攻击机/关火墙) web服务器 1张外网网卡(桥接192.168.1.105),一张内网网卡192.168.52.143/255.255.255.0/192.168.52.2 DNS 192.168.52.138 winser2008 域控服务器 1张…

Chrome谷歌浏览器如何能恢复到之前的旧版本

升级了谷歌最新版不习惯,如何降级版本 未完待续。。 电脑中的Chrome谷歌浏览器升级到了最新版本,但是有种种的不适应,如何能恢复到之前的旧版本呢?我们来看看操作步骤,而且无需卸载重装。 怎么恢复Chrome 之前版本&a…

云上贵州多彩宝荣获仓颉社区先锋应用奖 | 助力数字政务新突破

在信息技术应用创新的浪潮中,仓颉社区吸引了众多企业和开发者的积极参与,已有多个应用成功落地,展现出蓬勃的创新活力。仓颉编程语言精心遴选了在社区建设、应用创新、开源共建、技术布道等方面做出突出贡献的优秀项目应用,并颁发…

LabVIEW实车四轮轮速信号再现系统

开发了一个基于LabVIEW的实车四轮轮速信号再现系统。该系统解决现有电机驱动传感器成本高、重复性差、真实性差和精度低等问题,提供一种高精度、低成本的轮速信号再现解决方案。 项目背景 ABS轮速传感器在现代汽车安全系统中发挥着至关重要的作用。为保证其准确性和…

Java算法 二叉树入门 力扣简单题相同的树 翻转二叉树 判断对称二叉树 递归求二叉树的层数

目录 模版 先序遍历 中序遍历 后序遍历 力扣原题 相同的二叉树 力扣原题 翻转二叉树 遍历树的层数 题目 静态变量 核心逻辑 模版 // 二叉树public static class Node{public int value;public Node left;public Node right;public Node(int v) {valuev;}} 先序遍历 …

P6周:VGG-16算法-Pytorch实现人脸识别

🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 我的环境 语言环境:Python 3.8.12 编译器:jupyter notebook 深度学习环境:torch 1.12.0cu113 一、前期准备 1.设置GPU im…

Ubuntu、Windows系统网络设置(ping通内外网)

一、 虚拟机VMware和Ubuntu系统的网络配置说明 1、虚拟机的网络适配器的模式有三种: 桥接模式NAT模式主机模式 2、虚拟机VMware的网卡配置(如何进行配置界面(虚拟机->设置)) 注意: 1、以上桥接模式(ubuntu有独立IP)、NAT模式(没有独立IP)都可以联…

Web端实时播放RTSP视频流(监控)

一、安装ffmpeg: 1、官网下载FFmpeg: Download FFmpeg 2、点击Windows图标,选第一个:Windows builds from gyan.dev 3、跳转到下载页面: 4、下载后放到合适的位置,不用安装,解压即可: 5、配置path 复制解压后的\bin路径,配置环境变量如图: <

Mongodb相关内容

Mongodb相关内容 1、Windows平台安装2、Linux平台安装3、基本常用命令文档更新删除文档分页查询索引 pymongo操作 客户端下载&#xff1a;https://download.csdn.net/download/guoqingru0311/90273435 1、Windows平台安装 方式一&#xff1a; 方式2&#xff1a; 方式3&#…

SQL2000在win10上安装的方法

安装前最好先关闭防火墙和一些杀毒软件&#xff0c;因为这些软件在安装过程中可能会碰到注册表等一下杀毒软件比较敏感的地带&#xff0c;如果违反杀毒软件的规则会被当做病毒强行终止删除 首相找到C盘下window文件中的sysWOW64文件 鼠标右键&#xff0c;点击属性、安全、高级 …

EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成

EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成 1所有的材料都可以在EAMM: One-Shot Emotional Talking Face via Audio-Based Emotion-Aware Motion Model网站上找到。 摘要 尽管音频驱动的对话人脸生成技术已取得显著进展&#xff0c;但现有方法要么忽…

【华为路由/交换机的ftp文件操作】

华为路由/交换机的ftp文件操作 PC&#xff1a;10.0.1.1 R1&#xff1a;10.0.1.254 / 10.0.2.254 FTP&#xff1a;10.0.2.1 S1&#xff1a;无配置 在桌面创建FTP-Huawei文件夹&#xff0c;里面创建config/test.txt。 点击上图中的“启动”按钮。 然后ftp到server&#xff0c;…

Web前端开发技术之HTMLCSS知识点总结

学习路线 一、新闻网界面1. 代码示例2. 效果展示3. 知识点总结3.1 HTML标签和字符实体3.2 超链接、颜色描述与标题元素3.3 关于图片和视频标签&#xff1a;3.4 CSS引入方式3.5 CSS选择器优先级 二、flex布局1. 代码示例2. 效果展示3. 知识点总结3.1 span标签和flex容器的区别3.…

基于SSM汽车美容管家【提供源码+答辩PPT+文档+项目部署】(高质量源码,可定制,提供文档,免费部署到本地)

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

idea gradle compiler error: package xxx does not exist

idea 编译运行task时报项目内的包不存在&#xff0c;如果你试了网上的其它方法还不能解决&#xff0c;应该是你更新了新版idea&#xff0c;项目用的是旧版jdk&#xff0c;请在以下编译器设置中把项目JDK字节码版本设为8&#xff08;jdk1.8&#xff0c;我这里是17请自行选择&…

1.17学习

crypto nssctf-[SWPUCTF 2021 新生赛]crypto8 不太认识这是什么编码&#xff0c;搜索一下发现是一个UUENCODE编码&#xff0c;用在线工具UUENCODE解码计算器—LZL在线工具解码就好 misc buuctf-文件中的秘密 下载附件打开后发现是一个图片&#xff0c;应该是一个图片隐写&…

Formality:参考设计/实现设计以及顶层设计

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482​​​ Formality存在两个重要的概念&#xff1a;参考设计/实现设计和顶层设计&#xff0c;本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…