• 接口自动化测试


    1.基础知识

    1.接口测试原理

    接口测试的原理就是模拟客户端向服务器发送请求,服务器接收请求报文后对相应的报文做处理并向客户端返回应答,客户端接收应答的过程。

    2.接口测试点及用例设计方法

    接口测试采用的方法其实与黑盒测试一致的,甚至可以把接口测试理解为没有界面的功能测试。只不过接口测试的关注点主要在请求和响应上。另外,还包括接口的安全接口的性能等。常用的用例设计有等价类,边界值法等。
    一般测试用例的设计要从单接口参数的校验到整个业务功能点的验证,还可以验证一些安全性和异常情况。
    在这里插入图片描述

    3.接口测试要点

    • 检查接口返回的数据是否与预期结果一致。
    • 接口测试结果检查通常需要通过SQL语句从数据库内进行查询确认。
    • 检查接口的容错性,假如传递数据的类型错误时是否可以处理。
    • 接口参数的边界值,例如传递的参数足够大或为负数时,接口是否可以正常处理。
    • 接口的性能,http请求接口大多与后端执行的SQL语句性能,算法等比较相关。
    • 接口的安全性,外部调用的接口尤为重要,一般每个接口都要进行鉴权验证。

    4.常见HTTP状态码

    状态码含义
    1**临时响应并需要请求者继续执行操作
    2**请求成功。操作被成功接收并处理
    3**重定向代码,用于已经移动的文件并且在头信息中指定新的地址信息
    4**客户端错误,请求包含语法错误或者无法完成请求
    5**服务器错误,服务器在处理请求的过程中发生错误

    比如:
    200 服务器成功处理请求
    404 未找到资源
    410 找到资源,但现在已不存在
    500 内部服务器错误
    503 服务器目前无法为请求提高服务
    302 临时重定向
    304 客户端的缓存资源时最新的,要客户端使用缓存

    5.HTTP基础知识

    • DNS:Domain Name Server 域名服务器
      http:// www.baidu.com: 80/ adv_search? w=py&order=false# tag
      在这里插入图片描述

    • HTTP报文格式分为两种

    请求报文:请求行,请求头部,回车换行,消息体
    响应报文:状态行,响应头部,回车换行,消息体

    HTTP由请求和响应构成,是一个标准的客户端服务器模型(B/S架构)。HTTP协议永远都是客户端发起请求,服务器回送响应。B/S架构又叫浏览器/服务器模型,严格意义上说,这个B不仅仅只是浏览器,凡是能够发生HTTP请求的对象或者工具,都可以叫做客户端。

    • HTTP请求组成部分

    URL地址,请求参数(可选),请求头,请求体(仅限POST请求)
    对于响应内容部分,主要关注两个点:响应状态码,响应内容

    • HTTP工作过程

      1. 浏览器输入
      2. dns域名解析:域名与IP映射(第一次访问去DNS找对应IP,不是第一次访问则本机存有IP)
      3. 建立tcp连接(三次握手)
      4. 发送http request:请求信息
      5. web服务器接收请求
      6. 应用服务器处理业务逻辑
      7. 关闭tcp连接:请求响应完成。如果浏览器在其头部信息中加入了connection:keep-alive,则tcp连接将任然保持打开状态。
      8. 浏览器:渲染响应页面
    • Get和Post
      Get:从服务器端获取资源或数据
      Post:向服务器端提交数据
      Get和Post的区别:
      1)Get请求一般用于向服务器请求获取一个资源,没有副作用,一般会在客户端做缓存。Post请求一般用于向服务器提交数据并让其去完成一件事,所以这个操作是有副作用的,不会在客户端做缓存,
      2)Get请求发送数据的时候,一般会将请求数据放在url字符串中发送给服务器端,所以从安全性角度来看相对没有Post请求安全性搞,所以get请求一般不会用于比较隐私数据的传输。而Post请求时将请求数据放在请求体body里面,所以一般用于表单数据,登录数据等数据的传输。

    6.接口自动化测试工具

    7.token

    • cookie
      存在于客户端,由服务器端通过set.cookie方法来进行设置。

    • session
      存在于服务器端的内存中,主要用于和cookie一起来验证客户端的登录状态。

    • token
      token是服务器端生成的一串字符串,用作于客户端进行请求的一个令牌。
      token运行的原理:
      (1)客户端第一次登录成功时,由服务器端生成,并保存于服务器端的数据库中,服务器端再将token值返回给客户端。
      (2)客户端拿到token值之后,会进行保存(保存位置由服务器端指定)。
      (3)后面客户端发送请求时,会将token值附带在请求参数中发送给服务器进行验证。
      (4)服务器端收到客户端的请求之后,会取出token值与保存在本地数据库中的token值进行比较。
      (5)如果两个token是一致的,说明用户已登录成功,当前用户处于登录状态。
      (6)如果没有这个token值,说明用户没有登录过。
      (7)如果token值已经发生改变,说明原登录信息已经失效,需要重新登录。

    2.抓包工具

    1.chrom抓包

    右键-》检查-》找到网络
    在这里插入图片描述
    需要关注的字段
    在这里插入图片描述
    在这里插入图片描述
    响应内容
    在这里插入图片描述

    2.Fiddler抓包(PC端,手机端)

    1.原理

    Fiddler是通过改写HTTP代理,让数据从它那通过,来监控并且截取到数据。在打开它的那一瞬间,它就已经设置好了浏览器的代理了。当你关闭的时候,它又帮你把代理还原了。在这里插入图片描述

    2.下载安装

    官网下载:https://www.telerik.com/fiddler
    按照指示填写,下载,然后傻瓜式安装,一直点击是就可以安装成功。

    3.抓取数据信息说明

    在这里插入图片描述

    名称含义
    #抓取HTTP Request的顺序,图标表示请求状态和响应状态
    ResultHTTP状态码 (重点关注)
    Protocol请求使用的协议,常用HTTP,HTTPS
    Host请求地址的主机名
    URL请求资源的位置
    Body请求的大小
    Caching请求的缓存过期时间或者缓存控制值
    Content-Type请求响应的类型
    Process发送此请求的进程:进程ID
    Comments允许用户为此回话添加备注
    Custom允许用户设置自定义值

    要访问HTTPS协议需要设置一下:Tools –> Fiddler Options ,选择HTTPS,勾选Decrypt HTTPS TrafficDecrypt,然后后面弹出的窗口都点击yes/是,点击Actions,最后点击OK

    4.数据详细字段说明

    在这里插入图片描述

    名称含义
    Statistics请求的性能数据分析
    Inspectors查看数据内容(常用)
    AutoResponder允许拦截指定规则的请求
    Composer自定义请求发送服务器
    Filters请求过滤规则(常用)
    Timeline请求响应时间

    5.过滤

    过滤最常用,过滤掉不需要的抓包数据,只显示自己需要的,这样看起来会方便很多。

    • Filddler过滤
      在这里插入图片描述
      2)命令过滤
      ?+字符串
      在这里插入图片描述
      @+host
      在这里插入图片描述

    =+状态码
    在这里插入图片描述

    5.断言

    断言目的是为了验证服务端功能。
    在这里插入图片描述

    • 全局断言Rules -> Automatic Breakpoints

    在这里插入图片描述
    在这里插入图片描述
    Before Request断言
    在这里插入图片描述
    Before Response断言
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    • 命令断言
      Before Request断言:bpu 域名或IP
      取消断言bpu
      Before Response断言:bpafter 域名或IP
      取消断言bpafter
      在这里插入图片描述

    3.Request库(发送请求)

    安装Requests库:pip install requests

    1.利用requests发送get请求

    import requests
    
    def test1():
        resp = requests.get('http://www.taobao.com')
        print(resp.status_code)  # 响应的状态码信息
        print(resp.text)  # 获取响应对象的文本信息
        print(resp.url)  # 获取响应对象所对应的请求地址
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.利用requests发送get请求+参数

    import requests
    
    # 直接在url上添加请求参数
    def test1():
        resp = requests.get('https://baidu.com/s?wd=python')  # 自动在url后面添加参数
        print(resp.text)
        
    # get请求+参数
    def test2():
        data = {
            'wd': 'python'
        }  # 请求参数
        resp = requests.get('https://baidu.com/s', params=data)  # 自动在url后面添加参数
        print(resp.text)
    
    if __name__ == '__main__':
        test2()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.利用requests发送post请求

    import requests
    
    def test1():
        resp = requests.post('https://ynuf.aliapp.org/service/um.json?_bx-v=2.0.31')
        print(resp.status_code)  # 响应的状态码信息
        print(resp.text)  # 获取响应对象的文本信息
        print(resp.url)  # 获取响应对象所对应的请求地址
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.在post请求中以json方式传递参数

    import requests
    
    # 以json格式传
    def test1():
        data = {"username": "test", "password": "123", "age": 18, "phone": 1588888888}  # 字典格式是json
        resp = requests.post('', json=data)
        print(resp.text)
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5.添加或者修改headers信息

    如果浏览器访问,响应正常,如果不是浏览器来访问,是爬虫或代码访问,则响应不正常。这个需要用到headers信息。

    import requests
    
    # 含有header访问才能跟浏览器访问显示一样的
    def test1():
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
        }
        resp = requests.get('', headers=headers)
        print(resp.text)
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.在请求头中添加cookie信息

    import requests
    
    # 绕过登录,想要获取登录之后的信息,需要带上Cookie
    def test1():
        headers = {
            'Cookie': ''  # 每次都要更新
        }
        resp = requests.get('', headers=headers)
        print(resp.text)
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7.利用session对象保持会话状态

    需要登录才能访问的接口,对于这种一定要使用session会话来帮助保存会话信息

    import requests
    
    # 利用session保持会话状态
    def test1():
        sess = requests.Session()  # 创建一个session会话对象,帮助我们保存客户端的会话信息
        data = {
            'username': 'admin',
            'password': 'admin123'
        }
        sess.post('', data=data)  # 操作登录
        resp2 = sess.get('')  # 请求登录之后的接口
        print(resp2.text)
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    8.利用requests上传和下载文件

    import requests
    
    # 上传文件不带参数
    def test1():
        files = {
            'file': open('test.txt', 'rb')
        }
        resp = requests.post('', files=files)
        print(resp.text)
        
    # 上传文件带其他参数
    def test2():
        data = {
            'batchname': 'GB20210707'  # 抓包的
        }
        files = {
            'batchfile': open('Test.xls', 'rb')
        }
        resp = requests.post('', data=data, files=files)
        print(resp.text)
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    9.加密接口测试

    询问开发用的什么加密方法

    import requests
    
    # 加密接口请求
    def test1():
        uid, name, password, salt = '3', 'qcj', '123456', 'LZ7dYxCj5S68ucAh'
        import hashlib  # 有MD5加密方法
        hl = hashlib.md5()
        hl.update(('{}-{}-{}-{}'.format(uid, name, password, salt)).encode('utf-8'))
        sign = hl.hexdigest()  # 对hl对象中保存的字段进行md5加密算法
        print(sign)
        data = {
            'uid': '3',
            'sign': sign
        }
        resp = requests.post('', json=data)
        print(resp.text)
    
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    10.接口参数关联

    import requests
    
    # 接口参数关联(下一个请求的入参是上一请求的出参)
    def test1():
        data = {
            'username': 'qcj',
            'password': '123456'
        }
    
        resp = requests.post('', data=data)  # 请求第一个接口
        resp_json = resp.json()  # 第一个接口响应的json内容
        auth_token = resp_json['data']  # 提取第一个接口的data出参
    
        headers = {
            'auth-token': auth_token
        }
        resp = requests.get('', headers=headers)  # 请求第二个接口
        print(resp.text)
        
    if __name__ == '__main__':
        test1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    4.接口测试返回值的处理

    • 为什么我们需要关心接口返回的响应值
      原因:我们需要对返回的响应内容进行断言,对比实际结果与预期结果,从而验证接口工作是否正常。

    • 接口响应内容的形式?
      主要有三种形式:JSON格式的字符串;HTML源码;程序员自定义的字符串。

    • 主要的处理方式?
      处理方式1:正则表达式来进行处理,这种方法适合以上三种响应内容形式。
      处理方式2:lxml库进行处理,这种方式仅针对返回内容是HTML源码形式的。
      处理方式3:直接使用requests库自带的json方法进行处理,这种方式仅针对返回内容是json形式的。

    1.re库(正则表达式)

    获取指定内容最常用的一个正则表达式.*?的使用。

    在这里插入图片描述
    在这里插入图片描述

    • 正则表达式特殊字符组合练习
    import re  # 正则表达式的库
    
    log = '''
        now: 2020-04-15  23:44:34 id:    ST0013 status:      nok
        now: 2020-04-26 09:33:14 id: DAMX002 status:  good
        now: 2020-04-17 22:27:39 id: SIMKOIF0 status:     well
        now: 2020-04-18 16:45:30 id: 04 status: unknown
    '''
    
    # \s表示空格  \d{4}表示4个十进制数字开始  \s+表示一个或多个空格
    dt = re.findall('now:\s(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})', log)
    # \s+表示一个或多个空格 \w*表示任意个字母  \d+表示一个或多个十进制数  
    sid = re.findall('id:\s+(\w*\d+)', log)
    # \s+表示一个或多个空格  \w+表示一个或多个字母
    status = re.findall('status:\s+(\w+)', log)
    print(dt)
    print(sid)
    print(status)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果:
    在这里插入图片描述

    • 正则表达式.*?法取出文件里面的某个字段值
    import re  # 正则表达式的库
    
    # 从文件中截取某个字段的值
    with open('zzlb.txt', 'r') as f:
        content = f.read()
        result = re.findall('"SNAME":"(.*?)"', content) # 截取文件中SNAME字段的值
        print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 正则表达式.*?法取出HTML源码里面的某个字段值
    import re  # 正则表达式的库
    
    # 正则表达式中换行符的处理
    content = '''
    
    '''
    result = re.findall("href='(.*?)'", content, re.S) # 处理html格式的,有换行符的需要加re.S print([item.strip() for item in result]) # \n相当于空格,可以用strip去掉
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    运行结果:
    在这里插入图片描述

    2.lxml库(处理响应内容是HTML源码)

    lxml库进行处理,这种方式仅针对返回内容是HTML源码形式的。

    例子:登录进去的页面,会有注销或者退出登录的字段,验证登录是否成功,可以提取登录进去页面的HTML源码中的注销字段来验证。

    # 解析HTML文档格式响应
    from lxml import etree
    import requests
    
    def verifylogin():
        headers = {
            'cookie': ''  # 登录后的cookie
        }
        resp = requests.get('', headers=headers) # 登录后的url
        resp.encoding = 'utf-8'  # 防止中文乱码
        html = etree.HTML(resp.text) # 获取登录后页面的HTML
        result = html.xpath("//a[@href='javascript:logoff()']/text()") # 获取指定a元素上显示的文本信息
        print(result)
    
    if __name__ == '__main__':
    	verifylogin()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.requests库(处理响应内容是json形式)

    查看json格式的网站:bejson
    要先清楚响应内容的json结构,层级,字典里面的层级。
    响应内容:
    在这里插入图片描述

    import requests
    
    def verifylogin():
        headers = {
            'cookie': ''  # 登录后的cookie
        }
        data = {
             'page': '1',
             'rows': '5'
        } # 参数
        resp = requests.post('', headers=headers, data=data) # 登录后的url
        resp_json = resp.json()  # 通过json方法将resp对象转换为一个json对象
        print(resp_json['people'][1]['lastName'])
    
    if __name__ == '__main__':
    	verifylogin()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果:Hunter
    在这里插入图片描述

    5.Apifox

    Apifox是接口管理,开发,测试全流程集成工具,通过一套系统,一份数据,解决多个系统之间的数据同步问题。只要定义好接口文档,接口调试,数据Mock,接口测试就可以直接使用,无需再次定义。接口文档和接口开发调试使用同一个工具,接口调试完成后即可保证和接口文档定义完全一致。高校,及时,准确。
    Postman + Swagger + Mock + JMeter = ApiFox

    • 下载安装
      官网:https://www.apifox.cn/ 下载安装按照指示来很简单
      在这里插入图片描述

    • 创建get请求
      在这里插入图片描述

    • 创建Post请求
      在这里插入图片描述

    • 接口关联(上一个请求的响应内容有作为下个请求的入参)
      第一个请求后置操作添加变量
      在这里插入图片描述
      第二请求,可将变量值作为headers值,或参数值
      在这里插入图片描述

    • 多条数据
      在这里插入图片描述
      在这里插入图片描述

    • 命令的方式运行接口自动化脚本
      (1)先安装apifox-cli库,cmd中输入命令
      nmp install -g apifox-cli
      如果报错unable to verify the first cortificato,则分别输入以下两个命令
      npm config set strict-ssl false
      nmp install -g apifox-cli

      (2)然后将apifox中的测试用例导出来
      在这里插入图片描述 (3)将到处的自动化脚本和测试数据文件放在一一个目录,在这个目录下打开cmd,输入命令
      apifox run 测试用例文件名 -d 测试数据文件名 -n 2 -r html

    -d 测试用到的数据文件,比如data.csv
    -n 循环次数
    -r 在当前路径生成测试报告,并指定报告格式
    例如:apifox run 回归测试 -d 测试数据文件名 -n 2 -r html

    例如:apifox run 回归测试.apifox-cli.json -d data.csv -n 2 -r html

    • 导出接口文档
      在这里插入图片描述

    • 相比其他接口测试工具的优点
      (1)可以创建系统,邀请多个系统人员参与。
      (2)进行接口设计,然后添加数据变成接口测试用例,如果修改接口设计,同时测试用例也会被修改。
      (3) 执行接口测试用例,响应是JSON格式会自动录入接口设计文档。
      (4)多个测试用例组成集合,可以一键运行,生成测试报告。
      (5)可以连接数据库,执行sql脚本,能生成接口代码。
      (6)可以多条测试数据导入,进行测试

  • 相关阅读:
    用go实现cors中间件
    【动态规划】leetcode 62. 不同路径
    Redis---第一篇
    【编译原理】语法分析
    某全球领先的芯片供应商:优化数据跨网交换流程,提高安全管控能力
    c++ 图的重构识别
    MapReduce 排序三种实现方式
    高精度减法
    软考高级软件架构师论文——论软件架构评估
    巡检管理系统哪一款简单实用?如何解决传统巡检难题,实现高效监管?
  • 原文地址:https://blog.csdn.net/XGZ2IT/article/details/127969161