1.金字塔模型


把软件测试从宏观的思维分为三层,最底层的是单元测试,中间层是API测试,最上层是UI⾃动化测试,如下所示:


服务端测试笔记_服务器

 基于微服务的架构模型中,金字塔模型如下图所示:

服务端测试笔记_服务端_02

2.HTTP协议


总结三次握⼿具体为:


第⼀次握⼿:起初两端都处于CLOSED关闭状态,Client将标志位SYN置为1,随机产⽣⼀个值seq=x,并将该数据包发送给Server,Client进⼊SYN-SENT状态,等待Server确认;


第⼆次握⼿:Server收到数据包后由标志位SYN=1得知Client请求建⽴连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产⽣⼀个值seq=y,并将该数据包发送给Client以确认连接请求,Server进⼊SYN-RCVD状态,此时操作系统为该TCP连接分配TCP缓存和变量;


第三次握⼿:Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,


ack=y+1,并且此时操作系统为该TCP连接分配TCP缓存和变量,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建⽴成功,Client和Server进⼊ESTABLISHED状态,完成三次握⼿,随后Client和Server就可以开始传输数据。


3.HTTP完整请求

   在API的自动化测试中,我们更多关注的是HTTP应用层的交互,因为即使主流的架构如微服务架构,它的通信模式也是基于REST API轻量级的通信模式。在HTTP的协议中,一个完整的HTTP请求流程具体为:

(1)客户端与服务端之间建立TCP的连接请求

(2)客户端向服 务端发送Request的请求

1)请求地址

2)请求方法

3)请求头

4)请求参数

(3)服务端Response相应回复给客户端

1)协议状态码

2)响应头

3)响应数据

(4)客户端与服务端之间关闭TCP的连接请求

4.通信模式

(1)同步交互

1)容易超时,客户端发送请求后,服务端迟迟没有回应客户端的请求

2)如果请求存在大的计算量和逻辑存在问题,就会导致请求堵塞

服务端测试笔记_数据_03

(2)异步交互

1)在异步的交互中,客户端和服务端互相不需要 关注对⽅的存在,只需要关注对应的MQ的消息,客户端与服务端的交互主要是会通过MQ的消息中间作为消息的传递来进⾏交互的

服务端测试笔记_json_04

5.常用请求方法

服务端测试笔记_服务器_05

Post:不仅可以进行添加,还可以删除和修改

Put和Delete:也不一定完全可以修改和删除,因为存在安全隐患

6.常用协议状态码

(1)200:请求成功

(2)301:永久重定向 Moved Permanently(会按照Location首部字段提示的新URI更新书签。页面内容更新,且地址栏网址也更新)

(3)302:临时重定项 Found(不更新书签。页面内容更新,但地址栏网址不更新)

400开头都是客户端的错误

(4)40:Bad Request 客户端请求错误(请求头或者请求参数不对) 

(5)401:Unauthorized (该状态码表示发送的请求需要有通过 HTTP 认证的认证信息)

(6)403:Forbidden (未获得文件系统的访问授权,访问权限出现某些问题)

(7)404:请求的资源不存在

(8)405:不被允许的请求⽅法

500开头的都是服务器的错误

(9)500:服务器内部错误 (服务器端在执行请求时发生了错误)

(10)504:GateWay Timeout(服务器假死,能用但是没有及时从服务器收到请求)

7.请求头/响应头

 服务端测试笔记_json_06

服务端测试笔记_json_07

8.常用请求数据格式

 服务端测试笔记_服务端_08

序列化JSON格式数据:是字典类型

9.



import requests

r=requests.get(url='http://localhost:5000/login')
print('状态协议码:',r.status_code)
print('响应头:',r.headers)
#只能是JSON数据
print('响应数据:',r.json())
#表单、JSON、XML数据
print('响应数据:',r.text)
print('返回二进制的内容',r.content)
print('响应时间:',r.elapsed.total_seconds())
print('cookies:',r.cookies)


10.JSON类型



import requests

r=requests.post(url='http://localhost:5000/login',
json={'username':'liuxun','password':'admin','sex':'女','age':21},
headers={"Content-Type":"application/json"})
print(r.status_code)
print(r.json())


11.Data类型



import requests
import json

r=requests.post(url='http://localhost:5000/login',
data=json.dumps({'username':'liuxun','password':'admin','sex':'女','age':21}),
headers={"Content-Type":"application/json"})
print(r.status_code)
print(r.json())


12.实战



import unittest
import json
import requests

class ApiTest(unittest.TestCase):
def setUp(self) -> None:
self.url='http://localhost:5000/login'
self.data={'username':'liuxun','password':'admin','sex':'女','age':21}
self.headers={'Content-Type':'application/json'}

def test_login_001(self):
r=requests.get(url=self.url)
self.assertEqual(r.status_code,200)
self.assertEqual(r.json()['status'],0)
self.assertEqual(r.json()['data'],'this is a login page')

def test_login_002(self):
r=requests.post(url=self.url,
json=self.data,
headers=self.headers)
self.assertEqual(r.status_code,200)
self.assertEqual(r.json()['username'],'liuxun')

def test_login_username_null(self):
'''校验username参数为空的错误信息'''
r=requests.post(url=self.url,
json={'password':'admin','sex':'女','age':21},
headers={"Content-Type":"application/json"})
self.assertEqual(r.status_code,400)
self.assertEqual(r.json()['message']['username'],'用户名不能为空')

def test_login_password_null(self):
'''校验password参数为空的错误信息'''
r=requests.post(url=self.url,
json={'username':'liuxun','sex':'女','age':21},
headers={"Content-Type":"application/json"})
self.assertEqual(r.status_code,400)
self.assertEqual(r.json()['message']['password'],'账户密码不能为空')

def test_login_age_not_int(self):
'''校验年龄不为整型的错误信息'''
r=requests.post(url=self.url,
json={'username':'liuxun','password':'admin','sex':'女','age':'qsd'},
headers={"Content-Type":"application/json"})
self.assertEqual(r.status_code,400)
self.assertEqual(r.json()['message']['age'],'年龄必须为正正数')

def test_login_sex_boy_girl(self):
'''校验性别不是男的或者不是女的'''
r=requests.post(url=self.url,
json={'username':'liuxun','password':'admin','sex':"qwds",'age':21},
headers={"Content-Type":"application/json"})
self.assertEqual(r.status_code,400)
self.assertEqual(r.json()['message']['sex'],'性别只能是男或者女')

def test_jinyan(self):
r=requests.post(url='http://m.cyw.com/Home/ComSearch/search',
data={'k':'金燕'},
headers={'content_tyoe':'text/html; charset=utf-8','user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'})
self.assertEqual(r.status_code,200)
self.assertEqual(r.json()['procedure'],9)
print(r.json())

def test_wuyuan(self):
r=requests.post(url='http://m.cyw.com/Home/ComSearch/search_com',
data={'k':'婺源'},
headers={'content_tyoe':'text/html; charset=utf-8','user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'})
self.assertEqual(r.status_code,200)
self.assertEqual(r.json()['procedure'],8)
print(r.json())

if __name__ == '__main__':
unittest.main(verbosity=2)