ngrinder(二) 压力测试脚本groovy 实战

前言

groovy脚本

ngrinder 的 groovy 脚本是顺序结构的,用户可通过编写脚本执行过程中被预置的函数进行用户操作,完成各种复杂的测试工作。

ngrinder 的进程与线程

ngrinder 使用进程和线程来模拟多个用户。例如,如果您设置了如下的测试。只有一个代理将被激活,1个进程将被调用,然后这个进程将包括2个运行线程。每个线程的行为就像1个用户。因此,2个虚拟用户正在运行。如果将代理计数增加到2,则总共有4个虚拟用户(Vusers)。

并发量=代理数x进程数x线程数
如果在Vuser per agent 中输入总的虚拟用户数时,nGrinder根据内部算法,会进行适当的计算,如输入100,当agent数为1时, 会变成99,该算法可以通过 process_and_thread_policy.js 这个文件来修改。
若果agent 的内存4G以下的话,建议进程不要超过10个,线程数不要超过200.

  • 官方最新测试:4G内存的agent 最多可以模拟4000 虚拟用户。

?

预置函数

依据上面对agent、进程与线程的解释,就比较好理解ngrinder groovy 脚本的
结构了。
控制器将脚本分发给agent,每个agent按照算法启动对应数量的进程,每个进程里在启动对应数量的线程,执行测试任务。

注解 描述 执行次数 用例
@BeforeProcess 在进程被调用之前执行的函数 每进程一次 加载被线程共享的资源文件,定义 公共变量等
@AfterProcess 在进程被终止之前执行该函数 每进程一次 关闭资源文件
@BeforeThread 在每个线程被调用之前执行的函数 每线程一次 登录目标系统,建立线程内的一些值,例如,Cookie 处理
@AfterThread 在每个线程被终止之前执行的函数 每线程一次 退出系统
@Before 每个被 @Test 注解的方法被执行前应执行的函数 同虚拟用户数 每个被 @Test 注解的方法的共享逻辑、变量设置
@After 每个被 @Test 注解的方法被执行后应执行的函数 同虚拟用户数 很少使用
@Test 主测试行为,将被被执行多次 同虚拟用户数 测试体

?

groovy 脚本实例

?

压测实例

/*
这个脚本是对需要验签接口的压测
*/
import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import net.grinder.plugin.http.HTTPRequest
import net.grinder.plugin.http.HTTPPluginControl
import net.grinder.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
// import static net.grinder.util.GrinderUtils.* // You can use this if you‘re using nGrinder after 3.2.3
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith

import java.util.Date
import java.util.List
import java.util.ArrayList

import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;

import HTTPClient.Cookie
import HTTPClient.CookieModule
import HTTPClient.HTTPResponse
import HTTPClient.NVPair

import java.text.SimpleDateFormat;

import org.apache.commons.codec.binary.Base64;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Arrays;
import org.apache.commons.lang.StringUtils;
import java.lang.StringBuilder

import java.io.UnsupportedEncodingException;

/**
 * A simple example using the HTTP plugin that shows the retrieval of a
 * single page via HTTP.
 *
 * This script is automatically generated by ngrinder.
 *
 * @author admin
 */
@RunWith(GrinderRunner)
class TestRunner {

    public static GTest test
    public static HTTPRequest request
    // 定义全局变量
    public static NVPair[] params = []
    public static Cookie[] cookies = []
    public static String private_key
    public static String[] contents = []

    @BeforeProcess
    public static void beforeProcess() {
        HTTPPluginControl.getConnectionDefaults().timeout = 6000
        test = new GTest(1, "Test1")
        request = new HTTPRequest()
        // 获取加密私钥内容
        contents = new File("./resources/rsa_private_key_pkcs8.pem") as String[]
        StringBuilder private_str = new StringBuilder();
        for(int i=0;i<contents.length;i++){
            if (contents[i].charAt(0) != ‘-‘ && contents[i] != null) {
                private_str.append(contents[i]).append("\n");
            }
        }
        private_key = private_str.toString()
        //调试输出
        grinder.logger.info("before process.");
    }

    @BeforeThread
    public void beforeThread() {
        test.record(this, "test")
        grinder.statistics.delayReports=true;
        grinder.logger.info("before thread.");
    }
    //自定义函数,修改http头数据
    private NVPair[] headers(post) {
        if( post != null ){
            post="&"+post
        }else{
            post=""
        }
        def appid = "1111111111111111111111"
        def appcode = "11111"
        long currentTime = System.currentTimeMillis()
        def json = "appId="+appid+"&appCode="+appcode+"&"+""+"timestamp="+currentTime+post
        def sign = getsign(json)
        //grinder.logger.info(currentTime.toString())
        return [
                new NVPair("Content-type", "application/json;charset=UTF-8"),
                new NVPair("appId", "1013f9d4e97026cb07e3fdea1b560f2f"),
                new NVPair("sign", sign),
                new NVPair("timestamp", currentTime.toString()),
                new NVPair("appCode", "11111")
        ];
    }
    //自定义函数,生成YYYY-MM-dd HH:mm:ss 格式的当天日期串
    def today()
    {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        Calendar lastDate = Calendar.getInstance();
        str = sdf.format(lastDate.getTime());
        return str;
    }

    // 自定义函数加签
    private getsign(post){
        //加签算法 略
        return sign
    }

    @Before
    public void before() {
        request.setHeaders(headers())
        cookies.each { CookieModule.addCookie(it, HTTPPluginControl.getThreadHTTPClientContext()) }
        grinder.logger.info("before thread. init headers and cookies");
    }

    @Test
    public void test(){
        // 参数初始化
        def domain = "api.xxxx.com"
        def timestr=today()
        def json=‘{"eventCode":"1111111", "eventTime":"‘+timestr+‘", "channelCode":"1111111" , eventTime":"‘+timestr+‘"}}‘;
        //获取签名后的头信息
        def head = headers("bizContent="+json)
        //grinder.logger.info(head.toString())
        HTTPResponse result = request.POST(‘http://‘+domain+‘/channel/v1/mot/receive‘,json.getBytes(), head)

        //HTTPResponse result = request.GET("http://106.14.8.248/phpapi.php", params)
        if(result.text.equals(new String(result.text.getBytes("iso8859-1"), "iso8859-1")))
        {
            result.text=new String(result.text.getBytes("iso8859-1"),"utf-8");
        }
        //调试输出头信息
        grinder.logger.info("result="+request.getHeaders())
        //调试输出结果数据
        grinder.logger.info("result="+result.text)
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
        }
    }
}

原文地址:http://blog.51cto.com/13673090/2306627

时间: 2024-10-10 10:10:10

ngrinder(二) 压力测试脚本groovy 实战的相关文章

loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写

先说明一下,本人是开发,对测试不是特别熟悉,但因工作的需要,也做过一些性能测试方面的东西.比较久之前很简单的用过,最近又用到了,熟悉一下.现做一个总结. 使用loadrunner进行压力测试主要分两步,第一步是编写脚本(比较重点),第二步执行测试(配置都是在界面上点点就行了,当然我只的是比较简单的,能满足日常需要的),第三步分析结果(这一步比较高深,但是对于我来说能看懂简单的性能指标就OK了).所以这里就说一下脚本的编写,给未来再用到做参考. 1.HTTP的GET请求 这里以访问百度为例,地址h

loadrunner简单使用&mdash;&mdash;HTTP,WebService,Socket压力测试脚本编写

先说明一下,本人是开发,对测试不是特别熟悉,但因工作的需要,也做过一些性能测试方面的东西.比较久之前很简单的用过,最近又用到了,熟悉一下.现做一个总结. 使用loadrunner进行压力测试主要分两步:第一步是编写脚本(比较重点),第二步执行测试(配置都是在界面上点点就行,当然我只是比较简单的,能满足日常需要的),第三步分析结果(这一步比较高深,但是对于我来说能看懂简单的性能指标就OK)所以这里就说一下脚本的编写,给未来再用到做参考. 1,HTTP的GET请求 这里以访问百度为例,地址http:

(转载)loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写

原文出处:http://ajita.iteye.com/blog/1728243/ 先说明一下,本人是开发,对测试不是特别熟悉,但因工作的需要,也做过一些性能测试方面的东西.比较久之前很简单的用过,最近又用到了,熟悉一下.现做一个总结. 使用loadrunner进行压力测试主要分两步,第一步是编写脚本(比较重点),第二步执行测试(配置都是在界面上点点就行了,当然我只的是比较简单的,能满足日常需要的),第三步分析结果(这一步比较高深,但是对于我来说能看懂简单的性能指标就OK了).所以这里就说一下脚

如果使用socket发送http请求(并且编译成可以被lr调用的压力测试脚本)

#include  <unistd.h> #include  <sys/types.h>       /* basic system data types */ #include  <sys/socket.h>      /* basic socket definitions */ #include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */ #include  <

jmeter 压力测试

一.什么是压力测试 压力测试:测试系统在不同压力情况下的效率状况以及系统可以承受的压力状况. 举例说明:5000人同时到窗帘系统下单购买窗帘时,系统运行速度或者处理效率是否变慢或者系统是否会崩溃. 二.压力测试工具 1. LoadRunner LoadRunner,是一种预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试.通过使用 LoadRunner,企业能最大限度地缩短测试时间,优化性能和加速

postgresql压力测试工具用法以及参数解读

pgbench是PostgreSQL自带的一个数据库压力测试工具, 支持TPC-B测试模型, 或自定义测试模型. 自定义测试模型支持元命令, 调用shell脚本, 设置随机数, 变量等等. 支持3种异步接口[simple|extended|prepared] 参数详解列表 // TPC-B测试模型的初始化数据参数. Initialization options: -i invokes initialization mode //初始化参数 -F NUM fill factor -n do not

【技测】游戏上线前服务器压力测试应该怎么做

伴随手游上线推广,玩家爆发式增长,不少开发者都遇到过玩家冲爆服务器的情况,因此降低服务器崩溃的风险就显得非常重要.游戏上线前如果做了服务器压力测试帮助会很大.今天就来说说压力测试. 编写脚本机器人 为了在游戏上线前实际掌握服务器的承载能力,在游戏的开发流程末端都会引入压力测试.最普遍的一种测试方式是机器人模拟测试.通过脚本机器人在游戏中模拟一个玩家可能进行的操作,几千个机器人在服务器里面连续执行各种操作,测试各处功能的完整度. 脚本机器人是大部分CP在上线前的一个重要压测手段,因为这是低成本下最

如何使用 JMeter 调用你的 Restful Web Service?进行简单的压力测试和自动化测试

表述性状态传输(REST)作为对基于 SOAP 和 Web 服务描述语言(WSDL)的 Web 服务的简单替代,在 Web 开发上得到了广泛的接受.能够充分证明这点的是主流 Web 2.0 服务提供商在接口设计中对 REST 的普遍采用 - 包括雅虎.谷歌以及脸谱 - 出于简单易用.以面向资源的模型发布自己的服务的偏好他们都已经抛弃了 SOAP 和基于 WSDL 的接口.在你必须要对你的 RESTFul web service 进行测试的时候,你可能会有这两个选择: 使用 URL 对你的 Web

山东BOSS性能压力测试

1. 概述 在山东BOSS性能压力测试过程中,发现脚本对于整个压力测试过程的重要性,一个压力测试脚本录制和编辑修改得怎么样直接影响后面压力测试的执行.通常情况下,脚本应尽可能的精简,就像写代码一样.针对BOSS系统的特点, 个人 认为把单一业务录制成一个Action,并在脚本中添加Transaction,Find检查(可以采用URL-based scrīpt 方式录制并事先设定),Rendezvous,参数化等基本元素,然而有时我们会发现光有这些基本元素还不能满足我们的要求.比如在Control