接口自动化测试
一、测试框架介绍
接口测试场景
接口自动化测试场景
接口自动化测试与 Web/App 自动化测试对比
Web 自动化测试 | 接口自动化测试 | |
---|---|---|
成本 | ⭐️⭐️⭐️ | ⭐️ |
测试效率 | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ |
用例编写效率 | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ |
稳定性 | ⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ |
自动化回归测试效率 | ⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ |
测试覆盖度 | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ |
自动生成用例成本 | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️ |
接口测试工具类型
测试类型 | 工具 | 价值 |
---|---|---|
接口抓包 | Charles、Postman | 接口抓包工具,可以抓取 App 的数据包 |
接口测试 | Postman | 接口调试工具,接口手工测试工具,学习成本低,直接安装即可使用 |
接口自动化测试 | Python(Requests)、Java(RestAssured) | 用于接口自动化测试的 Java、Python 第三方库,需要与对应编程语言结合使用 |
性能测试 | JMeter | 性能测试工具 |
二、接口请求方法
常见的 HTTP 请求方法:
- GET(获取):用于从服务器获取资源。
- POST(提交):用于将数据提交到服务器,以创建新的资源。
- PUT(更新):用于更新服务器上的资源,或者创建新资源(如果不存在)。
- DELETE(删除):用于请求服务器删除指定的资源。
常见 HTTP 请求方法构造
方法 | 说明 |
---|---|
requests.request() | 构造一个请求,支撑以下各方法的基础方法。 |
requests.get() | 构造 HTTP 协议中的 GET 请求。 |
requests.post() | 构造 HTTP 协议中的 POST 请求。 |
requests.put() | 构造 HTTP 协议中的 PUT 请求。 |
requests.delete() | 构造 HTTP 协议中的 DELETE 请求。 |
环境:pip install requests
import requests
import requestsdef test_get():url = "https://httpbin.ceshiren.com/get"r = requests.get(url)#同样可以用requests.Request("GET", url)print(r.json())def test_post():url = "https://httpbin.ceshiren.com/post"r=requests.post(url)print(r.json())#如果出现Method Not Allowed错误,可能是因为请求方法不正确
def test_put():url = "https://httpbin.ceshiren.com/put"r = requests.put(url)print(r.json())
def test_delete():url = "https://httpbin.ceshiren.com/delete"r = requests.delete(url)print(r.json())
三、接口请求参数
概念:接口请求中携带的,会在路径之后使用的代表客户端向服务器传递的参数。使用key=value的形式拼接在url中,多个之间用&隔开
import requests#发起一个get请求,并携带url参数信息
def test_get_url():url= "https://httpbin.ceshiren.com/get?name=ad&age=18"r=requests.get(url)print(r.text)
def test_get_params():url = "https://httpbin.ceshiren.com/get"#定义一个字典格式params = {"name": "ad", "age": 18}r = requests.get(url, params=params)print(r.text)
#==============================================
def test_post_url():url = "https://httpbin.ceshiren.com/post?name=ad2&age=19"r = requests.post(url)print(r.text)
def test_post_params():url = "https://httpbin.ceshiren.com/post"# 定义一个字典格式params = {"name": "ad2", "age": 19}r = requests.get(url, params=params)print(r.text)
四、接口请求头
请求头是在 HTTP 请求消息中包含的元数据信息,用于描述请求或响应的一些属性和特征。
常见的头信息:
内容 | 含义 |
---|---|
Authorization | 表示客户端请求的身份验证信息 |
Cookie | 表示客户端的状态信息,通常用于身份验证和会话管理 |
Content-Type | 表示请求消息体的 MIME 类型 |
User-Agent | 发送请求的客户端软件信息 |
import requests
def test_headers():url= "https://httpbin.ceshiren.com/get"headers={"name":"ad", "age": 18}r= requests.get(url,headers=headers)print(r.text)
五、json请求体
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation),JSON是轻量级的文本数据交换格式(数据传递)
JSON 独立于语言,JSON 使用 Javascript 语法来描述数据对象,JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持 JSON。
比如接口需要上传 JSON 格式或者我们返回的响应信息也是 JSON 格式
JSON 的语法规则和数据类型如下:
- 数字(整数或浮点数),如
{"age": 18, "score": 70.5}
- 字符串(只能被双引号包裹),如
{"name": "zs" , "sex": "女"}
- 逻辑值(true 或 false),如
{"flag": true}
- 数组(在中括号中),如
{"score": [100, 80, 90]}
- 对象(在大括号中),如
{"stu1": {"name": "zs", "sex": "女"}, "url": "https://www.baidu.com"}
- null,如
{"score": null}
JSON 与 Python 字典的区别:
JSON: - 键只能是字符串,值可以是字符串、数字、对象、数组、布尔值或 null
Python 字典: - 键可以是数字、字符串、元组。值可以是数字、字符串、元组、列表或字典
JSON 是一种数据交换格式,比较简洁和通用,而 Python 字典则是 Python 中的数据结构,更灵活且用于在 Python 中进行数据处理及存储。
访问JSON对象值:
myobj={"name":"zs","sal":10000,"add":None}
# 将字典对象转换为 JSON 字符串
json_str = json.dumps(myobj)
print(json_str)
访问JSON数组:
n = {"name": "qingan", "age": 22, "sites": ["Google", "baidu", "Taobao"]}
x = n["sites"][0]
print(x)
常用接口请求体
类型 | 介绍 | Content-type |
---|---|---|
JSON(JavaScript Object Notation) | 轻量级的数据交换格式,最常见的一种类型。 | application/json |
表单数据(Form Data) | 以键值对的形式提交数据,例如通过 HTML 表单提交数据。 | application/x-www-form-urlencoded |
XML(eXtensible Markup Language) | 常用的标记语言,通常用于传递配置文件等数据。 | application/xml text/xml |
文件(File) | 可以通过请求体上传文件数据,例如上传图片、视频等文件。 | 上传文件的 MIME 类型,例如 image/jpeg multipart/form-data |
纯文本(Text) | 纯文本数据,例如发送邮件、发送短信等场景 | text/plain |
其他格式 | 二进制数据、protobuf 等格式 |
接口中上传的类型除了 json
还有 data
,我们可以看请求头内的 content-type
参数来判断该上传什么格式:
- 若是 application/json
,为 json 格式,则使用 json 参数
- 若是 application/x-www-form-urlencoded
,为表单格式,则使用 data 参数
六、接口响应断言
接口响应断言是在进行接口测试时用于验证接口返回结果的方法。断言主要是用来检查代码或测试中的期望条件是否满足。在接口测试中,断言通常用于验证 API 的响应是否符合预期,确保接口按照预定的规范工作。
Response对象
响应对象
import requests
from requests import Response# Response就是一个响应对象,可以随意定义名称
Response = requests.get('http://www.example.com')
了解下响应对象包含了什么
属性 | 含义 |
---|---|
r | 响应 Response 对象(可以使用任意的变量名) |
r.status_code | HTTP 响应状态码 |
r.headers | 返回一个字典,包含响应头的所有信息。 |
r.text | 返回响应的内容,是一个字符串。 |
r.url | 编码之后的请求的 url |
r.content | 返回响应的内容,是一个字节流。 |
r.raw | 响应的原始内容 |
r.json() | 如果响应的内容是 JSON 格式,可以使用该方法将其解析成 Python 对象。 |
响应断言
断言用到的是assert关键字>预期的结果和实际结果做对比:
- 判断xx为真
assert xx
- 判断xx不为真
assert not xx
- 判断b包含a
assert a in b
- 判断a等于b
assert a == b
基础断言: - r.status_code
import requestsdef req():r = requests.get("https://httpbin.ceshiren.com/get")#判断我们的接口返回的状态码是否是200assert r.status_code == 200
- 判断a不等于b
assert a != b
七、json响应体断言
JSON响应断言是针对API测试中的响应数据进行验证的一种方法,通常用于确认API服务是否按照预期返回正确的数据。在自动化测试中,需要对接口的返回结果进行验证,以确保接口的功能和数据符合预期
- 服务器端响应客户端请求后返回的数据体。
- 接口响应体的格式通常为 JSON、XML、HTML 等。
JSON格式响应体:
{"name": "John","age": 30,"city": "New York"
}
在断言中的应用
依然假定上面的 JSON
对象是某个接口的 response
反序列化得到的。接下来,看看在自动化测试中如何利用 JSONPath
表达式进行断言。
在 Python 语言中,使用 JSONPath
需要安装一个第三方库 jsonpath
。
pip install jsonpath
假定这是一个接口的 response
response={ "store": {"book": [ { "category": "reference","author": "Nigel Rees","title": "Sayings of the Century","price": 8.95},{ "category": "fiction","author": "Evelyn Waugh","title": "Sword of Honour","price": 12.99},{ "category": "fiction","author": "Herman Melville","title": "Moby Dick","isbn": "0-553-21311-3","price": 8.99},{ "category": "fiction","author": "J. R. R. Tolkien","title": "The Lord of the Rings","isbn": "0-395-19395-8","price": 22.99}],"bicycle": {"color": "red","price": 19.95}},"expensive": 10
}
- 测试用例1:
验证 response 中包含 Nigel Rees
, Evelyn Waugh
, Herman Melville
, J. R. R. Tolkien
这四位作者的图书。
import jsonpath
def test_authors():author_list = jsonpath.jsonpath(response, '$.store.book[*].author')assert author_list == ['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien']
- 测试用例2:
验证 response 中的商品价格包含8.95, 12.99, 8.99, 22.99, 19.95这5种。
def test_all_price():store_price_list = jsonpath.jsonpath(response, '$.store..price')# store_price_list = jsonpath.jsonpath(response, '$..price')assert store_price_list == [8.95, 12.99, 8.99, 22.99, 19.95]
- 测试用例3:
验证 response 中的第3本图书的书名是 Moby Dick。
def test_third_book_title():book_3 = jsonpath.jsonpath(response, '$.store.book[2]')assert book_3[0]['title'] == "Moby Dick"
- 4. 测试用例4:
验证 response 中的最后一本图书的 isbn
是 0-395-19395-8。
def test_last_book_isbn():last_book_isbn = jsonpath.jsonpath(response, f'$.store.book[-1:]')assert last_book_isbn[0]['isbn'] == "0-395-19395-8"
- 测试用例5:
验证 repsonse 中前两本书价格之和是8.95 + 12.99
def test_12_books_price():book_12 = jsonpath.jsonpath(response, '$..book[0,1].price')assert book_12[0] + book_12[1] == 8.95 + 12.99
- 测试用例6:
验证 response 中有两本书的价格小于10
def test_2books_cheap_than_10():book_lg10 = jsonpath.jsonpath(response, '$..book[?(@.price<10)]')assert len(book_lg10) <= 2
- 测试用例7:
验证 response
中具有 color
属性的商品,其 color
是 red
def test_has_color():colorful_goods = jsonpath.jsonpath(response, '$.store..[?(@.color)]')assert "red" == colorful_goods[0]['color']