写点什么

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

用户头像
FunTester
关注
发布于: 6 小时前

在最近的工作中,挫败感极大,我做了深刻反思,得出来一个道理:如是观照,实事求是


原因比较复杂,其中一项是因为某一批接口测试需求比较紧,我之前一直的思路就是尽可能模拟真实数据,使用多用户进行性能测试,一般测试前都需要尽量大量的数据准备工作。但是这次不灵了,接口之间的参数依赖过于复杂,如果真写起来,可真就是把端上的工作重新做一遍,不值当的。


所以我取了个巧,在模拟用户造数据的时候,我直接复制了浏览器里面的接口请求,然后通过不断的刷这个接口去造数据,就不用去一个参数一个参数的写请求了。顺便还能给端上同学写一个简单的性能测试工具 Demo,方便他们做一些简单的性能测试。


首先我去解析GETPOST请求,然后通过工具类FunRequest生成一个HttpRequestBase,然后验证一下请求,就可以正常进行性能测试阶段了。

复制请求

这里我采用了复制curl的格式的方式,因为其他的方式数据量太大了,比较复杂,解析起来困难,容易出BUG


GET 请求

分享一下复制的结果,删除了域名。


curl 'https://j****.cn/home/course_list?_=1611648498164&custom_directory_id=4630377&origin=0&page=1&page_size=10' \  -H 'Connection: keep-alive' \  -H 'sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"' \  -H 'DNT: 1' \  -H 'sec-ch-ua-mobile: ?0' \  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' \  -H 'requestid: 010427916771' \  -H 'Accept: application/json, text/javascript, */*; q=0.01' \  -H 'X-Requested-With: XMLHttpRequest' \  -H 'is_new_okay: 1' \  -H 'Sec-Fetch-Site: same-origin' \  -H 'Sec-Fetch-Mode: cors' \  -H 'Sec-Fetch-Dest: empty' \  -H 'Referer: https://jiaoshi-dev.xk12.cn/' \  -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' \  -H 'Cookie: db_log=1; org_id=640; user_action_cookie=user_action_87cf9c4d-1e22-4c8c-982e-a4419fa6dc1b_62951571858; teacher_id=9fec845f498a47abb68426c14f90693e' \  --compressed
复制代码

POST 请求

分享一下复制的结果,删除了域名,too!


curl 'https://j****.cn/myResourcePool/deleteResource' \  -H 'Connection: keep-alive' \  -H 'sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"' \  -H 'DNT: 1' \  -H 'sec-ch-ua-mobile: ?0' \  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' \  -H 'requestid: 011342477158' \  -H 'Accept: application/json, text/javascript, */*; q=0.01' \  -H 'X-Requested-With: XMLHttpRequest' \  -H 'is_new_okay: 1' \  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \  -H 'Origin: https://jiaoshi-dev.xk12.cn' \  -H 'Sec-Fetch-Site: same-origin' \  -H 'Sec-Fetch-Mode: cors' \  -H 'Sec-Fetch-Dest: empty' \  -H 'Referer: https://jiaoshi-dev.xk12.cn/myResourcePool_vm/my_resources' \  -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' \  -H 'Cookie: db_log=1; org_id=640; user_action_cookie=user_action_87cf9c4d-1e22-4c8c-982e-a4419fa6dc1b_62951571858; teacher_id=9fec845f498a47abb68426c14f90693e' \  --data-raw 'res_id=2317045&res_type=3' \  --compressed
复制代码

生成 HttpRequestBase 对象

这里我是把复制的请求写到本地的一个文本文件中,首先读取,然后遍历处理。


    public static HttpRequestBase getRequest(String path) {        def fileinfo = WriteRead.readTxtFileByLine(LONG_Path + path).stream().map {it.trim()}        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 << 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            }        }        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内部静态类。


static class CurlRequestBase {
String url
RequestType type =RequestType.GET
List<Header> headers = new ArrayList<>()
JSONObject params = new JSONObject()

}
复制代码

性能测试

这个比较容易,接入之前的性能测试框架即可。


public static void main(String[] args) {        def request = getRequest("get")        output FanLibrary.getHttpResponse(request)
def thread = new RequestThreadTimes<HttpRequestBase>(request, 100) new Concurrent(thread,30,"FunTester get请求测试").start()
testOver() }
复制代码

控制台输出

响应的数据量有点大,这里就不放响应结果了,直接放性能测试结果。


INFO-> gc回收线程开始了!INFO-> 线程:FunTester get请求测试16,执行次数:100,错误次数: 0,总耗时:12.92 s······省略········INFO-> 线程:FunTester get请求测试19,执行次数:100,错误次数: 0,总耗时:14.017 sINFO-> 总计30个线程,共用时:14.033 s,执行总数:3000,错误数:0,失败数:0INFO-> 数据保存成功!文件名:/Users/fv/Documents/workspace/fun/long/data/FunTester get请求测试2021012617384730INFO-> ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~>  {>  ① . "rt":132,>  ① . "total":3000,>  ① . "qps":225.86109542631283,>  ① . "failRate":0.0,>  ① . "threads":30,>  ① . "startTime":"2021-01-26 17:38:47",>  ① . "endTime":"2021-01-26 17:39:01",>  ① . "errorRate":0.0,>  ① . "executeTotal":3000,>  ① . "mark":"FunTester get请求测试20210126173847",>  ① . "table":"\r\n\t\t\t\tFunTester get请求测试30·····省略,见下图····\r\n">  }~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~INFO->         FunTester get请求测试30
>>响应时间分布图,横轴排序分成桶的序号,纵轴每个桶的中位数<< --<中位数数据最小值为:93 ms,最大值:204 ms>-- ██ ██ ██ ▅▅ ██ ▃▃ ██ ██ ▃▃ ██ ██ ██ ▂▂ ▇▇ ██ ██ ██ ██ ▁▁ ▄▄ ▇▇ ██ ██ ██ ██ ██ ██ ▂▂ ▅▅ ▇▇ ██ ██ ██ ██ ██ ██ ██ ██ ██ ▁▁ ▄▄ ▅▅ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ▃▃ ▅▅ ▇▇ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ▂▂ ▅▅ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ▃▃ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
INFO-> gc回收线程结束了!
Process finished with exit code 0
复制代码


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



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



FunTester,非著名测试开发,文章记录学习和感悟,欢迎关注,交流成长。
  • Gitee地址 https://gitee.com/fanapi/tester

  • GitHub地址 https://github.com/JunManYuanLong/FunTester




发布于: 6 小时前阅读数: 7
用户头像

FunTester

关注

公众号:FunTester,650+原创,欢迎关注 2020.10.20 加入

Have Fun,Tester! 公众号FunTester,坚持原创文章的测试人。 FunTester测试框架作者,DCS_FunTester分布式性能测试框架作者。

评论

发布
暂无评论
重放浏览器单个请求性能测试实践