天天看點

nGrinder 的 Groovy 腳本使用指南(Groovy 腳本結構)

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 測試體

通過下圖來說明執行流程:

nGrinder 的 Groovy 腳本使用指南(Groovy 腳本結構)

在測試用例示例中,請仔細檢視以下部分。

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