接口自动化项目落地之HTTPBin网站

原文:https://www.cnblogs.com/df888/p/16011061.html
 

接口自动化项目落地系列

找个开源网站或开源项目,用tep实现整套pytest接口自动化项目落地,归档到电子书,作为tep完整教程项目篇一部分。自从tep完整教程发布以后,tep被越来越多小伙伴了解。教程只是纯理论,是骡子是马,拉出来遛遛才知道。做接口自动化项目落地,一方面是为了让自己脑海中的构想实实在在的呈现出来,现实和理想存在多少差距,不断尝试去弥补和修缮;另一方面也是方便读者朋友们学习使用,借助实际项目来练习,才能在赛道中弯道超车。

HTTPBin网站

httpbin.org是一个简单的在线提供HTTP服务的网站:

它能够用来对HTTP进行在线测试。

测试报告

HTTPBin网站的接口自动化项目包含11个用例集

67条测试用例

自动化执行正确率98.5%,其中有1条错误结果,是我故意为之的,因为想展示下断言失败的效果。

环境配置

包含http和https两套环境,因为HTTPBin支持HTTP&HTTPS:

fixtures/fixture_env_vars.py

#!/usr/bin/python
# encoding=utf-8from tep.fixture import *@pytest.fixture(scope="session")
def env_vars(config):class Clazz(TepVars):env = config["env"]"""变量定义开始"""# 环境变量mapping = {"http": {  # http环境"domain": "http://httpbin.org",},"https": {  # https环境"domain": "https://httpbin.org",}# 继续添加}# 定义类属性,敲代码时会自动补全domain = mapping[env]["domain"]"""变量定义结束"""return Clazz()

配置默认为http环境:

conf.yaml

env: http

用例集

http-methods

import allure
from tep.client import request@allure.title("get请求")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/get",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'},params={})# 提取# 断言assert response.status_code < 400

auth

import allure
from tep.client import request@allure.title("Authorization以Bearer开头,认证成功")
def test(env_vars):# 描述# http://httpbin.org/#/Auth/get_basic_auth__user___passwd_# 数据# 请求response = request("get",url=env_vars.domain + "/bearer",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','Authorization': 'Bearer ZG9uZ2ZhbmdlcjoxMjM0NTY=',  # 替换token'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'},params={})# 提取# 断言assert response.status_code < 400

status-codes

import allure
from tep.client import request@allure.title("post返回状态码300")
def test(env_vars):# 描述# 数据# 请求response = request("post",url=env_vars.domain + "/status/300",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'Content-Length': '0', 'accept': 'text/plain','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Origin': 'http://httpbin.org', 'Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value'},json={})# 提取# 断言assert response.status_code == 300

request_inspection

import allure
from tep.client import request@allure.title("捕获请求信息--headers")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/headers",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value'},params={})# 提取# 断言assert response.status_code < 400assert response.json()["headers"]

response_inspection

import allure
from tep.client import request@allure.title("捕获响应信息--缓存")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/cache",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'Cache-Control': 'max-age=0','accept': 'application/json', 'If-None-Match': '1', 'If-Modified-Since': '1','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value'},params={})# 提取# 断言assert response.status_code == 304

response_formats

import allure
from tep.client import request@allure.title("txt文本text/plain")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/robots.txt",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'text/plain','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value'},params={})# 提取# 断言assert response.status_code < 400assert response.headers["content-type"] == "text/plain"

dynamic_data

import allure
from tep.client import request@allure.title("base64解码")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/base64/SFRUUEJJTiBpcyBhd2Vzb21l",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'text/html','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value'},params={})# 提取# 断言assert response.status_code < 400assert "HTTPBIN is awesome" == response.text

cookies

import allure
from tep.client import request@allure.title("cookies")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/cookies",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value'},params={})# 提取# 断言assert response.status_code < 400assert response.json()["cookies"]

images

import allure
from tep.client import request@allure.title("图片")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/image",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'image/webp','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},params={})# 提取# 断言assert response.status_code < 400

redirects

import allure
from tep.client import request@allure.title("重定向")
def test(env_vars):# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/redirect/1",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'text/html','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': 'http://httpbin.org/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},params={})# 提取# 断言assert response.status_code == 404

anything

import allure
from tep.client import request@allure.title("返回所有数据")
def test(env_vars):# 描述# 数据# 请求response = request("delete",url=env_vars.domain + "/anything",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Origin': '', 'Referer': '/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},json={})# 提取# 断言assert response.status_code < 400# 描述# 数据# 请求response = request("get",url=env_vars.domain + "/anything",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Referer': '/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},params={})# 提取# 断言assert response.status_code < 400# 描述# 数据# 请求response = request("patch",url=env_vars.domain + "/anything",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Origin': '', 'Referer': '/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},json={})# 提取# 断言assert response.status_code < 400# 描述# 数据# 请求response = request("post",url=env_vars.domain + "/anything",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'Content-Length': '0','accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Origin': '', 'Referer': '/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},json={})# 提取# 断言assert response.status_code < 400# 描述# 数据# 请求response = request("put",url=env_vars.domain + "/anything",headers={'Host': 'httpbin.org', 'Proxy-Connection': 'keep-alive', 'Content-Length': '0','accept': 'application/json','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36','Origin': '', 'Referer': '/', 'Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7','Cookie': 'stale_after=never; fake=fake_value; freeform=3; name=dongfanger'},json={})# 提取# 断言assert response.status_code < 400

只花了3小时完成

通过mitmproxy来录制流量自动生成用例,效率得到了极大的提高,从原来的1天缩短到3小时就完成了整个项目落地。相比于手工编写用例,这次写HTTPBin的接口自动化,我使用了utils/mitm.py来录制流量,mitmproxy稍微不方便的是需要手动开启代理,不过适应了以后还是能接受。录制流量后就会生成自动化用例,但是还需要二次修改,才会变成最终的用例。主要修改的工作量是在添加断言,根据业务设置合理的断言。其次是替换url为env_vars.domain + "/api"拼接方式,直接批量Replace即可。然后就是修改文件名和@allure.title了,给用例加上标题。工欲善其事,必先利其器。

tep共建

欢迎添加微信:cekaigang,分享交流tep实践案例,可以提供开源项目我来写,也可以写好后发我一起看看,优秀的项目会添加到tep完整教程的项目篇,以便更多测试同行们借鉴,大佬们赶快来加入我们吧。

参考资料:

HTTPBin接口自动化项目源码 GitHub - dongfanger/httpbin: httpbin.org接口自动化项目

postman Postman

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

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

相关文章

C语言:结构体

目录 结构体类型的声明 匿名结构体 全局结构体变量 嵌套结构体 访问结构体成员 结构的自引用 结构体变量的定义和初始化 结构体内存对齐 结构体内存对齐规则 修改默认对齐数 #pragma pack(n) offsetof 求结构体成员相对于结构体开头的偏移量的宏。 为什么存在内存…

pip list 和 conda list的区别

PS : 网上说conda activate了之后就可以随意pip了 可以conda和pip混用 但是安全起见还是尽量用pip 这样就算activate了&#xff0c;进入base虚拟环境了 conda与pip的区别 来源 Conda和pip通常被认为几乎完全相同。虽然这两个工具的某些功能重叠&#xff0c;但它们设计用于不…

硬件开发笔记(十二):RK3568底板电路电源模块和RTC模块原理图分析

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/134429973 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

清华源Certificate verification failed解决办法

Certificate verification failed: The certificate is NOT trusted. The certificate chain uses expired certificate. Could not handshake: Error in the certificate verification. sudo update-ca-certificates

C++之type traits

目录 帮助类std::integral_constantbool_constant 主要类型分类std::is_voidis_null_pointeris_integralis_floating_pointis_arrayis_enumis_unionis_classis_functionis_pointeris_lvalue_referenceis_rvalue_referenceis_member_object_pointeris_member_function_pointer 组…

rpc依赖安装

依赖&#xff1a; 0、boost&#xff1a;用于实现多线程等&#xff1b; 1、protobuf&#xff1a;用于实现数据的序列化、反序列化&#xff0c;也用于定义和生成rpc数据及接口&#xff1b; 2、libevent&#xff1a;用于实现基于IO多路复用机制的网络事件循环。 其实可以直接用包…

JAVA sql 查询

-- 1. 查询员工表所有数据&#xff0c;并说明使用*的缺点 SELECT * from employees -- *号查询效率低 -- 2. 查询所员工的 email 全名,公司 email 统一以 "qq.com " 结尾. SELECT email from employees WHERE email like "%qq.com" -- 3. 打印公司里…

庖丁解牛:NIO核心概念与机制详解 06 _ 连网和异步 I/O

文章目录 Pre概述异步 I/OSelectors打开一个 ServerSocketChannel选择键内部循环监听新连接接受新的连接删除处理过的 SelectionKey传入的 I/O回到主循环 Pre 庖丁解牛&#xff1a;NIO核心概念与机制详解 01 庖丁解牛&#xff1a;NIO核心概念与机制详解 02 _ 缓冲区的细节实现…

Go基础面经大全(持续补充中)

Go基础 1. 基础特性 Go的优势 天生支持并发&#xff0c;性能高。 单一的标准代码格式&#xff0c;比其他语言更具可读性。 自动垃圾收集机制比Java和Python更有效&#xff0c;因为它与程序同时执行。 Go数据类型 int, string, float, bool, array, slice, map, channel, p…

如何将本地Portainer管理界面结合cpolar内网穿透工具实现远程浏览器访问

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

Android修行手册-POI操作中文API文档

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

LLM模型-讯飞星火与百度文心api调用

spark-wenxin 1-讯飞星火1_1-SparkApi.py1_2- Chat_spark.py1_3-调用api 2-百度文心2_1.code 3-两者之间比较与openai 1-讯飞星火 进入讯飞官网进行创建应用&#xff0c;获取相关密钥APPID&#xff0c;APISecret&#xff0c;APIKey&#xff0c;选择最新版本 首次调用讯飞官方a…

redis三种集群方式

redis有三种集群方式&#xff1a;主从复制&#xff0c;哨兵模式和集群。 1.主从复制 主从复制原理&#xff1a; 从服务器连接主服务器&#xff0c;发送SYNC命令&#xff1b; 主服务器接收到SYNC命名后&#xff0c;开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所…

Git的简单使用

Git的简介 Git是一个分布式版本控制工具&#xff0c;通常用来对软件开发过程中的源代码文件进行管理。通过Git仓库来存储和管理这些文件&#xff0c;Git仓库分为两种&#xff0c;一个是本地仓库&#xff1a;开发人员自己电脑上的Git仓库&#xff0c;一个是远程仓库&#xff1a;…

centos FreeXL源码编译

安装、编译 https://www.gaia-gis.it/gaia-sins/freexl-2.0.0.zip wget https://www.gaia-gis.it/gaia-sins/freexl-2.0.0.zip#centos yum install -y minizip minizip-devel expat-devel ./configure --prefix/usr/local/freexl-2.0.0#Ubuntu apt install libminizip libmin…

学习c#的第十六天

目录 C# 正则表达式 定义正则表达式 字符转义 字符类 定位点 分组构造 Lookaround 概览 数量词 反向引用构造 替换构造 替代 正则表达式选项 其他构造 Regex 类 代码示例 实例 1 实例 2 实例 3 C# 正则表达式 正则表达式 是一种匹配输入文本的模式。.Net 框…

PHP比较漏洞, 代码审计, 字符串数字, “0e“字符串, 布尔值比较, 极限值, switch比较, in_array比较

PHP比较漏洞 一, 字符串与数字比较,0e’字符串比较 在 PHP 中处理字符串和数字比较时需要小心谨慎的重要性&#xff0c;尤其是在安全敏感的应用中。 在某些情况下&#xff0c;PHP 的类型强制转换可能会导致意外和潜在的安全漏洞。 var_dump("admin" 0); //true …

RecyclerView嵌套布局,导致RecyclerView复用失效 解决

前言&#xff1a;使用NestedScrollView嵌套RecyclerView。 解决步骤一&#xff1a;固定高度 NestedScrollView嵌套RecyclerView时&#xff0c;RecyclerView的高度是无限大&#xff0c;所以要将RecyclerView设置固定高度。在代码中固定的&#xff0c;灵活度更高。 binding.nest…

键盘方向键移动当前选中的table单元格,并可以输入内容

有类似于这样的表格&#xff0c;用的<table>标签。原本要在单元格的文本框里面输入内容&#xff0c;需要用鼠标一个一个去点以获取焦点&#xff0c;现在需要不用鼠标选中&#xff0c;直接用键盘的上下左右来移动当前正在输入的单元格文本框。 const currentCell React.u…

【数据结构初阶】单链表SLlist

描述 不同于顺序表&#xff0c;顺序表的数据是存储在一个连续的空间里的 而链表它是链接起来的结构体地址。 所以我们不用像顺序表一样先创建一块空间出来&#xff0c;而是创建一个能存数据节点和节点与下一个节点之间的连接&#xff1b; 所以&#xff1a;“一个能存数据节点…