본문 바로가기

Diary/TIL

2024-04-05) ngrinder 적용 시도

 

시간적 제약으로 공부를 포기한 주제들, 추후에 공부하기로 하였다.

시간 제약으로 인해 공부를 더 이어가지 못했다. 서비스의 견적을 파악하기 위해 ngrinder로 스트레스 테스트를 먼저 수행하고, 이후 pinpoint로 모니터링을 진행하기로 결정했다. 처음에는 ngrinder와 pinpoint를 local 환경에 설치했었는데, ngrinder가 Java 11 버전을 요구하는 단점 때문에 docker-compose를 사용하여 설치했다.

 

설치 과정 중에는 서로 간의 포트 충돌 문제가 발생하여 해결하는 데 어려움을 겪었다. 특히 pinpoint는 8080 포트에서 충돌이 발생하여, 잠시 메인 서비스의 포트 번호를 변경해야 했다.

 

팀원들과 함께 ngrinder 스크립트를 완성했지만, groovy에 대한 학습 부족으로 최적화된 코드 작성에 어려움을 겪었다. 또한, csv 파일을 사용하는 방법에 대한 러닝 커브가 가파르게 느껴졌으며, Java 11 사용 필요성으로 인해 Windows 사용자 중 일부는 설치와 사용에서 어려움을 겪었다. 이에 jmeter 사용도 고려하게 되었다.

아래는 1차적으로 완성된 그루비 코드이다.(여러 명에 대한 로그인 방법이 구현 당시에는 떠오르지 않아 jmeter도 알아보게 되었다.)

import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
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 org.ngrinder.http.HTTPRequest
import org.ngrinder.http.HTTPRequestControl
import org.ngrinder.http.HTTPResponse
import org.ngrinder.http.cookie.Cookie
import org.ngrinder.http.cookie.CookieManager

@RunWith(GrinderRunner)
class LoginAndUseTokenExample {
    public static GTest test
    public static HTTPRequest request
	public static Map<String, String> headers = [:]
	public static Map<String, Object> params = [:]
	public static String token
	public static String body = "{\"email\":\"id",\"password\":\"password\"}"
	public static localhost = "http://127.0.0.1:8080"
	public static domain = "https://pigonair.shop"

    @BeforeProcess
    public static void beforeProcess() {
        test = new GTest(1, "127.0.0.1")
        request = new HTTPRequest()
		// Set header data
		headers.put("Content-Type", "application/json")
		grinder.logger.info("before process.")
    }

    @BeforeThread
    public void beforeThread() {
        test.record(this, "test")
		grinder.statistics.delayReports = true
		grinder.logger.info("before thread.")
    }
	@Before
	public void before() {
		request.setHeaders(headers)
		grinder.logger.info("before. init headers and cookies")
	}
	@Test
	public void homePageAccess() {
        // 토큰으로 접속할 페이지의 예시 URL
        String PageUrl = localhost + "/"
        // 추출된 토큰으로 Authorization 헤더 설정
        // 다른 페이지에 GET 요청 수행
        HTTPResponse PageResponse = request.GET(PageUrl)
		assertThat(PageResponse.statusCode, is(200))
	}

    @Test
    public void test() {
        String loginUrl = localhost + "/login"

        // POST 요청 수행
        HTTPResponse loginResponse = request.POST(loginUrl, body.getBytes())
        assertThat(loginResponse.statusCode, is(200))
		token = loginResponse.getHeader("Authorization")
        assertThat(token, notNullValue())
        // 추출된 토큰을 이용한 후속 요청 수행 예시
        //myPageAccess(token) // 여기서는 예시로 "some_token"을 사용합니다.
		homePageAccess()
		flightAccess()
		seatAccess()
		reservationAccess()
	}

    void myPageAccess(String token) {
        // 토큰으로 접속할 페이지의 예시 URL
        String PageUrl = localhost + "/mypage"
        
        // 헤더 설정
        Map<String, String> headers = [:]
		assertThat(token, notNullValue())
        headers.put("Authorization", token)
        request.setHeaders(headers) // 헤더 설정

        // GET 요청 수행
        HTTPResponse otherPageResponse = request.GET(PageUrl)
        assertThat(otherPageResponse.statusCode, is(200))
    }
	void seatAccess() {
        // 토큰으로 접속할 페이지의 예시 URL
        String PageUrl =localhost + "/api/flight/1"

        // GET 요청 수행
        HTTPResponse otherPageResponse = request.GET(PageUrl)
        assertThat(otherPageResponse.statusCode, is(200))
    }
	
	void flightAccess() {
		HTTPResponse response = request.GET(localhost + "/flight", params)

		if (response.statusCode == 301 || response.statusCode == 302) {
			grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
		} else {
			assertThat(response.statusCode, is(200))
		}
	}
	
	void reservationAccess() {

		HTTPResponse response = request.GET(localhost + "/api/reservation", params)

		if (response.statusCode == 301 || response.statusCode == 302) {
			grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
		} else {
			assertThat(response.statusCode, is(200))
		}
	}
}

 

프로젝트를 마친 후, ngrinder에 좀 더 집중하여 csv 파일을 적용하고, 토큰을 csv 파일로 저장 및 읽는 기능까지 구현했다면 어땠을까 하는 아쉬움이 남는다. jmeter를 테스트 툴로 사용하면서 느꼈던 단점으로 로그 파일을 별도로 출력해야 하고, GUI보다 CUI를 사용해야 하는 점이 생각보다 큰 부담이었다.

'Diary > TIL' 카테고리의 다른 글

2024-04-08) 모니터링&테스트와 관련된 의사결정 여러가지  (0) 2024.05.17
2024-04-06) Pinpoint 등록 시도  (0) 2024.05.15
2024-04-04) JPA 필기 3  (0) 2024.05.14
2024-04-03) JPA 필기 2  (0) 2024.05.14
2024-04-02) JPA 필기 1  (0) 2024.05.13