nGrinder 架構簡介
nGrinder 的 Groovy 腳本使用指南(Groovy 腳本結構)
nGrinder 的 Groovy 腳本使用指南(Groovy maven 結構)
nGrinder 的 Groovy 腳本使用指南(導入 Groovy Maven 工程到 IntelliJ)
與Jython腳本不同,Groovy 腳本結構是基于JUnit的。原因是我們想盡可能的重用現有的 JUnit 經驗。幾個 IDE 已經內建了 JUnit 而且可以讓使用者直接運作測試用例。
先來看一個基礎的 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.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import HTTPClient.HTTPResponse
/**
* 這是一個使用 HTTP 插件的簡單例子,顯示一個通過 HTTP 協定的單頁檢索請求
*
* 這個是 nGrinder 自動生成的腳本
*
* @author ${userName}
*/
@RunWith(GrinderRunner)
class TestRunner {
public static GTest test;
public static HTTPRequest request;
// 這個方法每個程序隻執行一次
@BeforeProcess
public static void beforeClass() {
test = new GTest(, "${name}");
request = new HTTPRequest();
test.record(request);
grinder.logger.info("before process.");
}
// 這個方法每個線程執行一次
@BeforeThread
public void beforeThread() {
grinder.statistics.delayReports=true;
grinder.logger.info("before thread.");
}
// 在測試停止之前,這個方法将持續執行下去
@Test
public void test(){
HTTPResponse result = request.GET("${url}");
if (result.statusCode == || result.statusCode == ) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
} else {
assertThat(result.statusCode, is());
}
}
}
nGrinder 的 Groovy 測試用例需要使用 @RunWith(GroovyRunner) 注解進行注釋。當你在 IDE 的 JUnit 運作器中運作這個腳本時,這個注解将使用 GroovyRunner 來控制 JUnit 的行為,同時将 grinder 的上下文綁定到 JUnit 上。被 @Test 注釋的方法會被反複執行,正如你在上面所看到的,你可以使用 JUnit 的斷言機制去對測試結果進行斷言處理。如果斷言失敗,那麼目前線程内的最後一個次測試将被認定為失敗。
替代 JUnit 中的通用注解:“@BeforeClass @Before @AfterClass @After ”,nGrinder 中的 Groovy 測試用例使用它自己的注解來控制腳本行為。
注解 | 描述 | 應用範圍 | 用例 |
---|---|---|---|
@BeforeProcess | 定義在程序被調用之前應執行的行為 | static method | 加載被線程共享的資源檔案,定義 GTest 等 |
@AfterProcess | 定義在程序被終止之前應執行的行為 | static method | 關閉資源檔案 |
@BeforeThread | 定義在每個線程被調用之前應執行的行為 | member method | 登入目标系統,建立線程内的一些值,例如,Cookie 處理 |
@AfterThread | 定義在每個線程被終止之前應執行的行為 | member method | 退出系統 |
@Before | 定義每個被 @Test 注解的方法被執行前應執行的行為 | member method | 對個被 @Test 注解的方法的共享邏輯、變量設定 |
@After | 定義每個被 @Test 注解的方法被執行後應執行的行為 | member method | 很少使用 |
@Test | 定義測試行為,被執行多次 | member method | 測試體 |
通過下圖來說明執行流程:
在測試用例示例中,請仔細檢視以下部分。
public static GTest test;
public static HTTPRequest request;
// 這個方法每個程序隻執行一次
@BeforeProcess
public static void beforeProcess() {
test = new GTest(, "test name");
request = new HTTPRequest();
test.record(request);
grinder.logger.info("before process.");
}
在被 @BeforeProcess 注釋的方法中,它定義了 GTest 執行個體而且記錄 HttpRequest 執行個體上的任何調用并儲存在靜态成員變量(request)中。
可以使用不同的名字定義多組 Gtest\HTTPRequest ,我還沒有驗證有什麼好處,也許寫插件時可以使用(以後再驗證,有知道的朋友也請告知)
在一個測試用例類中,可以定義多個測試方法,隻要在這些測試方法上使用 @Test 注解即可
@Test
public void testGoogle(){
HTTPResponse result = request.GET("http://www.google.com");
if (result.statusCode == || result.statusCode == ) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
} else {
assertThat(result.statusCode, is());
}
}
@Test
public void testYahoo(){
HTTPResponse result = request.GET("http://www.yahoo.com");
if (result.statusCode == || result.statusCode == ) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
} else {
assertThat(result.statusCode, is());
}
}
然而,你應該知道 ngrinder 的 GroovyRunner 對每一個線程隻建立一個測試用例對象,而不像 JUnit 那樣為每個被 @Test 注釋的方法建立單獨的測試用例對象。是以,每個被 @Test 注釋的方法可以共享成員變量,他們可以互相影響。在 nGrinder 測試用例中,被 @Test 注釋的方法很可能依賴前一個被 @Test 注釋的方法的執行結果。是以,如果你在成員變量中儲存前一個測試方法的結果,那麼下一個測試方法中就可以使用此變量,你可以輕松的實作測試依賴性。
private boolean googleResult;
@Test
public void testGoogle(){
googleResult = false;
HTTPResponse result = request.GET("http://www.google.com");
if (result.statusCode == || result.statusCode == ) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
} else {
assertThat(result.statusCode, is());
}
googleResult = true;
}
@Test
public void testYahoo(){
if (!googleResult) {
grinder.logger.warn("Just return. Because prev google test is failed.");
return;
}
HTTPResponse result = request.GET("http://www.yahoo.com");
if (result.statusCode == || result.statusCode == ) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
} else {
assertThat(result.statusCode, is());
}
}
初略翻譯,不準确的地方請多多指正
原文位址:http://www.cubrid.org/wiki_ngrinder/entry/groovy-script-structure