前两天写了一篇文章​​重放浏览器单个请求性能测试实践​​,介绍了如何从浏览器中复制请求,来获取请求对象,进而完成单接口的性能测试工作。今天就来分享一下如何通过这种方式进行多接口性能测试。

复制请求

这里我用了复制所有请求,通过一些过滤条件进行筛选需要测试的请求。

重放浏览器多个请求性能测试实践_性能测试

这个复制出来的数据太多了,格式基本和之前的一样,我就不重复展示了。

获取HttpRequestBase对象

这里唯一和前文不同的就是从一个文件中获取多个​​HTTPrequestbase​​​请求对象,这里我用了一个​​CurlRequestBase​​​,只要检测到结束标志符号**--compressed**,立刻生成一个​​HTTPrequestbase​​​对象,紧接着把初始的​​CurlRequestBase​​对象还原,这样不会干扰下一个请求的数据。

具体方法如下:

    /**
* 从curl复制结果中获取请求
* @param path
* @return
*/
public static List<HttpRequestBase> getRequests(String path) {
def fileinfo = WriteRead.readTxtFileByLine(LONG_Path + path).stream().map {it.trim()}
def requests = []
def base = new CurlRequestBase()
fileinfo.each {
if (it.startsWith("curl")) {
def split = it.split(" ", 2)
def type = split[0]
def value = split[1]
base.url = value.substring(value.indexOf('h'), value.lastIndexOf("'"))
} else if (it.startsWith("-H")) {
def split = it.split(" ", 2)[1].split(": ")
base.headers << FanLibrary.getHeader(split[0].substring(1), split[1].substring(0, split[1].lastIndexOf("'")))
} else if (it.startsWith("--data-raw")) {
base.params = getJson(it.substring(it.indexOf("'") + 1, it.lastIndexOf("'")).split("&"))
base.type = RequestType.POST
} else if (it.startsWith("--compressed")) {
requests << getRequest(base)
base = new CurlRequestBase()
}
}
requests.findAll {
it != null && it.getFirstHeader("accept").getValue().contains("application/json")
}
}

/**
* 将curlrequestbase对象转换成HTTPrequestbase
* @param base
* @return
*/
static HttpRequestBase getRequest(CurlRequestBase base) {
if (filterWords.any {
base.url.contains(it)
}) return
base.type == RequestType.GET ? FunRequest.isGet().setUri(base.url).addHeader(base.headers).getRequest() : FunRequest.isPost().setUri(base.url).addHeader(base.headers).addParams(base.params).getRequest()
}

中间用了两次过滤,一次是根据​​CurlRequestBase​​​对象的​​url​​​属性进行过滤,主要是过滤掉​​js​​​、​​css​​​、图片、网页和媒体文件包括无用的请求。一次是通过请求头​​accept​​​字段中​​application/json​​​信息过滤,把响应结果不是​​JSONObject​​的请求也过滤掉。

    public static def filterWords = [".js", ".png", ".gif", ".css", ".ico", "list_unread", ".svg", ".htm", ".jpeg",".ashx"]

if (filterWords.any {
base.url.contains(it)
}) return
        requests.findAll {
it != null && it.getFirstHeader("accept").getValue().contains("application/json")
}

性能测试

脚本如下:

    public static void main(String[] args) {
def requests = getRequests("get")
output(requests.size())
def threads = []
requests.each {
output FanLibrary.getHttpResponse(it)
threads << new RequestThreadTime<HttpRequestBase>(it, 100, null)
}
new Concurrent(threads, "FunTester测试").start()
testOver()
}

控制台输出

~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
> {
> ① . "rt":40,
> ① . "total":9993,
> ① . "qps":99.92275560021898,
> ① . "failRate":0.0,
> ① . "threads":4,
> ① . "startTime":"2021-01-27 15:37:43",
> ① . "endTime":"2021-01-27 15:39:23",
> ① . "errorRate":0.0,
> ① . "executeTotal":9993,
> ① . "mark":"FunTester测试20210127153743",
> ① . "table":"\r\n\t\"
> }
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
INFO->
FunTester测试4

>>响应时间分布图,横轴排序分成桶的序号,纵轴每个桶的中位数<<
--<中位数数据最小值为:25 ms,最大值:124 ms>--
██
██
██
▅▅ ██
██ ██
██ ██
██ ██
██ ██
██ ██
██ ██
██ ██
██ ██ ██
██ ██ ██
██ ██ ██
██ ██ ██
▃▃ ██ ██ ██
▂▂ ▂▂ ▃▃ ▅▅ ██ ██ ██ ██
▁▁ ▁▁ ▃▃ ▄▄ ▄▄ ▄▄ ▅▅ ▅▅ ▇▇ ▇▇ ██ ██ ██ ██ ██ ██ ██ ██ ██
▅▅ ▅▅ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██

INFO-> gc回收线程结束了!

Process finished with exit code 0

最后的响应结果需要使用等宽字体查看才行,如果系统默认的字是非等宽的,请参照下图:

重放浏览器多个请求性能测试实践_数据_02

关于如何使用性能测试框架和生成性能测试结果,有兴趣的可以翻一翻以前的文章。


FunTester,非著名测试开发,文章记录学习和感悟,欢迎关注,交流成长。