http协议内容

以下文章中涉及http协议的内容。

https://blog.csdn.net/sjwnghuoyuelaiyu/article/details/155565729?spm=1011.2124.3001.6209

开发者工具抓包

右键后点击检查,进入开发者工具(或者F12)。以部署到本地的禅道为例,抓取登录请求,在登录前打开开发者工具。

找到请求方法为post的包,点击可以查看请求报文和响应报文。

查看请求头中的Content-Type,可以发现提交的数据为表单数据,则可以在负载中查看:

同时查看响应头的Content-Type:为html文本格式,则可以在响应中查看文本内容:

http协议汇总

postman基本使用

向禅道发送get请求

在没有接口文档时,可以通过抓包工具来进行抓包,再通过postman来发送请求。

workspace->Collection->request,添加一个get请求,同时输入URL,由于get请求无请求体,所以请求头中无需指定Content-type,指定请求方法和URL后点击send发送请求。

向禅道发送post请求

post请求有请求体,所以在请求头中要指定Content-type,且请求体的格式依赖于指定的类型。

在登录界面用一个错误密码来登录,通过开发者工具抓取登录请求,获得URL和一些请求参数。

在postman中编辑请求。

向ihrm人力资源管理系统发送post请求:先获取报文。

然后在postman中编辑。

登录提供令牌

后续通过ihrm来进行接口测试,包含从接口测试点分析,测试用例编写与执行,接口自动化测试。

postman进阶使用

变量

变量分为全局变量(Global)、环境变量和集合变量。

全局变量

申明了全局变量后,postman中的任何集合和环境都可以使用该变量。添加全局变量如下:

环境变量

环境变量可以为不同的环境(开发,测试,生产)创建不同的环境配置,同时可以创建一些常用的变量。创建环境变量的步骤如下:

在使用变量的时候(通过{{变量名}}来使用),需要指定环境,如图:

集合变量

集合变量只能在该集合中使用,创建如下:

通过代码实现(请求前脚本)

在发送请求之前,可以通过在请求前脚本里面些内容来定义上述的三种变量,而不需要在软件内定义。

比如在某个集合里通过请求前脚本定义了一个集合变量,该变量就保存到这个集合里面,同时也可也在发送该请求之前在请求前脚本中定义,然后在URL中使用。如图:

这是因为一个请求在发送前,会先执行请求前脚本(若脚本发生错误则不会发送请求),然后发送请求,当服务器返回响应后,执行响应脚本。再举个例子,请求前脚本中定义变量账号和密码,然后在请求体中使用该变量:

发送请求之后,username和password变量也会保存到该集合中(因为定义的是集合变量)。

其余两种变量也可也通过请求前脚本来定义,具体代码如下:

pm.collectionVariables.set("URL_test","http://novel.hctestedu.com/user/login");//集合变量

pm.globals.set("URL_global1","http://novel.hctestedu.com/user/login") //全局变量

pm.environment.set("URL_login","http://novel.hctestedu.com/user/login")//环境变量

接口管理(Collection)

组织和管理API请求的容器,可以将多个请求放在一个Collection管理,可以通过集合运行器一次性执行整个Collection。如图示:

no tests found表示没有写任何断言。

断言

postman中的断言使用JavaScript编写的,分为Pre-request(请求前脚本)和Post-response(响应脚本),响应后脚本的断言包括状态码、检查某个字段等,请求前脚本可以动态设置请求头等。

postman会有些内置的断言,位置如下:

解释一下test的语法:

pm.test(参数1,参数2),test是一个测试用例,参数1是一个字符串,是这个用例的名字,第二个参数是一个函数,pm.response.to.have.status(200)链式调用检查响应状态码是否等于 200。

状态码断言

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});
pm.test("Status is OK", function () {
    pm.response.to.have.status("OK");
});


pm.test("Status code is 200 or 201", function () {
    pm.expect(pm.response.code).to.be.oneOf([200,202]);
});

响应正文断言

响应体是否包含指定字符串

pm.test("Body matches string", function () {
    pm.expect(pm.response.text()).to.include("SUCCESS");
});

响应体(JSON)的msg字段是否等于"SUCCESS"

pm.test("Your test name", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData.msg).to.eql("SUCCESS");
});

响应体为纯文本是检查响应体是否完全相等于指定字符串

pm.test("Body is correct", function () {
    pm.response.to.have.body("response_body_string");
});

同时也可检查响应体(JSON)中的某个字段是否包含(include)某个内容

pm.test("Your test name", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData.data.token).to.include("ey");
});

响应头断言

响应头是否包含Content-Type

pm.test("Content-Type is present", function () {
    pm.response.to.have.header("Content-Type");
});

响应时间断言

响应时间是否少于200ms

pm.test("Response time is less than 200ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(200);
});

接口关联

上一个接口的返回数据是下一个接口的输入参数,所以这两个接口就产生了关联。实现的思路就是:

将上一个请求的响应体中用到的键保存到变量中,后续的接口就可以使用这个环境变量了。

这里以登录成功后将token保存到环境变量中为例,图示如下:

正常发送登录请求,然后在响应断言内写入上述脚本,在发送后,按照执行顺序,在发送成功之后会将token保存到环境变量中,后续就可以携带token来访问了。

这里就以读书屋为例子,我们打开个人中心并抓包,发现Cookie携带了token。

数据驱动

使用数据文件(csv、json)为一个接口提供多个测试数据,核心思想是将测试数据和测试脚本分离,并且可以提取断言。(这个功能需要破解)具体详见:

Postman安装与破解简易教程(亲测有效)-CSDN博客

接下来是具体的操作方式,我们先编写一个csv文件,第一行为键,如图示:

在postman的数据驱动测试中,编写规则如下:

username,password,expected
user1,123,SUCCESS
user2,456,FAIL

然后在postman中编写:

这里的值为{{username}},不是我们之前设置的那些变量,而是csv文件中对应键的名字,接下来执行集合,到如下的界面后,选择文件:

同时我们也可以使用json文件,也可编写动态断言。

动态断言如下:

pm.test("验证返回的 msg 与数据文件中的预期一致", function () {
    var jsonData = pm.response.json();
    var expectedMsg = pm.iterationData.get("expected");
    pm.expect(jsonData.msg).to.equal(expectedMsg);
});

pm.expect(实际值).to.断言方法(期望值);

pm.iterationData存储的是当前迭代对应那一行数据的所有字段。

生成测试报告

这里需要安装newman,具体参考:

接口测试postman/python环境配置-CSDN博客

首先准备集合和环境,导出集合和环境,如下图:

这里导出环境的时候要注意将变量设置为共享。

打开cmd,然后输入下面的指令发送请求:

语法:newman run 集合 (-e 环境) (-d 数据文件) (-r html --reporter-html-export 导出的html文件)

比如要将测试报告导出到桌面上的result.html中,如下:

一个登录接口实例

文件提供了测试相关结果,包含测试点分析、测试用例、生成的集合和环境、生成的测试报告。

测试点分析(ihrm)

基础内容

登录接口+添加用户

requests基本语法

发送get请求

import requests

#发送get请求
#response = requests.get(url,params,data,headers...)
#params data headers都是json格式
url="http://novel.hctestedu.com"
params={#可以加入查询参数
    "name":"1",
    "sex":"girl"
}
response = requests.get(url)
#(response.text)#响应内容内容 字符串
print(response.json)#解析成json格式
print(response.status_code) #状态码
print(response.reason) #状态码的描述 比如OK
print(response.headers)#响应头
print(response.cookies) #返回的cookies

get方法没有请求体,所以请求头中不需要指定Content-type。

发送post请求

import requests

#发送post请求

#表单形式
url="http://novel.hctestedu.com/user/login"
data={
    "username":"123456478901",
    "password":"1234567"
}
headers={
    "Content-type":"application/x-www-form-urlencoded"
}
response = requests.post(url,headers=headers,data=data)
print(response.status_code)
print(response.text)
print(response.json())

Content-type默认为表单形式(application/x-www-form-urlencoded),请求数据为data,若参数为json,则默认为json格式。

#json格式
#不要同时使用 data 和 json 参数,后者会覆盖前者
json={
    "username": "12345678901",
    "password": "123456"
}
headers={
    "Content-type":"application/json"#也可以不声明
}

response = requests.post(url,headers=headers,json=json)
print(response.status_code)
print(response.text)#只是提供演示
print(response.json())

以上为传入json文件。

#修改密码:
url="http://novel.hctestedu.com/user/updatePassword"

headers={
    "content-type":"application/x-www-form-urlencoded",
    "Authorization":"eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3NzcyNjQ2MTYsInN1YiI6IntcImlkXCI6MjA0MzU3MzE4ODg3MjQzNzc2MCxcInVzZXJuYW1lXCI6XCIxODgzNDI1MDk3NFwiLFwibmlja05hbWVcIjpcIjE4ODM0MjUwOTc0XCJ9IiwiY3JlYXRlZCI6MTc3NjY1OTgxNjE3Mn0.XqMmw0bFlfeaMv5A-x348H00GqdWTZiKvPCd4t4Yd4L4zIXBs1Wta4DaF7vg8LDU3BQE3sXtsv-J_OkuI4au-A"
}

data={
    "oldPassword":"1234567",
    "newPassword1":"123456",
    "newPassword2":"123456"
}

response = requests.post(url,headers=headers,data=data)
print(response.status_code)
print(response.text)

Restful风格修改密码时用put。

异常捕获

import requests

#表单形式
url="http://novel.hctestedu.com/user/login"
data={
    "username":"12345678901",
    "password":"123456"
}
headers={
    "Content-type":"application/x-www-form-urlencoded"
}

try:
    response = requests.post(url, headers=headers, data=data,timeout=5)
    response.raise_for_status()
except requests.exceptions.Timeout:
    print("Timeout")#请求超时
except requests.exceptions.RequestException as e:
    print(f"请求失败{e}")

except requests.exceptions.Timeout:捕获超时异常;

except requests.exceptions.RequestException as e:捕获其他requests库产生的异常。包括 ConnectionErrorHTTPErrorTooManyRedirectsSSLError。

pytest+requests接口测试

结合之前学习到的pytest的内容,这里重点关注参数化,以下的类为11个测试用例的执行:

#将每个字典转换为列表在生成一个大列表
mylist=[]
for user in datas:
    user_info = [] #存储username password,Vcode,expected
    user_info.append(user.get("username"))
    user_info.append(user.get("password"))
    user_info.append(user.get("Vcode"))
    user_info.append(user.get("expected"))
    mylist.append(user_info)


#展开测试 参数化
#mylist 中的每个元素(通常是一个元组或列表)会被解包,其第 1 个值赋给第一个参数 username,
# 第 2 个值赋给第二个参数 password,第 3 个值赋给第三个参数 Vcode,第 4 个值赋给第四个参数 expected
class Test02():
    @pytest.mark.parametrize('username,password,Vcode,expected', mylist)
    def test02(self, username, password, Vcode, expected):
        data={
            "username": username,
            "password": password,
            "Vcode": Vcode
        }
        response = requests.post(URL, headers=headers, data=data)
        assert response.status_code == 200
        assert response.json().get("msg") == expected

这个项目会放在文档的开头,结合上面用postman测试的结果,要用到测试数据data11.json,可以直接调用。

这部分测试详情看下一篇文章,pytest+requests测试登录接口。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐