seldom 2.0 让接口自动化测试更简单
前言
HTTP接口测试很简单,不管工具、框架、还是平台,只要很的好的几个点就是好工具。
- 测试数据问题:比如删除接口,重复执行还能保持结果一致,必定要做数据初始化。
- 接口依赖问题:B接口依赖A的返回值,C接口依赖B接口的返回值。
- 加密问题:不同的接口加密规则不一样。有些用到时间戳、md5、base64、AES,如何提供种能力。
- 断言问题:有些接口返回的结构体很复杂,如何灵活的做到断言。
对于以上问题,工具和平台要么不支持,要么很麻烦,然而框架是最灵活的。
unittest/pytest + requests/https 直接上手写代码就好了,既简单又灵活。
那么同样是写代码,A框架需要10行,B框架只需要5行,然而又不失灵活性,那我当然是选择更少的了,毕竟,人生苦短嘛。
seldom适合个人接口自动化项目,它有以下优势。
- 可以写更少的代码
- 自动生成HTML/XML测试报告
- 支持参数化,减少重复的代码
- 支持生成随机数据
- 支持har文件转case
- 支持数据库操作
这些是seldom支持的功能,我们只需要集成HTTP接口库,并提供强大的断言即可。seldom 2.0
加入了HTTP接口自动化测试支持。
Seldom 兼容 Requests API 如下:
seldom | requests |
---|---|
self.get() | requests.get() |
self.post() | requests.post() |
self.put() | requests.put() |
self.delete() | requests.delete() |
Seldom VS Request+unittest
先来看看unittest + requests是如何来做接口自动化的:
import unittest
import requests
class TestAPI(unittest.TestCase):
def test_get_method(self):
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
self.assertEqual(r.status_code, 200)
if __name__ == '__main__':
unittest.main()
这其实已经非常简洁了。同样的用例,用seldom实现。
# test_req.py
import seldom
class TestAPI(seldom.TestCase):
def test_get_method(self):
payload = {'key1': 'value1', 'key2': 'value2'}
self.get("http://httpbin.org/get", params=payload)
self.assertStatusCode(200)
if __name__ == '__main__':
seldom.main()
主要简化点在,接口的返回数据的处理。当然,seldom真正的优势在断言、日志和报告。
har to case
对于不熟悉 Requests 库的人来说,通过Seldom来写接口测试用例还是会有一点难度。于是,seldom提供了har
文件转 case
的命令。
首先,打开fiddler 工具进行抓包,选中某一个请求。
然后,选择菜单栏:file
-> Export Sessions
-> Selected Sessions...
选择导出的文件格式。
点击next
保存为demo.har
文件。
最后,通过seldom -h2c
转为demo.py
脚本文件。
> seldom -h2c .\demo.har
.\demo.py
2021-06-14 18:05:50 [INFO] Start to generate testcase.
2021-06-14 18:05:50 [INFO] created file: D:\.\demo.py
demo.py
文件。
import seldom
class TestRequest(seldom.TestCase):
def start(self):
self.url = "http://httpbin.org/post"
def test_case(self):
headers = {"User-Agent": "python-requests/2.25.0", "Accept-Encoding": "gzip, deflate", "Accept": "application/json", "Connection": "keep-alive", "Host": "httpbin.org", "Content-Length": "36", "Origin": "http://httpbin.org", "Content-Type": "application/json", "Cookie": "lang=zh"}
cookies = {"lang": "zh"}
self.post(self.url, json={"key1": "value1", "key2": "value2"}, headers=headers, cookies=cookies)
self.assertStatusCode(200)
if __name__ == '__main__':
seldom.main()
运行测试
打开debug模式seldom.run(debug=True)
运行上面的用例。
> python .\test_req.py
2021-04-29 18:19:39 [INFO] A run the test in debug mode without generating HTML report!
2021-04-29 18:19:39 [INFO]
__ __
________ / /___/ /___ ____ ____
/ ___/ _ \/ / __ / __ \/ __ ` ___/
(__ ) __/ / /_/ / /_/ / / / / / /
/____/\___/_/\__,_/\____/_/ /_/ /_/
-----------------------------------------
@itest.info
test_get_method (test_req.TestAPI) ...
----------- Request ---------------
url: http://httpbin.org/get method: GET
----------- Response ️ -------------
type: json
{'args': {'key1': 'value1', 'key2': 'value2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-608a883c-7b355ba81fcd0d287566405a'}, 'origin': '183.178.27.36', 'url': 'http://httpbin.org/get?key1=value1&key2=value2'}
ok
----------------------------------------------------------------------
Ran 1 test in 0.619s
OK
通过日志/报告都可以清楚的看到。
- 请求的方法
- 请求url
- 响应的类型
- 响应的数据
更强大的断言
断言接口返回的数据是我们在做接口自动化很重要的工作。
assertJSON
接口返回结果如下:
{
"args": {
"hobby": [
"basketball",
"swim"
],
"name": "tom"
}
}
我的目标是断言name
和 hobby
部分的内容。seldom可以针对JSON
文件进行断言。
import seldom
class TestAPI(seldom.TestCase):
def test_assert_json(self):
payload = {'name': 'tom', 'hobby': ['basketball', 'swim']}
self.get("http://httpbin.org/get", params=payload)
assert_json = {'args': {'hobby': ['swim', 'basketball'], 'name': 'tom'}}
self.assertJSON(assert_json)
运行日志
test_get_method (test_req.TestAPI) ...
----------- Request ---------------
url: http://httpbin.org/get method: GET
----------- Response ️ -------------
type: json
{'args': {'hobby': ['basketball', 'swim'], 'name': 'tom'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-608a896d-48fac4f6139912ba01d2626f'}, 'origin': '183.178.27.36', 'url': 'http://httpbin.org/get?name=tom&hobby=basketball&hobby=swim'}
Assert data has not key: headers
Assert data has not key: origin
Assert data has not key: url
ok
----------------------------------------------------------------------
Ran 1 test in 1.305s
OK
seldom还会提示你还有哪些字段没有断言。
assertPath
接口返回数据如下:
{
"args": {
"hobby":
["basketball", "swim"],
"name": "tom"
}
}
seldom中可以通过path进行断言:
import seldom
class TestAPI(seldom.TestCase):
def test_assert_path(self):
payload = {'name': 'tom', 'hobby': ['basketball', 'swim']}
self.get("http://httpbin.org/get", params=payload)
self.assertPath("name", "tom")
self.assertPath("args.hobby[0]", "basketball")
assertSchema
有时并不关心数据本身是什么,而是需要断言数据的类型。 assertSchema
是基于 jsonschema
实现的断言方法。
jsonschema: https://json-schema.org/learn/
接口返回数据如下:
{
"args": {
"hobby":
["basketball", "swim"],
"name": "tom",
"age": "18"
}
}
seldom中可以通过利用jsonschema
进行断言:
import seldom
class TestAPI(seldom.TestCase):
def test_assert_schema(self):
payload = {"hobby": ["basketball", "swim"], "name": "tom", "age": "18"}
self.get("/get", params=payload)
schema = {
"type": "object",
"properties": {
"args": {
"type": "object",
"properties": {
"age": {"type": "string"},
"name": {"type": "string"},
"hobby": {
"type": "array",
"items": {
"type": "string"
},
}
}
}
},
}
self.assertSchema(schema)
是否再次感受到了seldom提供的断言非常灵活,强大。
接口数据依赖
在场景测试中,我们需要利用上一个接口的数据,调用下一个接口。
import seldom
class TestRespData(seldom.TestCase):
def test_data_dependency(self):
"""
Test for interface data dependencies
"""
headers = {"X-Account-Fullname": "bugmaster"}
self.get("/get", headers=headers)
self.assertStatusCode(200)
username = self.response["headers"]["X-Account-Fullname"]
self.post("/post", data={'username': username})
self.assertStatusCode(200)
seldom提供了self.response
用于记录上个接口返回的结果,直接拿来用即可。
数据驱动
seldom本来就提供的有强大的数据驱动,拿来做接口测试非常方便。
@data
import seldom
from seldom import data
class TestDDT(seldom.TestCase):
@data([
("key1", 'value1'),
("key2", 'value2'),
("key3", 'value3')
])
def test_data(self, key, value):
"""
Data-Driver Tests
"""
payload = {key: value}
self.post("/post", data=payload)
self.assertStatusCode(200)
self.assertEqual(self.response["form"][key], value)
@file_data
创建data.json
数据文件
{
"login": [
["admin", "admin123"],
["guest", "guest123"]
]
}
通过file_data
实现数据驱动。
import seldom
from seldom import file_data
class TestDDT(seldom.TestCase):
@file_data("data.json", key="login")
def test_data(self, username, password):
"""
Data-Driver Tests
"""
payload = {username: password}
self.post("http://httpbin.org/post", data=payload)
self.assertStatusCode(200)
self.assertEqual(self.response["form"][username], password)
更过数据文件(csv/excel/yaml),参考
随机生成测试数据
seldom提供随机生成测试数据方法,可以生成一些常用的数据。
import seldom
from seldom import testdata
class TestAPI(seldom.TestCase):
def test_data(self):
phone = testdata.get_phone()
payload = {'phone': phone}
self.get("http://httpbin.org/get", params=payload)
self.assertPath("args.phone", phone)
更过类型的测试数据,参考
数据库操作
seldom 支持sqlite3、MySQL数据库操作。
sqlite3 | MySQL |
---|---|
delete_data() | delete_data() |
insert_data() | insert_data() |
select_data() | select_data() |
update_data() | update_data() |
init_table() | init_table() |
close() | close() |
连接数据库
连接sqlit3数据库
from seldom.db_operation import SQLiteDB
db = SQLiteDB(r"D:\learnAPI\db.sqlite3")
连接MySQL数据库(需要)
- 安装pymysql驱动
> pip install pymysql
- 链接
from seldom.db_operation import MySQLDB
db = MySQLDB(host="127.0.0.1",
port="3306",
user="root",
password="123",
database="db_name")
操作方法
- delete_data
删除表数据。
db.delete_data(table="user", where={"id":1})
- insert_data
插入一条数据。
data = {'id': 1, 'username': 'admin', 'password': "123"},
db.insert_data(table="user", data=data)
- select_data
查询表数据。
result = db.select_data(table="user", where={"id":1, "name": "tom"})
print(result)
- update_data
更新表数据。
db.update_data(table="user", data={"name":"new tom"}, where={"name": "tom"})
- init_table
批量插入数据,在插入之前先清空表数据。
datas = {
'api_event': [
{'id': 1, 'name': '红米Pro发布会'},
{'id': 2, 'name': '可参加人数为0'},
{'id': 3, 'name': '当前状态为0关闭'},
{'id': 4, 'name': '发布会已结束'},
{'id': 5, 'name': '小米5发布会'},
],
'api_guest': [
{'id': 1, 'real_name': 'alen'},
{'id': 2, 'real_name': 'has sign'},
{'id': 3, 'real_name': 'tom'},
]
}
db.init_table(datas)
- close
关闭数据库连接。
db.close()
最后,基于seldom 实现接口自动化测试的项目:https://github.com/defnngj/pyrequest2
seldom 2.0 让接口自动化测试更简单的更多相关文章
- APICloud数据云3.0 -- 让后端业务更简单
近年来,各类移动端应用层出不穷,app.小程序已成为企业业务数字化的必然选择,围绕互联网产品的技术创新与开发者生态,正在历经行业发展的又一次革新. APICloud作为国内领先的移动应用开发平台,一直 ...
- Jmeter接口自动化测试:简单使用步骤
好处:不需要页面就可以提前介入测试,实施成本低,修改量少,相对于UI自动化来说更为稳定 1. 下载略过 2. 使用步骤 创建线程组合控制器(Jmeter基本操作) 针对http协议的接口增加Sampl ...
- 使用 JsonPath 完成接口自动化测试中参数关联和数据验证(Python语言)
背景: 接口自动化测试实现简单.成本较低.收益较高,越来越受到企业重视 restful风格的api设计大行其道 json成为主流的轻量级数据交换格式 痛点: 接口关联 也称为关联参数.在应用业务接口中 ...
- 接口自动化测试框架-AIM2.0
跳转到3.0版本https://www.cnblogs.com/df888/p/12031649.html AIM是我用python搭建的第一款接口自动化测试框架,随着技术的提升,框架也在升级,故有了 ...
- 【热门技术】EventBus 3.0,让事件订阅更简单,从此告别组件消息传递烦恼~
一.写在前面 还在为时间接收而烦恼吗?还在为各种组件间的消息传递烦恼吗?EventBus 3.0,专注于android的发布.订阅事件总线,让各组件间的消息传递更简单!完美替代Intent,Handl ...
- 接口自动化测试的"开胃小菜"---简单黑客攻击手段
Web应用系统的小安全漏洞及相应的攻击方式 接口自动化测试的"开胃小菜" 1 写作目的 本文讲述一个简单的利用WebAPI来进行一次基本没有破坏力的“黑客”行为. 主要目的如下 ...
- 如何简单实现接口自动化测试(基于 python) 原博主地址https://blog.csdn.net/gitchat/article/details/77849725
如何简单实现接口自动化测试(基于 python) 2017年09月05日 11:52:25 阅读数:9904 GitChat 作者:饿了么技术社区 原文:如何简单实现接口自动化测试(基于 python ...
- 记录python接口自动化测试--简单总结一下学习过程(第十目)
至此,从excel文件中循环读取接口到把测试结果写进excel,一个简易的接口自动化测试框架就完成了.大概花了1周的时间,利用下班和周末的时间来理顺思路.编写调试代码,当然现在也还有很多不足,例如没有 ...
- 简单实现接口自动化测试(基于python+unittest)
简单实现接口自动化测试(基于python+unittest) 简介 本文通过从Postman获取基本的接口测试Code简单的接口测试入手,一步步调整优化接口调用,以及增加基本的结果判断,讲解Pytho ...
随机推荐
- 汇编环境搭建(vs2010(2012)+masm32)
我本地使用的环境VS2012(2010)+MASM32,下面的图是在网上找的几个博客拼在一起的,用的是vs2010,但是并不影响.(所有文件我都打包好了,如果懒的话可以直接下载这个包)地址是:http ...
- json对象的获取
<script type="text/javascript"> var person = { //json对象定义开始 name:'tom', //字符串 age:24 ...
- 前端小白的学习之路html与css的较量【二】
标签的划分 块级元素 独占一行 设置 宽 高可以起作用 排列方式: 上下排列 行内元素 可以共占一行 设置 宽 高 不起作用,大小由内容决定 排列方式:左右排列 行内块 可以共占一行 可以设置宽 高 ...
- IntelliJ IDEA打开Maven项目,Spring boot所有依赖红名,不可用
导入外部的springboot项目时,出现报红线,无论怎么刷新maven就是不下载依赖包,情况如下 解决办法: 1)直接去自己的maven仓库,找到Spring boot,然后直接删除下面的文件 2) ...
- 安装mysql警告: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
CentOS安装rpm安装MySQL时爆出警告: warning: mysql-community-server-5.7.18-1.el6.x86_64.rpm: Header V3 DSA/SHA1 ...
- app.json文件配置
pages 页面路径的存放列表 通过手写页面路径可以在对应目录下自动创建对应文件 "pages": [ "pages/demo3/demo3", "p ...
- VS2010编写32位和64位dll环境配置,以及判断dll是多少位
前言 最近在编写dll注入程序的时候,因为想注入到系统进程,结果发现总是注入失败.自闭了好长一会发现我忘记了我的系统是64位的,系统进程也是64位的,而我编写的待注入的DLL是32位了,所以才导致失败 ...
- 大华摄像头报警接口中图片加密,python调用c++方式实现解密
项目中,大华摄像头的报警信息,里面有图片地址,需要1天内取下来,保持留痕 可惜,图片下载后,加密了,大华提供了android,ios,c++例子,没有提供java解密例子 没办法,只好先用c++例子简 ...
- KMP(The Knuth-Morris-Pratt Algorithm)
本文代码来自于中国大学MOOC KMP课件下载 注释内容为自己理解,如有错误请评论,或者私信给我,谢谢 #include <stdio.h> #include "stdlib.h ...
- [Django框架 - 注意事项,安装,项目搭建,小白必会三板斧]
[Django框架 - 注意事项,安装,项目搭建,小白必会三板斧] 想要正常运行django项目所需要知道的注意事项 1. 计算机名称不能有中文,不然bug在哪儿你都不知道! 2. 项目名和py文件名 ...