Link
Today
Total
05-04 10:56
Archives
관리 메뉴

초보개발자 긍.응.성

nGrinder Groovy Script 작성방법 본문

nGrinder

nGrinder Groovy Script 작성방법

긍.응.성 2020. 12. 2. 01:48
반응형

Groovy Script Structure

nGrinder 3.2부터 스크립트 언어로써 Groovy를 지원하기 시작했습니다. Groovy 스크립트는 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

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

    public static GTest test;
    public static HTTPRequest request;

    // This method is executed once per a process.
    @BeforeProcess
    public static void beforeClass() {
        test = new GTest(1, "${name}");
        request = new HTTPRequest();
        test.record(request);
        grinder.logger.info("before process.");
    }

    // This method is executed once per a thread.
    @BeforeThread
    public void beforeThread() {
        grinder.statistics.delayReports=true;
        grinder.logger.info("before thread.");
    }

    // This method is continuously executed until you stop the test
    @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(GrinderRunner) 애너테이션을 꼭 붙여주어야 합니다. 이 부분은 GroovyRunner가 JUnit의 행동을 제어하며 JUnit에 grinder context를 마운트 합니다.

@Test 애너테이션이 붙은 메서드에는 각자 수행되어할 행동을 정의합니다. 이 메서드에선 JUnit assertion을 이용하여 결과를 단언(assert)할 수 있습니다. 만약 assertion이 실패한다면 해당 쓰레드는 failure로 처리됩니다.

JUnit이 제공하는 @BeforeClass, @Before, @AfterClass, @After 애너테이션 대신, nGrinder Groovy 테스트는 아래와 같은 애너테이션을 지원합니다.

애너테이션 설명 적용 메서드 형태 사용 예
@BeforeProcess 프로세스가 호출되기 전 처리할 동작 정의 static method 쓰레드가 공유할 자원을 로드한다.

GTest 와 타겟에 대하여 테스트할 레코드를 설정한다.
@AfterProcess 프로세스가 종료되기 전 처리할 동작 정의 static method 리소스를 반납한다.
@BeforeThread 각 쓰레드가 실행되기 전 처리할 동작 정의 member method 타겟 시스템에 로그인한다.
쿠키 핸들러와 같은 쓰레드 단위로 가질 데이터를 정의한다.
@AfterThread 각 쓰레드가 실행된 후 처리할 동작 정의 member method 타겟 시스템에서 로그아웃한다
@Before 각각의 @Test 메서드가 수행되기 전 처리할 동작 정의 member method 테스트에 사용할 변수 세팅
@After 각각의 @Test 메서드가 수행된 후 처리할 동작 정의 member method 잘 사용되지 않는다...
@Test 테스트할 동작 정의. 다중호출 됨 member method 테스트

 

  • 실행 플로우

 

이제 위의 소스를 정의된 애너테이션을 따라 살펴보겠습니다

@BeforeProcess

public static GTest test;
public static HTTPRequest request;

// This method is executed once per a process.
@BeforeProcess
public static void beforeProcess() {
    // Instead of Test in Jython, GTest is used here
    // It's because the identifier "Test" is alredy used by the @Test
    // GTest is the replacement to avoid the naming confliction.
    test = new GTest(1, "test name");
    request = new HTTPRequest();
    test.record(request);
    grinder.logger.info("before process.");
}

@BeforeProcess 애너테이션이 지정되었기에 프로세스가 생성 전 호출되며 모든 쓰레드가 공유할 데이터를 정의하기 좋은 곳입니다. 테스트 수집을 위한 GTest 인스턴스를 생성하고, HTTPRequest객체인 request 인스턴스를 생성합니다. test.record(request); 부분은 해당 HTTPRequest를 이용한 호출을 nGrinder가 수집하도록 설정하는 부분으로, 다수의 HTTPRequest에 대해 수집하고 싶다면 변수를 하나 더 추가하여 record 메서드에 전달하여 등록해주면 됩니다.

@BeforeThread

// This method is executed once per a thread.
@BeforeThread
public void beforeThread() {
    grinder.statistics.delayReports=true;
    grinder.logger.info("before thread.");
}

쓰레드가 시작되기 전 작업을 정의하는 곳입니다. 주로 타겟 시스템에 로그인을 하거나 쿠키 핸들링 등을 지정합니다. 만약 테스트하는 대상이 HTTPRequest가 아닌 @Test메서드 라면 이 메서드 내에서 아래와 같이 @Test에 대한 성능을 측정할 수 있습니다.

@BeforeThread
public void beforeThread() {
  test1.record(this, "doTransaction1"); // Record current object’s doTransaction1 method into test1.
  test2.record(this, "doTransaction2"); // Record current object’s doTransaction2 method into test2.
  grinder.statistics.delayReports=true;
  grinder.logger.info("before thread.");
}

@Test
public void doTransaction1(){
  // Do transactions here!!
}

@Test
public void doTransaction2(){
  // Do another transactions here!!
}

@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));
    }
}

측정하려는 테스트의 몸체를 작성하는 부분입니다. JUnit는 각 테스트 별로 별도의 테스트 객체를 생성하지만, GrinderRunner는 쓰레드 당 한 개의 테스트 객체를 사용하기에, @Test 메서드들이 같은 멤버 변수를 참조할 수 있습니다. 그렇기에 위의 예시의 testYahoo 메서드는 testGoogle 메서드 결과가 반영된 googleResult 변수의 값에 따라 수행 방식이 달라집니다.


참고자료

반응형

'nGrinder' 카테고리의 다른 글

nGrinder 설치 및 실행  (0) 2020.11.26
Comments