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

FunTester · 2021年01月29日 · 2051 次阅读

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

复制请求

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

复制浏览器所有请求

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

获取 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属性进行过滤,主要是过滤掉jscss、图片、网页和媒体文件包括无用的请求。一次是通过请求头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

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

FunTester性能测试结果

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


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

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 0 条回复 时间 点赞
1楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册