前文回顾:性能测试中记录每一个耗时请求,做完了单接口耗时请求的记录功能,近期又迎来了一批多接口链路压测的需求。刚好趁着这个机会,多实现一些不同场景的链路压测需求,锻炼一波,也能提高自己写的FunTester测试框架的兼容性,可谓一石多鸟,何乐而不为。
非技术内容的分享简略一些。
业务需求
老师在首页看到资源列表后,对相应的列表进行收藏和取消收藏操作。
接口参数
- 收藏
/**
*收藏OK智课
* @param minicourse_id
* @param ktype 0-机构,1-老师
* @return
*/
public JSONObject collect(int minicourse_id = 43089, int ktype = 0, int grade_id = 12) {
String url = OKClassApi.COLLECT
def params = getParams()
params.put("org_id", 80);
params.put("org_type", 1);
params.put("minicourse_id", minicourse_id);
params.put("kid_route", [82]);
params.put("ktype", ktype);
params.put("grade_id", grade_id);
params.put("link_source", 1);//0-教师空间,1-教师机
def response = getPostResponse(url, params)
output(response)
response
}
- 取消收藏
/**
* 取消收藏
* @param minicourse_id
* @param ktype
* @param grade_id
* @return
*/
public JSONObject unCollect(int minicourse_id = 43089, int ktype = 0) {
String url = OKClassApi.UNCOLLECT
def params = getParams()
params.put("minicourse_id", minicourse_id);
params.put("kid_route", [82]);
params.put("ktype", ktype);
def response = getPostResponse(url, params)
output(response)
response
}
测试方案
通过创建不用的用户对象,一个线程绑定一个用户对象,使用该对象进行收藏和取消收藏操作。把一次循环当做一个request
进行数据的统计,计算QPS
和RT
等数据,生成测试结果图像。此处参考:性能测试中图形化输出测试数据。
测试脚本
测试脚本使用Groovy
,方便在服务器上执行,基本跟Java
没有差别。
我用一个AtomicInteger
对象来控制每一个线程创建的用户对象不同,具体方法是OkayBase okayBase = getBase(u.getAndIncrement())
。通过获取每个对象最后一次发出请求的HttpRequestBase
请求,获取请求的Mark
对象值requestid
,拼接到线程标记对象threadmark
中,这样就可以获取到耗时的请求了。具体的数据格式如下:1218_Fdev160809808115759_Fdev160809808182457
。
package com.okayqa.composer.performance.master1_0
import com.fun.base.constaint.ThreadLimitTimesCount
import com.fun.frame.execute.Concurrent
import com.fun.frame.httpclient.ClientManage
import com.fun.utils.ArgsUtil
import com.okayqa.common.Common
import com.okayqa.composer.base.OkayBase
import com.okayqa.composer.function.OKClass
import java.util.concurrent.atomic.AtomicInteger
class BothCollect extends OkayBase {
static AtomicInteger u = new AtomicInteger(0)
static int times
static int thread
public static void main(String[] args) {
ClientManage.init(5, 1, 0, "", 0)
def util = new ArgsUtil(args)
thread = util.getIntOrdefault(0, 200)
times = util.getIntOrdefault(1, 100)
def funs = []
thread.times {
funs << new Fun()
}
new Concurrent(funs, "收藏和取消收藏").start()
allOver()
}
static int getTimes() {
return times
}
static class Fun extends ThreadLimitTimesCount {
OkayBase okayBase = getBase(u.getAndIncrement())
OKClass driver = new OKClass(okayBase)
public Fun() {
super(null, getTimes(), null)
}
@Override
protected void doing() throws Exception {
def collect = driver.collect()
def last = okayBase.getLast()
def value1 = okayBase.getLastRequestId() + CONNECTOR
this.threadmark += value
if (collect.getJSONObject("meta").getIntValue("ecode") != 0) fail(value + "请求出错!")
def collect1 = driver.unCollect()
def value1 = okayBase.getLastRequestId()
this.threadmark += value1
if (collect1.getJSONObject("meta").getIntValue("ecode") != 0) fail(value1 + "请求出错!")
}
}
}
记录方案实现
首先对Base
类进行改造,增加private HttpRequestBase last;
属性,然后在public JSONObject getResponse(HttpRequestBase httpRequestBase)
方法中增加复制操作,如下:
@Override
public JSONObject getResponse(HttpRequestBase httpRequestBase) {
setHeaders(httpRequestBase);
recordRequest(httpRequestBase);
JSONObject response = FanLibrary.getHttpResponse(httpRequestBase);
handleResponseHeader(response);
return response;
}
然后增加last
相关操作:
@Override
public void recordRequest(HttpRequestBase base) {
this.last = base;
}
/**
* 获取最后一个请求
*
* @return
*/
@Override
public HttpRequestBase getRequest() {
return last == null ? FanLibrary.getLastRequest() : last;
}
/**
* 获取最后一个请求的requestid
*
* @return
*/
public String getLastRequestId() {
HttpRequestBase httpRequestBase getLast();
return httpRequestBase.getFirstHeader(Common.REQUEST_ID.getName()).getValue();
}
这里用了一个非空判断,主要是为了防止空指针异常,有些Base
对象初始化并不是通过接口请求实现的。在进行批量Base
对象创建和初始化的时候用的是单线程,代码如下:
def funs = []
thread.times {
funs << new Fun()
}
所以不存在线程安全的问题,故而采取了这种方案。
测试框架相关使用情况可以参考之前的视频讲解:
接口测试视频
- FunTester 测试框架视频讲解(序)
- 获取 HTTP 请求对象 -- 测试框架视频讲解
- 发送请求和解析响应—测试框架视频解读
- json 对象基本操作 -- 视频讲解
- GET 请求实践 -- 测试框架视频讲解
- POST 请求实践 -- 视频演示
- 如何处理 header 和 cookie--视频演示
- FunRequest 类功能 -- 视频演示
- 接口测试业务验证 -- 视频演示
- 自动化测试项目基础 -- 视频讲解
- JSONArray 基本操作 -- 视频演示
- 自动化项目基类实践 -- 视频演示
- 模块类和自动化用例实践 -- 视频演示
- 性能框架多线程基类和执行类 -- 视频讲解
- 定时和定量压测模式实现 -- 视频讲解
- 基于 HTTP 请求的多线程实现类 -- 视频讲解