Camille-接口测试

* 接口:不同的系统之间相互连接的部分,是一个传递数据的通道
* 接口测试:检查数据的交换、传递和控制管理过程
网络模型:
OSI七层模型
应用层
表示层
会话层
传输层
网络层
数据链路层
物理层

TCP/IP四层模型
应用层
传输层
网络层
网络接口层


TCP/IP协议栈
DNS域名解析
TELNET远程终端协议
HTTP超文本传输协议
FTP文件传输协议
SMTP发邮件协议
POP3收邮件协议

TCP/UDP 
IP、ARP、RARP、ICMP、IGMP
各种通讯网络接口(以太网等)(物理网络)

应用层
传输层(段)
网络层(包)
数据链路层(帧)
物理层(比特流)

常见接口协议:
Network Access     LAN connection  WAN connection
 Internet       IP 
Transport     TCP  UDP
Application FTP  HTTP  SMTP  email   DNS  TFTP

RPC协议:以本地代码调用的方式实现远程执行
主要用于公司内部的服务调用
常见的RPC协议:
Dubbo
gRPc
THrift

> HTTP协议
请求:
请求行:method url protocol
请求方法:GET、POST、PUT、DELETE、HEAD
请求头:Host Cookies User-Agent
请求参数: query
请求体:JSON XML FORM
响应:
响应状态行
响应头
响应体

URI和URL

* URI,统一资源标识符,用来唯一的标识一个资源。
* URL,统一资源定位符,它是一种具体的 URI
* URL 结构:`https://www.baidu.com/s?wd=霍格沃兹&rsv_spt=1`
  1. 协议:`http`
  2. 域名:`www.baidu.com`
  3. 端口:跟在域名后面,域名和端口之间使用“:”作为分隔符,非必须,如果省略端口部分将采用默认端口
  4. 路径:`/s`
  5. 请求参数:`wd=霍格沃兹&rsv_spt=**1`

HTTP响应状态码:
* 1xx 临时响应,表示通知信息,请求收到了或正在进行处理
* 2xx 表示成功,接受或知道了
  * 200 成功
* 3xx 表示重定向,要完成请求还必须才去进一步的行动
  * 301 永久移动
  * 302 临时移动
* 4xx 表示客户端请求错误
  * 403 未授权
  * 404 未找到
* 5xx 表示服务端错误
  * 500 服务器内部错误
  * 503 服务不可用

## RESTful 架构
* Restful:Representational State Transfer
* 借助于 HTTP 协议的基本请求方法代表资源的状态切换
  * GET:获取资源
  * POST:新增或者更新
  * PUT:更新资源
  * DELETE:删除资源

# 接口测试用例设计
## 接口测试流程
需求分析-测试设计-测试用例评审-测试执行-验收-预发布-上线

接口测试思路:
接口幂等性-重复提交
故障注入-Redis故障降级测试
故障注入-服务故障转移测试
线程安全测试-并发测试
线程安全测试-分布式测试
线程安全测试-数据库读写安全测试
基本功能流程测试-冒烟测试
基本功能流程测试-正常流程覆盖测试
基于输入域的测试-边界值测试
基于输入域的测试-特殊字符校验
基于输入域的测试-参数类型校验
基于输入域的测试-必选参数校验
基于输入域的测试-组合参数校验
基于输入域的测试-有效性校验
基于输入域的测试-默认值校验
基于输入域的测试-排重逻辑

## Postman
* 官网下载地址
  * https://www.postman.com/downloads

##Postman使用
#发送 GET 请求
* 新建请求
* 填写请求方式:GET
* 填写请求 URL:
  * https://ceshiren.com/
  * https://httpbin.ceshiren.com/get
* 填写请求参数: para_key = para_value
#发送POST请求
* 请求方式:POST
* 请求 URL:https://httpbin.ceshiren.com/post
* 请求参数
  * FORM 格式:Body –> form-data
  * JSON 格式:Body –> raw –> JSON
  * 文件格式:Body –> form-data –> File
## 查看接口响应

* 响应体
* 响应头
* 响应状态
## 操作头信息

* 添加请求头
* 修改请求头
## 宠物商店接口文档分析

* 接口文档:https://petstore.swagger.io
* 宠物的增删改查
## 接口测试用例设计

* 宠物的增删改查冒烟测试用例
## Postman 完成接口测试

## 运行测试集

* 测试集页面 -> Run 按钮

* 创建测试集
* 编写断言
* 运行测试集
* 查看测试结果
## 断言

* 验证响应状态码
* 验证响应体中是否包含某个字符串
* 验证 JSON 中的某个值是否等于预期的值
* 验证响应体是否与某个字符串完全相同
* 验证响应头信息中的 Content-Type 是否存在
* 验证响应时间是否小于某个值
// Status Code:Code is 200
// 验证响应状态码
pm.test("响应状态码为 200", function () {
    pm.response.to.have.status(200);
});

// Response Body:contains string 
// 验证响应体中是否包含某个字符串
pm.test("响应体中包含预期的字符串", function () {
    pm.expect(pm.response.text()).to.include("doggie");
});

// Response Body:JSON value check
// 验证 JSON 中的某个值是否等于预期的值
pm.test("宠物名称为 doggie", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData[0].name).to.eql("doggie");
});

// Response Body:Is equal to a string
// 验证响应体是否与某个字符串完全相同
pm.test("响应体正确", function () {
    pm.response.to.have.body("response_body_string");
});

// Response Body:Content-Type header check
// 验证响应头信息中的 Content-Type 是否存在
pm.test("Content-Type is present", function () {
    pm.response.to.have.header("Content-Type");
});

// Response time is less than 200ms
// 验证响应时间是否小于某个值
pm.test("Response time is less than 200ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(200);
});

## 变量

* Postman 中变量的种类与作用域
  * Data:在测试集中上传的数据
  * Environment:环境范围
  * Collection:集合范围
  * Global:全局范围
  * Local:在脚本中设置的变量

## 变量定义

* 全局变量:Environments -> Globals
* 测试集变量:测试集页面 -> Variables
* 环境变量:Environments -> +

## 变量的使用

* 请求 URL, Params 参数或 Body 表格或JSON/XML 文本中通过 `{ {变量名}}` 使用
* 在 Pre-request Script 和 Tests 脚本中使用封装好的语句获取或者设置对应变量

```
// 获取全局变量
var status = pm.globals.get("status");
// 输入到控制台
console.log(status)

// 获取测试集变量
var petId = pm.collectionVariables.get("petId");
// 获取环境变量
var url = pm.environment.get("baseURL");

// 设置全局变量
pm.globals.set("status", "sold");
// 设置测试集变量
pm.collectionVariables.set("petId", 0);
// 设置环境变量
pm.environment.set("baseURL", "");
```

## 变量的优先级

* 优先级从高至低为:Data -> Enviroment -> Collection -> Global -> Local

* 验证响应状态码
* 验证响应体中是否包含某个字符串
* 验证 JSON 中的某个值是否等于预期的值
* 验证响应体是否与某个字符串完全相同
* 验证响应头信息中的 Content-Type 是否存在
* 验证响应时间是否小于某个值

```
// Status Code:Code is 200
// 验证响应状态码
pm.test("响应状态码为 200", function () {
    pm.response.to.have.status(200);
});

// Response Body:contains string 
// 验证响应体中是否包含某个字符串
pm.test("响应体中包含预期的字符串", function () {
    pm.expect(pm.response.text()).to.include("doggie");
});

// Response Body:JSON value check
// 验证 JSON 中的某个值是否等于预期的值
pm.test("宠物名称为 doggie", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData[0].name).to.eql("doggie");
});

// Response Body:Is equal to a string
// 验证响应体是否与某个字符串完全相同
pm.test("响应体正确", function () {
    pm.response.to.have.body("response_body_string");
});

// Response Body:Content-Type header check
// 验证响应头信息中的 Content-Type 是否存在
pm.test("Content-Type is present", function () {
    pm.response.to.have.header("Content-Type");
});

// Response time is less than 200ms
// 验证响应时间是否小于某个值
pm.test("Response time is less than 200ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(200);
});
```

## 运行测试集

* 测试集页面 -> Run 按钮

![](https://material.hogwarts.ceshiren.com/resource/mock/L1/ppt/assets/2022-04-20-15-00-18.png)

## 查看测试结果

![](https://material.hogwarts.ceshiren.com/resource/mock/L1/ppt/assets/2022-04-20-15-06-02.png)

## 变量

* Postman 中变量的种类与作用域
  * Data:在测试集中上传的数据
  * Environment:环境范围
  * Collection:集合范围
  * Global:全局范围
  * Local:在脚本中设置的变量

## 变量定义

* 全局变量:Environments -> Globals
* 测试集变量:测试集页面 -> Variables
* 环境变量:Environments -> +

## 变量的使用

* 请求 URL, Params 参数或 Body 表格或JSON/XML 文本中通过 `{ {变量名}}` 使用
* 在 Pre-request Script 和 Tests 脚本中使用封装好的语句获取或者设置对应变量

```
// 获取全局变量
var status = pm.globals.get("status");
// 输入到控制台
console.log(status)

// 获取测试集变量
var petId = pm.collectionVariables.get("petId");
// 获取环境变量
var url = pm.environment.get("baseURL");

// 设置全局变量
pm.globals.set("status", "sold");
// 设置测试集变量
pm.collectionVariables.set("petId", 0);
// 设置环境变量
pm.environment.set("baseURL", "");
```

## 变量的优先级

* 优先级从高至低为:Data -> Enviroment -> Collection -> Global -> Local

* 验证响应状态码
* 验证响应体中是否包含某个字符串
* 验证 JSON 中的某个值是否等于预期的值
* 验证响应体是否与某个字符串完全相同
* 验证响应头信息中的 Content-Type 是否存在
* 验证响应时间是否小于某个值
// Status Code:Code is 200
// 验证响应状态码
pm.test("响应状态码为 200", function () {
    pm.response.to.have.status(200);
});

// Response Body:contains string 
// 验证响应体中是否包含某个字符串
pm.test("响应体中包含预期的字符串", function () {
    pm.expect(pm.response.text()).to.include("doggie");
});

// Response Body:JSON value check
// 验证 JSON 中的某个值是否等于预期的值
pm.test("宠物名称为 doggie", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData[0].name).to.eql("doggie");
});

// Response Body:Is equal to a string
// 验证响应体是否与某个字符串完全相同
pm.test("响应体正确", function () {
    pm.response.to.have.body("response_body_string");
});

// Response Body:Content-Type header check
// 验证响应头信息中的 Content-Type 是否存在
pm.test("Content-Type is present", function () {
    pm.response.to.have.header("Content-Type");
});

// Response time is less than 200ms
// 验证响应时间是否小于某个值
pm.test("Response time is less than 200ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(200);
});

**Fiddler抓包:**
* 官网:https://www.telerik.com/fiddler/fiddler-classic
* Fiddler 是位于客户端和服务器端的 HTTP 代理
* 也是目前最常用的 HTTP 抓包工具之一
* 功能
  * 监控流量
  * 支持解密 HTTPS
  * 查看分析接口数据
  * 修改请求的数据
  * 修改服务器返回的数据
  * 设置断点

* 设置:Tools -> Options -> Connections
* 确认抓包端口:默认为 8888
* 默认勾选 Act as system proxy on startup
![image|514x449](upload://buGiPM2vyOjUtOoVLTX3qWG5ZGv.png)

配置:
* Tools -> Fiddler Options -> HTTPS
* 勾选 Decrypt HTTPS Traffic
* 弹出安装证书弹窗 -> 选择【Yes】-> 点击 【Yes】安装证书
* 点击 Actions -> Open Windows Certificate Manager 查看证书

抓取移动端请求:
* Tools -> Fiddler Options -> Connections
* 勾选 Allow remote computers to connect
* 移动端与电脑处于同一网络下
* 移动端配置网络代理
  * 代理服务器主机:电脑IP
  * 代理服务器端口:8888
* 浏览器输入 http://电脑ip:8888 下载 Fiddler 证书进行安装
* Statistic:性能与统计数据
* Inspectors:请求和响应数据
* Filter:制定过滤规则
* Composer:编辑发出请求
## AutoResponder
* 拦截某一请求,并重定向到本地的资源,或者使用 Fiddler 的内置响应
* 用于调试服务器端代码而无需修改服务器端的代码和配置
#断点
* 菜单栏 -> Rules -> Automatic Breakpoints ->选择断点方式
* 状态栏点击
  * 请求前断点:向上箭头
  * 响应后断点:向下箭头
* 命令行下输入
  * 请求前断点:`bpu xxx`
  * 响应后断点:`bpafter xxx`
弱网:
* 菜单栏 -> Rules -> Performance -> Simulate Modem Speeds
* 修改网络配置参数
  * 菜单栏 -> Rules -> Customize Rules…
  * 搜索关键词 simulate
  * 修改延迟时间

Postman参数传递:
* 创建登录接口
* 成功后在 Test 中提取 token
* 保存 token 到测试集变量
//获取响应数据的json对象
var jsonData = pm.response.json();
//从json对象中提取token值
var token = jsonData.data.token;
//把token值设置为测试集变量
pm.collectionVariables.set("token", token);

## 请求前脚本中获取参数

```
// 构造登录请求
const loginRequest = { 
    url: 'http://litemall.hogwarts.ceshiren.com/wx/auth/login', 
    method: "POST", 
    header: 'Content-Type: application/json',
    body: { 
        mode: 'raw',
        raw: JSON.stringify({'username': 'user123', "password": "user123"})
    } 
}; 

// 发送请求 
pm.sendRequest(loginRequest, function (err, response) {
    if (err) {
        console.log(err);
    } else {
        console.log(response.json());
        pm.collectionVariables.set("token", response.json().data.token);
    }
});
```
弱网测试:
* 按照移动的特性,一般应用低于 3G、弱信号的 Wifi 可以划分为弱网
* 弱网测试是健壮性测试的重要部分,对移动端测试必不可少
* 弱网测试主要进行弱网状态下的功能测试,同时关注用户体验
包含:带宽、丢包、延迟
Mock测试场景:
* 前后端数据交互
* 第三方系统数据交互
* 硬件设备解耦
好处:
* 不依赖第三方数据
* 节省工作量
* 节省联调

* 匹配规则
* 模拟响应

## 协议分析工具

* 网络监听:TcpDump + WireShark
* 代理 Proxy
  * 推荐工具:手工测试charles [全平台]、安全测试burpsuite [全平台 java]
  * 自动化测试:mitmproxy
  * 其他代理: fiddler [仅windows]、AnyProxy [全平台]
* 协议客户端工具: curl、postman
## tcpdump

* 参数:
  * -x 十六进制展示
  * -w file 保存文件
* 表达式:
  * ip tcp 协议
  * host 主机名
  * port 80
  * src 来源 dst 目的
  * and or () 逻辑表达式
## WireShark

## 抓取访问百度的数据包

* `sudo tcpdump host www.baidu.com -w /tmp/tcpdump.log`
* `curl http://www.baidu.com`
* 停止tcpdump
* 使用wireshark打开/tmp/tcpdump.log

## [Test Double 测试替身](https://martinfowler.com/bliki/TestDouble.html)

* **Dummy 占位对象** 对象被传递但从未实际使用过。通常它们仅用于填充参数列表。
* **Fake 假对象** 对象实际上有工作实现,但通常采取一些捷径,这使得它们不适合生产(内存数据库就是一个很好的例子)。
* **Stubs 桩对象** 为测试期间调用提供预设答案,通常根本不响应任何超出测试程序的内容。
* **Spies 间谍对象** 它们还根据调用方式记录一些信息。其中一种形式可能是电子邮件服务,它记录发送了多少消息。
* **Mocks 模拟对象** 是我们在这里谈论的:预先编程的对象,这些期望形成了它们期望接收的调用的规范。

|概念|监听调用|预设期望|按需预设期望|真实数据|真实数据修改|
|---|---|---|---|---|---|
|Dummy 傀儡对象||||||
|Spy 间谍对象|✅|||||
|Fake 假对象|✅|||✅||
|Stub 桩对象|✅|✅||||
|Mock 模拟对象|✅|✅|✅|✅|✅|
## Mitmproxy 简介

* mitmproxy:交互式的命令行工具
  * 注意:不支持 windows
* mitmweb:基于浏览器的界面交互工具
* mitmdump:简单的终端输出,可以编写强大的插件和脚本

> 官方网站:https://mitmproxy.org/

## Mitmproxy 安装

推荐使用 python 进行安装

```
// 方式一
pip install mitmproxy==5.2.0

// 方式二
pip install pipx
pipx install mitmproxy==5.2.0

// 验证是否安装成功
mitmdump --version
```
PC端证书配置:
1. 配置电脑代理
2. 启动 mitmproxy
3. 在浏览器输入地址 mitm.it
4. 选择对应系统下载证书并安装
## 移动端证书配置

1. 在手机配置代理,ip 配置为**电脑的 ip 地址**,端口配置为 mitmproxy 监听端口
2. 启动 mitmproxy
3. 在手机浏览器输入地址 mitm.it
4. 选择 Android,下载并安装,即可成功抓取手机端的 https 的数据包
工具:
* mitmproxy
* mitmweb
* mitmdump
## mitmdump 参数介绍

* `-p` 参数,指定监听端口,默认监听 8080
* `-s` 参数,执行 python 脚本
## 核心组件

* Addons(插件):https://docs.mitmproxy.org/archive/v5/addons-overview/
* Events(事件):https://docs.mitmproxy.org/archive/v5/addons-events/
## 脚本编写

```
# 创建 python 文件 request_demo.py
def request(flow):
    flow.request.headers["myheader"] = "value"
```

```
// mitmdump 执行命令
mitmdump -p 8999 -s xx/request_demo.py
```
## 实现 MapLocal

1. 创建一个本地文件,设定响应数据
2. 编写脚本,在请求事件中,即给响应对象复制
3. 执行命令
4. 访问浏览器验证结果

```
from mitmproxy import http

# request 名称不能被改变
# mitmdump 加载这个脚本的时候
# 当有请求来的时候,就会回调这个request方法
# flow 为抓取到的请求信息
def request(flow: http.HTTPFlow) -> None:
    
    # 发起请求,判断url是不是等于一个路径
    if flow.request.pretty_url == "http://example.com/path":
        # 一旦请求的url等于我们的预期,我们就会创造一个response
        # 这个response比较简单,请求状态码为200,响应数据位hello world
        # 响应数据格式为html
        flow.response = http.HTTPResponse.make(
            200,  # (optional) status code
            b"Hello World",  # (optional) content
            {"Content-Type": "text/html"}  # (optional) headers
        )
```

## 实现 Rewrite

1. 修改股票名称
2. 修改股票价格

```
from mitmproxy import http

# response 名称不能被改变
# mitmdump 加载这个脚本的时候
# 当拦截到响应之后,就会回调这个 response 方法
# flow 为抓取到的接口信息
def response(flow: http.HTTPFlow):
    # 打印响应内容
    print(flow.response.content)
```

相关推荐

  1. Camille-接口测试

    2024-02-02 17:28:01       31 阅读
  2. 测试接口参数测试

    2024-02-02 17:28:01       36 阅读
  3. 接口测试:项目测试

    2024-02-02 17:28:01       25 阅读
  4. 接口测试接口测试面试基础常识

    2024-02-02 17:28:01       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-02 17:28:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-02 17:28:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-02 17:28:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-02 17:28:01       18 阅读

热门阅读

  1. 如何保证接口幂等

    2024-02-02 17:28:01       32 阅读
  2. docker搭建nginx的RTMP服务器的步骤

    2024-02-02 17:28:01       22 阅读
  3. 51单片机——串口通信编程

    2024-02-02 17:28:01       29 阅读
  4. go 问题记录(日志丢失)

    2024-02-02 17:28:01       34 阅读
  5. conda环境更改jupyter的环境

    2024-02-02 17:28:01       30 阅读
  6. 【C语言】(10)循环结构

    2024-02-02 17:28:01       32 阅读