參考文獻:
https://blog.csdn.net/neven7/article/details/50669459
1.背景
之前在這篇文章中性能測試初探—接口性能測試介紹過nGrinder,本文將介紹在nGrinder腳本中使用資源文件中數據作爲接口參數和解析生成的CSV結果,生成TPS標準差,TPS波動率,最小/大RT,RT 25/50/75/80/85/90/95/99百分位數(原生結果中無這些結果,這些結果更有利於性能分析)。
2.實現
2-1.創建腳本
如果腳本中需獲取參數,可以使用Performance Test菜單下的Test Configuration->Show Advanced Configuration->Parameter輸入框中參數值(http://www.cubrid.org/wiki_ngrinder/entry/how-to-pass-a-parameter-to-the-script),但是隻支持1-50字符長度;如果參數值較長,可以使用resources(http://www.cubrid.org/wiki_ngrinder/entry/how-to-use-resources), 支持json, csv, txt, properties格式。
腳本示例如下:
定義String[] basic用於存放文件./resources/basicauth.txt中的值(數組元素爲文件中的每一行)
HTTP GET:
package org.ngrinder;
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 HTTPClient.HTTPResponse
import HTTPClient.NVPair
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 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 hugang
*/
@RunWith(GrinderRunner)
class TestRunner {
public static GTest test
public static HTTPRequest request
public static File file
public static String[] basic
@BeforeProcess
public static void beforeProcess() {
HTTPPluginControl.getConnectionDefaults().timeout = 6000
test = new GTest(1, "10.75.0.55")
request = new HTTPRequest()
test.record(request);
// 將文件內容轉成參數數組
basic = new File("./resources/basicauth.txt") as String[];
// grinder.logger.info(basic[0] + " " + basic[1])
grinder.logger.info("before process.");
}
@BeforeThread
public void beforeThread() {
grinder.statistics.delayReports=true;
grinder.logger.info("before thread.");
}
@Test
public void test(){
// 隨機獲取auth
int index = (int) (Math.random() * basic.length);
String basicAuth = basic[index];
println(basicAuth);
// GET請求,wiki http://grinder.sourceforge.net/g3/script-javadoc/net/grinder/plugin/http/HTTPRequest.html
// param1: uri, param2: queryData, param3: headers
HTTPResponse result = request.GET("http://10.75.0.55:8080/2/likes/by_me.json",[new NVPair("object_type", "pic")] as NVPair[], [new NVPair("Authorization", basicAuth)] as NVPair[])
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));
// 請求返回的數據
// println(result.text);
// 定義一個事務,接口返回數據校驗,是否包含
assertThat(result.text, containsString("\"object_type\":\"pic\""));
}
}
}
HTTP post:
package org.ngrinder;
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 HTTPClient.HTTPResponse
import HTTPClient.NVPair
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 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 hugang
*/
@RunWith(GrinderRunner)
class TestRunner {
public static GTest test
public static HTTPRequest request
public static File file
public static String[] basic
@BeforeProcess
public static void beforeProcess() {
HTTPPluginControl.getConnectionDefaults().timeout = 6000
test = new GTest(1, "10.210.230.28")
request = new HTTPRequest()
test.record(request);
// 將文件內容轉成參數數組
basic = new File("./resources/basicauth.txt") as String[];
// grinder.logger.info(basic[0] + " " + basic[1])
grinder.logger.info("before process.");
}
@BeforeThread
public void beforeThread() {
grinder.statistics.delayReports=true;
grinder.logger.info("before thread.");
}
@Test
public void test(){
// 隨機獲取auth
int index = (int) (Math.random() * basic.length);
String basicAuth = basic[index];
println(basicAuth);
// POST請求,wiki http://grinder.sourceforge.net/g3/script-javadoc/net/grinder/plugin/http/HTTPRequest.html
// param1: uri, param2: queryData, param3: headers
HTTPResponse result = request.POST("http://10.210.230.28/2/statuses/update.json",[new NVPair("status", "text " + Math.random())] as NVPair[], [new NVPair("Authorization", basicAuth)] as NVPair[])
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));
// 請求返回的數據
// println(result.text);
// 定義一個事務,接口返回數據校驗,是否包含
assertThat(result.text, containsString("\"created_at\":"));
}
}
}
2-2. 驗證腳本
點擊Validate Script, 會出現如下信息:
...
2016-02-15 16:56:32,140 INFO Start time is 1455526592140 ms since Epoch
2016-02-15 16:56:32,318 INFO http://10.75.0.55:8080/2/likes/by_me.json?object_type=pic -> 200 OK, 3414 bytes
2016-02-15 16:56:32,342 INFO finished 1 run
2016-02-15 16:56:32,345 INFO elapsed time is 204 ms
2016-02-15 16:56:32,345 INFO Final statistics for this process:
2016-02-15 16:56:32,355 INFO
Tests Errors Mean Test Test Time TPS Mean Response Response Mean time to Mean time to Mean time to
Time (ms) Standard response bytes per errors resolve host establish first byte
Deviation length second connection
(ms)
Test 1 1 0 32.00 0.00 4.90 3414.00 16735.29 0 1.00 5.00 24.00 "10.75.0.55"
Totals 1 0 32.00 0.00 4.90 3414.00 16735.29 0 1.00 5.00 24.00
...
Tests 爲1, Errors 爲0 表示腳本驗證通過。
2-3.設計場景
3.結果
3.1.彙總信息
如果還需獲取詳細信息,需下載csv文件:
彙總數據項目地址:https://github.com/neven7/ngrinder-csv-analysis
解析ngrinder csv結果,統計TPS標準差,TPS波動率,最小/大RT,RT 25/50/75/80/85/90/95/99百分位數
步驟:
將ngrinder 生成的csv文件:output.csv,放到工程src/main/resources下
執行src/main/java下ParseCsv.java文件
Console輸出結果示例:
TPS平均值:257.88
TPS標準差:33.10
TPS波動率:12.84%
RT平均響應時間:19.43 ms
Min RT:14.90 ms
RT 25百分位數:18.07 ms
RT 50百分位數:19.14 ms
RT 75百分位數:20.33 ms
RT 80百分位數:20.78 ms
RT 85百分位數:21.29 ms
RT 90百分位數:21.86 ms
RT 95百分位數:23.52 ms
RT 99百分位數:25.91 ms
Max RT:46.93 ms