接口自动化从入门到精通(持续更新)

接口自动化之request模块

一、既然我们有postman\jmeter这些的接口测试工具,为什么要做接口做自动化?

①原因
1.敏捷开发,接口一般数量很大,团队实现接口测试,版本控制。
2.功能太死板,有些接口完全无法实现(复杂的加密接口,签名接口等)
3.接口项目当中有多种不同协议的接口。
4.排错,定位接口问题不方便,结合抓包实现。
5.没有办法生成美观的报告。
6.多接口串联,数据库验证,日志监控,
7.有些公司做web自动化+接口自动化。

②目前市场行情

1.主流测接口工具(中小型项目或公司)jmeter、postman、apifox

2.接口自动化测试(大中型项目或公司)python+requests+pytest+allure+logging+jenkins

3.基于平台的接口自动化(超大型的公司项目)Diango+vue java+mvc

二、回顾HTTP协议

请求:
请求行(请求方式,请求路径,协议)
请求头(常用)
        Content-Type:客户端发送的数据格式
                applcaton/x-www-form-urlencoded 表单
                applcation/json   json数据
                multipart/form-data  文件上传
                application/octrent-stream  二进制文件上传
        Accept:接收的数据格式
        X-Requested-with 异步请求
        User-Agent:客户端类型
请求正文;请求数据
响应:
        响应行,(状态码、状态信息)

        响应头,

        响应正文:响应数据

三.requests请求命令

requests是第三方库,主要用于发送http请求来进行接口自动化

window系统使用cmd打开命令窗口,安装命令pip install requests

请求

第一种方式,底层代码就是调用的第二种方式
 

1.requests.get(url, params=None, **kwargs)   发送get请求
2.requests.post(url, data=None, json=None, **kwargs)   发送post请求
3.requests.delete((url, **kwargs)  发送delete请求
4.requests.put(url, data=None, **kwargs)     发送put请求

第二种方式:底层代码就是调用的第三种方式

1 requests request(method, url, **kwargs)   最核心的方法

第三种方式:自动的处理有cookie关联的接口,有些关联接口用相同cookie没有cookie会报错

requests.session().request( self,
        method,#请求方式
        url,#请求路径
        params=None,  #params:查询字符串,在接口路径后面以?传递的参数,多个函数之间用&分割,
        data=None, #data:表单参数,content-Type: applcaton/x-www-form-urlencoded
        json=None, #json:json参数 content-Type:applcation/json 
        files=None, #files:文件参数content-Type:multipart/form-data 
        headers=None, #请求头
        cookies=None, #cookies信息
---------------------------------
        auth=None, #鉴权
        timeout=None, #超时
        allow_redirects=True, #重定向
        proxies=None, #代理
        hooks=None,  #钩子
        stream=None, #文件下载
        verify=None, #证书验证
        cert=None, #CA证书
       )

联系:第一种调第二种,第二种调三种

区别:第三种能够自动处理有cookie关联的接口,前两种都是单独的请求(类似于jmeter的http中cookie管理器)示例

class TestApi:
    csrf_token=''
    # 创建一个session对象
    sess=requests.session()
    def test_phpwind(self):
        # 使用session对象发送请求
        response = TestApi().sess.request(method="get",url="http://47.107.116.139/phpwind/")
        #response = requests.get("http://47.107.116.139/phpwind/")
        print(response.text)
        csrf_token=re.search('name="csrf_token" value="(.*?)"',response.text).group(1)
        TestApi().csrf_token=csrf_token
        assert "本站新帖" in response.text
    def test_login(self):
        data={
            "username": "user",
            "password": "123",
            "crf_token": TestApi().csrf_token,
            "back_url": "http://47.107.116.139/phpwind/",
            "invite": "",
        }
        headerss = {
            "Accept": "application/json, text/javascript,/; q=0.01",
            "X-Requested-With": "XMLHttpRequest"
        }
        # 使用session对象发送请求
        response = TestApi().sess.request(method="post",url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun",data=data,headers=headerss)
       # response = requests.post("http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun",data=data,headers=headerss)
        print(response.json())

四、发送请求细节详解

 (1)params传参:查询字符串参数
传参方式:在接口路径后面以?传递的参数,多个参数之间用&分隔
传参细节:对参数内容进行了urlencode编码(内容以ASCII的方式呈现 

class TestApi:
    def test_login(self ):
        params={
            "username":"admin",
            "password":"123456"
        }
        response = requests.get("http://127.0.0.1:8000/api/login/",params=params)

(2)data传参:Form表单参数
1.添加了一个请求头:Content-Type:application/x-www.form-urlencoded
2.对参数内容进行了urlencode编码(内容以ASCII的方式呈现)

class TestApi:
    def test_login(self ):
        data={
            "username":"admin",
            "password":"123456"
        }
        response = requests.get("http://127.0.0.1:8000/api/login/",data=data)

(3)json传参:json参数
1.添加请求头:Content-Type:application/json
2.对参数进行:Unicode编码

class TestApi:
    def test_login(self ):
        data={
            "username":"admin",
            "password":"123456"
        }
        response = requests.get("http://127.0.0.1:8000/api/login/",json=data)

(4)files传参:文件参数
1.添加请求头:Content-Type:multipart/form-data
2.构建了一个表单数据,把文件的内容以二进制的方式加到body里面,

两种文件上传的方式:
第一种:打开一个已经存在的文件上传

class TestApi:
    def test_login(self ):
        data={
            "upload":open("C:\\Users\\1.jpg","rb")
        }
        response = requests.get("http://127.0.0.1:8000/api/login/",files=data)

第二种:自己构造(图片name,文件内容,上传格式)

    def test_login(self):
        data = {
            "upload":  ("a.png", "文件内容", "image/jpg")
        }
        response = requests.get("http://127.0.0.1:8000/api/login/", files=data)

上传多个文件

    def test_login(self):
        data = {
            "upload":  ("a.png", "文件内容", "image/jpg")
            "upload":open("C:\\Users\\1.jpg","rb")

            
        }
        response = requests.get("http://127.0.0.1:8000/api/login/", files=data)

同时传递表单参数和文件参数:(表单不会进行urlencode骗码)


    def test_login(self):
        data1 = {
            "upload":  ("a.png", "文件内容", "image/jpg")
        }
        data2= {
            "username": "zhuyifan",
            "password": "123456"
        }
        response = requests.get("http://127.0.0.1:8000/api/login/", data=data2,files=data1)   

五、requests响应

 响应:response对象

rep=requests.request()

#返回字符串的数据
print(rep.text)
#返回二进制字节格式的数据
print(rep.content)
#返回字典格式的数据,除了他是方法其他全是属性
print(rep.json())
#状态码
print(rep.status_code)
#返回状态信息
print(rep.reason)
#返回cookie信息
print(rep.cookies)
#返回编码格式
print(rep.encoding)
#返回响应头信息
print(rep.headers)
#返回请求方式
print(rep.method)
#返回请求路径
print(rep.url)
#返回请求数据
print(rep.body)

六、接口自动化测试实战

简介

线性脚本:NO

unittest、pytest用例管理框架

前提:pip install pytest

pytest默认规则:
1.Py文件必须以test开头或者_test结尾。
2.类名必须以Test开头
3.测试用例必须以test _开头

发送接口步骤

1.import pytest 导入pytest框架

import requests 导入requests库

requests.post()发送post请求,括号中需要填写url、data或者json,其他的包括必填的请求头 

发送post请求data和json区别

区别

在发送POST请求时,datajson都是requests库中用于传递请求体的参数。然而,它们在使用和期望的输入格式上有所不同。

  1. data 参数
    • data 参数期望接收一个字符串或一个元组列表 (key, value) 对,通常用于发送表单编码的数据application/x-www-form-urlencoded
    • 如果你传递一个字典给 datarequests 库会自动将其转换为查询字符串,并且设置 Content-Type 为 application/x-www-form-urlencoded
    • 例如:
      payload = {'key1': 'value1', 'key2': 'value2'}
      response = requests.post(url, data=payload)
  2. json 参数
    • json 参数期望接收一个Python对象(通常是字典或列表),requests库会将其自动序列化为JSON格式,并且设置Content-Typeapplication/json
    • 使用json参数时,你不需要手动序列化Python对象,requests会为你处理这个转换。
    • 例如:
       
          
      payload = {'key1': 'value1', 'key2': 'value2'}
      response = requests.post(url, json=payload)

  • 格式data 期望表单编码的数据,而 json 期望JSON格式的数据。
  • Content-Typedata 通常设置 Content-Type 为 application/x-www-form-urlencoded,而 json 设置 Content-Type 为 application/json
  • 序列化:当你使用 data 参数传递字典时,requests 会自动将其转换为查询字符串;而当你使用 json 参数时,requests 会自动将Python对象序列化为JSON字符串。

总结
你应该根据API的要求和你的数据类型选择使用 data 还是 json。如果你发送的是JSON格式的数据,并且API期望接收 application/json 类型的请求体,那么你应该使用 json 参数。如果你发送的是表单编码的数据,那么你应该使用 data 参数。如果你不确定,应该查看API的文档来确定正确的参数和格式。

格式错误互相转换

json.dumps(data)  序列化        把字典格式的数据转换为str格式

json.loads(data)  反序列化        把str格式转换为字典格式

总结:

使用data只能传简单的只有键值对的dict或者str格式。json一般只能传dict格式,简单的复杂的和嵌套的都可以      

接口关联  

:第1个接口的返回值中的数据作为第2个接口的参数。


正则表达式:

使用re库,只能提取字符串的数据,
        re.search:提取一个值,得到的是一个对象,通过下标group(1)取值,如果没有匹配列值则返回None
        re.findall:提取多个值,得到的是一个列表,通过下标【1】取值,,如果没有匹配到值可返回None

import re

class TestApi:
    def test_phpwind(self):

        response = requests.get("http://47.107.116.139/phpwind/")
        print(response.text)
        search=re.search('name="csrf_token" value="(.*?)"',response.text).group(1)
        print(search)
        findall=re.findall('name="csrf_token" value="(.*?)"',response.text)[0]
        print(findall)

然后进行接口关联

class TestApi:
    #通过类变量
    csrf_token=''
    def test_phpwind(self):

        response = requests.get("http://47.107.116.139/phpwind/")
        print(response.text)
        csrf_token=re.search('name="csrf_token" value="(.*?)"',response.text).group(1)
        TestApi().csrf_token=csrf_token
        assert "本站新帖" in response.text
    def test_login(self):
        data={
            "username": "zhangshang",
            "password": "123",
            "crf_token": TestApi().csrf_token,
            "back_url": "http://47.107.116.139/phpwind/index.php",
            "invite": "",
        }
        headerss = {
            "Accept": "application/json, text/javascript,/;q=0.01",
            "X-Requested-With": "XMLHttpRequest"
        }

        response = requests.post("http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun",data=data,headers=headerss)

Jsonpath表达式:jsonpath 

方法:jsonpath.jsonpath ,通过下标[1]取值,,如果没有匹配到值可返回None
{access_loken': 72_Elind8uyQPa_bGMm3nNEc_ebvrRhIVR8910-0BA6DIKeyky INOigXt4far1to9qloUWzryTBws-EWItFNFmN1XRFUF1INW-k6l69c-yfPlmBOqdmTFFJaV3DgANSEAEAVIN', 'expires_in': 7200, mashang:[{name":"百里"}.{"name":"北凡"}"}
语法规则:
(1) $根节点
(2).取子节点
$.access token
$.expires in
(3)取列表中的值
$.mashang[0]  ={name":"百里"}                  $.mashang[0].name  =  百里
$.mashang[1] ={"name":"北凡"}
(4).递归取值,无论几层都取出来
$..name  =["百里”,“北凡”]

jsonpath.jsonpath(response.json(),'$..msg')[0]

七、接口自动化封装

第一步

核心是requests request()   最核心的方法,

将发送请求统一改成requests.request

通过session实现cookie鉴权,

用一个会话去发送请求,其中的东西都不会断,包括里边的cookie,就相当于用电话不用短信

更改前

以下是引用的token转化的类变量

将cookie转化为类变量

更改后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值