1、背景说明
项目思想:BDD
行为驱动开发的思想褒贬不一,这里不多说。遵循的宗旨能解决业务痛点的思想就是好思想。
接口测试工具在实际的业务测试场景中往往会遇到一些使用上的局限性,自定义扩展要求技术较高,如果二次开发工具成本较大;
处于探索期的自动化团队,接口易于入手
接口测试用例后期的版本、维护、变更、存储遇到很多问题;
接口测试多人协同没有友好的支持;
接口测试用例没有统一的规范后期管理混乱、测试报告(业务场景接口)展示针对性、可读性差;
…
2、技术选型
cucumber 框架 官方链接 || GitHub链接
简介:Cucumber 是一个能够理解用普通语言 描述的测试用例的支持行为驱动开发(BDD)的自动化测试工具,用多种语言编写,支持Java、JavaScript、Ruby、.Net等多种开发语言。
rest-assured框架 官方链接 || GitHub链接
简介:REST-assured 用于方便 REST 服务测试的 JAVA DSL。
xeger正则表达式 GitHub链接
mock框架 GitHub链接
(微信不能外链接,以上可自行查找)
3、整体的框架思想
架构图谱
单框架的了解
cucumber-环境配置
需要装俩idea插件用于自定义关键字自动提示和feature编写帮助
https://plugins.jetbrains.com/plugin/9164-gherkin/versions
https://plugins.jetbrains.com/plugin/7212-cucumber-for-java
或者直接在idea编译器内Settings->Plugins搜索:gherkin&&Cucumber for Java 安装即可
4、项目使用流程
idea创建一个maven项目使用自定义模板,配置如下:
GroupId=io.cucumber
ArtifactId=cucumber-archetype
Version=6.6.0
#踩坑,高版本结合其他框架使用遇到一些不适配的问题,目前使用6.6.0版本比较稳定
自动生成cucumber项目模板
feature简单示例
Feature: rest-assured+cucumber测试实例
Scenario: get请求示例场景
Given 接口参数
|params1|value1
|params2|value2
When 发起接口请求 "http://127.0.0.1:8091/api/test"
Then 断言 "code"="1"
StepDefinitions类接收处理
public String body;
public Response response;
@Given("接口参数")
public void getubjectMajorstype(List<Map<String, String>> vegetables) {
Map reqMap = vegetables.get(0);
this.body = reqMap.toString();
System.out.println("subjectMajorstype = " + reqMap.toString());
}
@When("发起接口请求 {string}")
public void sendReq(String url){
System.out.println("真正调用接口"+url);
RequestSpecification request = given().contentType(ContentType.JSON).body(body);
this.response = request.get(url);
String responseBody = this.response.getBody().asString();
System.out.println("当前响应结果:"+responseBody);
}
@Then("断言 {string}={string}")
public void assertRes(String aValue){
if ( aValue.equals("0")){
System.out.println("=======断言通过=========");
}else {
System.out.println("==========断言失败==========");
}
}
rest-assured和cucumber遵循规范:
given-when-then逻辑思想
rest-assured具体使用可以参考GitHub的示例
public Response post(Map<String, String> headers, String body, String url) {
request = given().headers(headers).contentType(ContentType.JSON).body(body);
response = request.post(url);
}
框架核心实现与测试用例分离
- 核心实现与测试用例分类
- 只关注接口的测试用例和维护
- 核心实现
核心实现基础是上面创建的cucumber模板maven项目,根据实际需求功能不断完善…
- 测试用例pom文件引用核心实现,通过git管理测试用例版本
接口用例编写的关键字说明
接口执行顺序说明
用例执行前逻辑控制:预加载数据、获取场景名、环境变量…
用例执行中逻辑控制:根据各自场景使用关键字控制…
用例执行后逻辑控制:收集测试用例结果,展示用例测试结果数据…
接口用例关键字控制说明:整体遵循given-when-then思想
given 来控制请求前:api、参数、mock、文件流等功能使用
when 来控制发送什么样的请求:支持restful风格请求-get/post/delete/put,以及对应mock的请求类型
then 来控制获取响应后的参数化、响应结果的断言、数据库断言等
自定义关键字说明
Param 支持 :application/x-www-form-urlencoded 和 form-data格式
Body支持:raw 的json格式
ParamsJsonX支持:是把Param写成json格式
JSONPATH_GET_MONGO:是rest-assured的jsonpath使用,用于取出当前响应结果的某一对象值,也支持参数化
常用写法
• 获取children的列表rest-assured的jsonpath取值写法
Then JSONPATH_GET_MONGO
|data[0].children|children|
• 获取children第二条记录rest-assured的jsonpath取值写法
Then JSONPATH_GET_MONGO
|data[0].children[1]|children|
• 获取children第二条记录的yearId值rest-assured的jsonpath取值写法
Then JSONPATH_GET_MONGO
|data[0].children[1].yearId|yearId|
• 获取children所有的yearId值(列表)rest-assured的jsonpath取值写法
Then JSONPATH_GET_MONGO
|data[0].children.yearId|yearId|
• 获取特定的yearId值rest-assured的jsonpath取值写法【目前公司用的,支持该写法】
Then JSONPATH_GET_MONGO
| data[0].children.findAll{ children -> children.year == "2020"}.yearId[0] | yearId_2020 |
• 标准版的jsonpath取值【rest-assured的json-path不支持这种写法】
Then JSONPATH_GET_MONGO
| data[0].children[?@.year == "2020"}.yearId | yearId_2020 |
JSONPATH_ASSERT_EQUALS:是rest-assured的jsonpath使用,用于断言参数化当前响应结果与期望结果是否相等
INIT_MOCK:开启mock,mock读取顺着当前用例执行结束而结束
CONTENT_TYPE_IN_MULTIPART:开启文件上传支持
#采坑:目前rest-assured底层只支持一个文件的上传,不支持多个文件同时上传
FILECONTENT_ASSERT_CONTAINS:文本内容断言
ASSERT_MYSQL_SQL:SQL断言
todo。。。自定义扩展
接口用例编写实战分享
1.前置条件:
以企业微信为示例演示接口用例编写流程
企业微信测试地址:https://work.weixin.qq.com/
企业微信错误查询工具:https://open.work.weixin.qq.com/devtool/query?e=50001
配置idea编译器服务端地址
2.feature项目目录结构(和核心实现分离,只看到接口用例):
3.测试流程步骤
简单的测试操作流程:获取鉴权token->新增部门成员->编辑新增成员名称->删除被编辑名称的成员操作流程
#初始化变量池
@test
Feature: 初始化数据
Scenario: 初始化变量数据
Given INIT_MOCK
Given INI_VAR_DATA
"""
name: 测试名_Random(Char[4])
mobile: 152Random(Long[5])5317
email: testerRandom(Char[4])@qq.com
wxName: zyRandom(Char[2])
alias: alias_Random(Char[4])
userid: userid_testRandom(Char[4])
editUserid: 修改名称操作_Random(Char[2])
"""
# 1.获取access_token
Scenario: 获取access_token
Given API "/cgi-bin/gettoken"
And Param
"""
corpid : ww27d6f876d80ceec6
corpsecret: yiXycY2QFDwD9HysYNk6hF7NFnt1CxBybuei1YKVaVw
"""
When GET
Then STATUS "200"
Then JSONPATH_GET_MONGO
|access_token|getToken|
Then JSONPATH_ASSERT_EQUALS
| errmsg | ok |
# 2.新增企业微信成员
Scenario: wx_新增人员接口
Given API "/cgi-bin/user/create?access_token=${getToken}"
And Body
"""
{
"userid": "test_user",
"name": "test_name",
"position": "测试工程师",
"alias": "背锅侠",
"mobile": "15238380000",
"email":"76556@qq.com",
"department": [3],
}
"""
When POST
Then STATUS "200"
# jsonpath断言使用
Then JSONPATH_ASSERT_EQUALS
| errcode | 0 |
# 3.断言新增人员是否成功
Scenario Outline: wx_读取人员接口
Given API "/cgi-bin/user/get"
And Param
"""
access_token: ${getToken}
userid: ${userid}
"""
When GET
Then STATUS "200"
Then JSONPATH_ASSERT "<jsonPath>" equals "<value>"
Examples:
| jsonPath | value |
| errmsg | ok |
# 4.编辑新增成员_修改name
Scenario: 编辑新增企业微信成员操作
Given API "/cgi-bin/user/update?access_token=${getToken}"
And Body
"""
{
"userid": "test_user",
"name": "test_name_edit",
"department": [3],
"order": [10],
"position": "测试工程师",
"mobile": "15238305311",
"gender": "1",
"email": "zhangsn@gdev.com"
}
"""
When POST
Then STATUS "200"
Then JSONPATH_ASSERT_EQUALS
| errcode | 0 |
| errmsg |updated |
# 5. 删除微信成员操作
Scenario: 删除新增企业微信成员操作
Given API "/cgi-bin/user/delete?access_token=${getToken}"
#urlencoded格式也可以在Param里写成yaml格式,也可以在url拼接使用
And Param
"""
userid: test_user
"""
When GET
Then STATUS "200"
Then JSONPATH_ASSERT_EQUALS
| errcode | 0 |
通过上面的用例可以看出,需要什么功能只需要引入实现的关键字即可
用例的优化动态参数化和用例可持续执行
目前框架已实现功能
mock数据支持
restful风格接口支持
文件上传支持
jsonPath参数化变量引用支持
CSV文件参数数据引用
断言参数化变量引用支持
数据库断言支持
响应URL链接断言支持
随机函数支持
String 、Char、Long 、Boolean 的数据类型随机生成
各自日期类型和身份证等数据的随机生成
// 生成当前时间
Random(Date[yyyy-MM-dd hh:mm:ss])
// 当前事件为模板指定个别值
Random(Date[2020-MM-dd hh:mm:ss])
Random(Date[yyyy-03-12 08:mm:ss])
// 只生成年月日
Random(Date[yyyy-12-dd])
// 随机生日的身份证号
Random(IDCard)
// 指定生日的身份证号
Random(IDCard[20210312])
4、项目的核心思想
框架的核心实现思想
底层实现思路分析
jenkins集成cucumber报告展示
冒烟测试报告…
1.报告汇总:
2.错误信息展示
3.配置坑:Cucumber reports 报告展示坑,由于配置了mock的config.json数据导致可能识别json文件有点问题,需要指定cucumber.json名即可结果
写在最后附上项目源码地址:
https://github.com/CuiZhongyuan/cucumber-weixin-api-test
由于涉及公司项目核心jar包未开源,公众号后台回复cucumber即可获取打包后依赖jar包,放置maven依赖包com相应路径下即可:
<dependency>
<groupId>com.weixin.api</groupId>
<artifactId>cuke</artifactId>
<version>jxc_2.2.2</version>
<scope>test</scope>
</dependency>
如果你不想一个人野蛮生长,找不到系统的资料,问题得不到帮助,坚持几天便放弃的感受的话,可以加入我们的QQ群:746506216,大家可以一起讨论交流,里面会有各种软件测试资料和技术交流。
资源分享
下方这份完整的软件测试视频学习教程已经上## 标题传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】