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(1, "${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 == 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));
        }
    }
}

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(1, "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 == 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));
    }
}

@Test
public void testYahoo(){
    HTTPResponse result = request.GET("http://www.yahoo.com");
    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));
    }
}

然而,你应该知道 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 == 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));
    }
    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 == 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://www.cubrid.org/wiki_ngrinder/entry/groovy-script-structure

阅读更多
想对作者说点什么?
相关热词

博主推荐

换一批

没有更多推荐了,返回首页