在经过这么久的铺垫,​​FunTester​​测试框架分布式版本的工作正式开始了,我首先写了一个单节点的版本,通过​​HTTP​​协议接口进行任务上传,而非像之前设想中的,定时去​​master​​节点进行​​pull​​任务。

此版本为单节点部署,可本地部署,预计下个月开源,主要是考虑到版本不稳定,肯定会进行多轮更改。

当前服务只是针对之前设想的方案(一)(基于​​HttpRequestBase​​对象)进行实践,感兴趣的童鞋可以翻看旧文章:


  • 分布式性能测试框架用例方案设想(一)
  • 基于docker的分布式性能测试框架功能验证(一)

至于方案(二)(基于​​jar​​包方法模板)和方案(三)(基于​​Java/Groovy​​测试脚本)的设想、验证以及实现,后续会慢慢推出。PS:没看错,我已经找找了执行​​Java​​测试脚本的方法。

欢迎大家在使用过程中,多提提意见,多提提需求,当然多多宣传也行。

自费服务器,大家以体验为主。以后实际使用以本地部署为主,公网依然以体验为主,这个服务器费用还是有点贵的。

内测阶段,访问密钥请联系​​FunTester​​作者本人,改接口文档可能会有所变化,请及时关注​​FunTester​​,获取最新动态。我用​​postman​​导出了一份测试Demo(含测试密钥),有兴趣的同学请联系作者本人获取。

Part1接口文档

接口地址:http://124.70.188.11:8080/test/post

请求方式:POST

传参格式:JSON(application/json)

1参数


参数

类型

限制

备注

times

int



thread

int



mode

String


默认ftt

desc

String


任务描述

runup

int


软启动时间

key

String


访问秘钥,找FunTester作者要

request

String


被测请求,格式如下

2非Java语言补充

request也可以通过JSON对象上传参数,文档如下:


参数

类型

限制

备注

requestType

String


请求类型,目前GET/POST

uri

String


请求地址

args

JSON


GET请求参数

json

JSON


POST请求JSON参数

params

JSON


POST请求form表单参数

headers

JSONarray


请求headers(key-value)

3postman截图

分布式性能测试框架单节点内测_测试demopostman传参截图

4请求参数Demo

{
"mode":"ftt",
"request":{
"args":{},
"headers":[],
"requestType":"GET",
"json":{},
"params":{},
"uri":"待测接口地址"},
"times":10,
"thread":1,
"runup":1,
"key":"funtester2021",
"desc":"FunTester分布式测试Demo"
}

Part2Java版本--基于FunTester

这个版本用了​​com.funtester.httpclient.FunRequest​​​类,所以需要下载​​FunTester​​​测试框架的主​​git​​​项目,地址如下:​​https://gitee.com/fanapi/tester​​​,分支​​oker​​。

import com.alibaba.fastjson.JSONObject;
import com.funtester.httpclient.ClientManage;
import com.funtester.httpclient.FunLibrary;
import com.funtester.httpclient.FunRequest;
import com.funtester.utils.DecodeEncode;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;

public class PerSerTest extends FunLibrary {

public static void main(String[] args) {
ClientManage.init(100, 100, 0, EMPTY, 0);
JSONObject res = new JSONObject();
res.put("times", 100);
res.put("thread", 10);
res.put("key", "");
res.put("mode", "ftt");
res.put("desc", "FunTester分布式测试Demo");
res.put("runup", 10);
String url = "http://待测接口";
HttpGet get = FunLibrary.getHttpGet(url);
FunRequest request = FunRequest.initFromRequest(get);
res.put("request", request.toJson());
HttpPost httpPost = getHttpPost("http://124.70.188.11:8080/test/post", res.toString());
JSONObject response = getHttpResponse(httpPost);
output(response);
String table = response.getJSONObject("data").getString("table");
output(DecodeEncode.unzipBase64(table));
}

}

Part3Java版本--通用版

这个版本将所有的参数都用​​JSON​​​格式,​​Python​​​版本的也参考这个构建请求参数。我​​Python​​已经生疏,由于时间关系,我等其他大佬实现了之后会做分享。

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.funtester.httpclient.ClientManage;
import com.funtester.httpclient.FunLibrary;
import com.funtester.utils.DecodeEncode;
import org.apache.http.client.methods.HttpPost;

public class PerSerTest2 extends FunLibrary {

public static void main(String[] args) {
ClientManage.init(100, 100, 0, EMPTY, 0);
JSONObject res = new JSONObject();
res.put("times", 10);
res.put("thread", 10);
res.put("key", "");
res.put("mode", "ftt");
res.put("desc", "FunTester分布式测试Demo");
res.put("runup", 10);
JSONObject re = new JSONObject();
re.put("requestType", "GET");
re.put("uri", "http://待测接口");
re.put("args", new JSONObject());
re.put("json", new JSONObject());
re.put("params", new JSONObject());
re.put("headers", new JSONArray());
res.put("request", re);
HttpPost httpPost = getHttpPost("http://124.70.188.11:8080/test/post", res.toString());
JSONObject response = getHttpResponse(httpPost);
output(response);
String table = response.getJSONObject("data").getString("table");
output(DecodeEncode.unzipBase64(table));

}

}

Part4Groovy版本

我给​​Groovy​​的一个定义就是快速构建测试脚本,这里非常明显差异,对比以上两种​​Java​​​版本的代码,​​Groovy​​非常简单。

import com.alibaba.fastjson.JSONObject
import com.funtester.httpclient.ClientManage
import com.funtester.httpclient.FunLibrary
import com.funtester.httpclient.FunRequest

class PerSerTest extends FunLibrary {

public static void main(String[] args) {
ClientManage.init(100,100,0,EMPTY,0)
def res = new JSONObject()
res.times = 100
res.thread = 10
res.key = ""
res.mode = "ftt"
res.desc = "FunTester分布式测试Demo"
res.runup = 10
String url = "http://"
def get = FunLibrary.getHttpGet(url)
def request = FunRequest.initFromRequest(get)
res.request = request.toJson()
def get1 = getHttpPost("http://124.70.188.11:8080/test/post",res.toString())
def response = getHttpResponse(get1)
output(response)


}

}

Part5接口响应

接口响应是一个​​JSON​​​对象,也是一个​​com.funtester.base.bean.PerformanceResultBean​​对象,后面我会奉上代码,这里先看见控制台输出。

INFO-> 请求uri:http://124.70.188.11:8080/test/post , 耗时:14217 ms , HTTPcode: 200
INFO->
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
> {
> ① . "code":0,
> ① . "data":{
> ② . . . "rt":18,
> ② . . . "failRate":0.0,
> ② . . . "threads":10,
> ② . . . "deviation":"53.29%",
> ② . . . "qps2":259.4752186588921,
> ② . . . "errorRate":0.0,
> ② . . . "executeTotal":801,
> ② . . . "total":1801,
> ② . . . "qps":555.5555555555555,
> ② . . . "startTime":"2021-06-01 18:09:17",
> ② . . . "endTime":"2021-06-01 18:09:20",
> ② . . . "mark":"FunTester分布式测试Demo011809",
> ② . . . "table":"eJzj5VIgCNxK80JSi0tSi552tD3d0fx0T/+zrd0v1k91Sc3NVzA0UCjJKEpNTCFsDi8XL37bglKLC/LzilMVQjJzU60UKnSLU4syE3MU8kpzdRQqdXNTUzIT8wjZQdgdCrmZeQoQw6yMFXKLdXITK6yMzI2ATCI0E/QFpeDRtA4gIs4no7aM2jJIbXk0rRWI6GMT2IpRm0ZtGrVp1KZRm0ZtGrVp1KZRm7DY9GhaExAp0INqBiIKqBYgwkVBW5bIDUy4DwEIcgne"
> ① . },
> ① . "FunTester":200
> }
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~

其中最外层的​​FunTester​​​是框架加上去的,并非真正的响应。​​data​​​中的内容就是性能测试的结果,也就是​​com.funtester.base.bean.PerformanceResultBean​​​对象。其中如果想看​​table​​内容的话,需要添加两行代码:

   String table = response.getJSONObject("data").getString("table");
output(DecodeEncode.unzipBase64(table));

控制台输出如下:

分布式性能测试框架单节点内测_测试框架_02图形化展示测试数据

Part6com.funtester.base.bean.PerformanceResultBean

package com.funtester.base.bean
import com.funtester.db.mysql.MySqlTestimport com.funtester.frame.Outputimport com.funtester.utils.DecodeEncode
/**
* 性能测试结果集
*/class PerformanceResultBean extends AbstractBean implements Serializable {
private static final long serialVersionUID = -1595942562342357L;
/**
* 测试用例描述
*/ String mark
/**
* 开始时间
*/ String startTime
/**
* 结束时间
*/ String endTime
/**
* 表格信息
*/ String table
/**
* 线程数
*/ int threads
/**
* 总请求次数
*/ int total
/**
* 平均响应时间
*/ int rt
/**
* 吞吐量,公式为QPS=Thead/avg(time)
*/ double qps
/**
* 通过QPS=count(r)/T公式计算得到的QPS,在固定QPS模式中,这个值来源于预设QPS
*/ double qps2
/**
* 理论误差,两种统计模式
*/ String deviation
/**
* 错误率
*/ double errorRate
/**
* 失败率
*/ double failRate
/**
* 执行总数
*/ int executeTotal
PerformanceResultBean(String mark, String startTime, String endTime, int threads, int total, int rt, double qps, double qps2, double errorRate, double failRate, int executeTotal, String table) { this.mark = mark this.startTime = startTime this.endTime = endTime this.threads = threads this.total = total this.rt = rt this.qps = qps this.qps2 = qps2 this.errorRate = errorRate this.failRate = failRate this.executeTotal = executeTotal this.table = DecodeEncode.zipBase64(table) this.deviation = com.funtester.frame.SourceCode.getPercent(Math.abs(qps - qps2) * 100 / Math.max(qps, qps2)) Output.output(this.toJson()) Output.output(table) MySqlTest.savePerformanceBean(this) }
}

FunTester,腾讯云年度作者​、Boss直聘签约作者​,GDevOps官方合作媒体,非著名测试开发,欢迎关注。


  • FunTester测试框架架构图初探
  • 性能测试软启动初探
  • 多项目登录互踢测试用例
  • 压测中测量异步写入接口的延迟
  • 分布式性能测试框架用例方案设想(一)
  • 敏捷团队的自动化测试【译】
  • 自动化测试框架的完整指南【译】
  • moco框架接口命中率统计实践
  • 无脚本测试
  • 好书推荐《Java性能权威指南》

分布式性能测试框架单节点内测_java_03