专栏文章 性能测试中标记请求参数实践

FunTester · 2021年01月15日 · 1216 次阅读

在之前的文章性能测试中标记每个请求链路压测中如何记录每一个耗时的请求中,我详细说明了如何标记HTTPrequestbase对象和记录HTTPrequestbase请求的响应时间,都是通过header中的某一个字段值进行标记的。

但是在实际工作中,很多时候无法进行header标记每一个请求对象,因为服务很可能不会通过header里面的某个字段来区分每一个请求,而且在链路压测中根本不会是一个HTTP请求,而是好几个HTTP请求,无法使用同一MarkRequest进行标记,所以在通用功能无法满足需求的时候就需要我们自己进行脚本的编写,下面分享一下我在一次性能测试中,对请求参数进行标记的实践。

接口

这是一个搜索接口,通过输入keyword来获取相关资源,具体业务和搜索能力细节这里就不讲了。下面看一下接口文档:

/**
 * 首页智课搜索
 *
 * @param keyword
 * @return
 */
public JSONObject ailearnSearch(String keyword) {
    String url = LaunchApi.AILEARN_SEARCH;
    JSONObject params = getParams();
    params.put("keyword", keyword);
    params.put("orgIdArray", Arrays.asList(80, 54, 640, 3018, 3346, 3308, 3305));
    params.put("page", 1);
    params.put("pageSize", 10);
    params.put("stageId", 2);//1:小学,2:初中,3:高中
    JSONObject response = getPostResponse(url, params);
    output(response);
    return response;
}

这个既是接口文档也是接口用例的基本方法,基本上是可以理解该接口的请求所需的必要因素的,相比各种各样平台或者形式提供的接口文档,我更愿意提供一个可直接请求的Demo,当然除了业务细节内容以外。

方法改造

首先这个功能测试方法是不适应性能测试的,首先我们看getParams()代码:

public JSONObject getParams() {
    return getJson("mark=" + Common.getRequestIdHeader().getValue());
}

这里很简单的,我向参数中添加一个keymark(公参)的字段,且赋上一个唯一的值,然后添加到参数里面。

但是在性能测试中,再从每一个请求里面解析这个参数比较麻烦,所以我进行了方法的改造,如何:

/**
 * 首页智课搜索(用于压测)
 *
 * @param rid
 * @return
 */
public JSONObject ailearnSearchP(String mark) {
    String url = LaunchApi.AILEARN_SEARCH;
    JSONObject params = new JSONObject();
    params.put("mark", mark);
    params.put("keyword", rstring.get(t.getAndIncrement() % rstring.size()));
    params.put("orgIdArray", Arrays.asList(80, 54, 640, 3018, 3346, 3308, 3305));
    params.put("page", 1);
    params.put("pageSize", 10);
    params.put("stageId", 2);//1:小学,2:初中,3:高中
    JSONObject response = getPostResponse(url, params);
    output(response);
    return response;
}

我用一个参数来给公参mark赋值,方便性能测试中调用这个方法。

性能脚本实现

这里我依然采用了内部静态类的方式完成自定义的性能多线程对象的实现,重写doing()方法。代码如下:

package com.okayqa.elasticsearch.performance

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.fun.utils.RString
import com.okayqa.elasticsearch.base.OkayBase
import com.okayqa.elasticsearch.function.Launch

import java.util.concurrent.atomic.AtomicInteger

public class LaunchSearch extends OkayBase {

    static AtomicInteger count = new AtomicInteger(getRandomIntRange(100, 999) * 1000000)

    public static void main(String[] args) {
        ClientManage.init(5, 3, -1, EMPTY, 0)
        def util = new ArgsUtil(args)
        def thread = util.getIntOrdefault(0, 20)
        int times = util.getIntOrdefault(1, 30)
        def launch = new Launch()
        def threads = []
        thread.times {
            threads << new FUN(times)
        }


        new Concurrent(threads, "首页智课搜索").start()


        allOver()
    }

    static class FUN extends ThreadLimitTimesCount {

        Launch drive = new Launch()

        FUN(int times) {
            super(null, times, null)
        }

        @Override
        protected void doing() throws Exception {
            this.threadmark = count.getAndIncrement() + RString.getString(4)
            drive.ailearnSearchP(threadmark)

        }
    }

}

我依然使用了AtomicInteger这个线程安全类,随机一个较大的int数值,然后随机mark的值的时候再添加length为 4 的字符串,主要是为了防止多次请求重复的问题。


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

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册