테스트 계획의 요소 (Elements of a Test Plan)
테스트 계획의 요소 (Elements of a Test Plan)
테스트 계획은 JMeter가 동작하게 하는 모든 구성 요소의 틀이에요. 최소한의 테스트는 Test Plan, 스레드 그룹(Thread Group), 하나 이상의 샘플러(Sampler)로 구성돼요. 여기서는 스레드 그룹, 컨트롤러, 샘플러, 리스너, 타이머, 어서션, 구성 요소, 실행 순서와 스코핑(적용 범위) 규칙까지 테스트 계획을 이루는 각 부분을 살펴볼게요.
본문
3.0 테스트 계획 (Test Plan)
Test Plan 객체에는 "Functional Testing" 체크박스가 있어요. 이걸 선택하면 JMeter가 각 샘플에 대해 서버에서 반환된 데이터를 기록해요. 테스트 리스너에서 파일을 선택했다면 이 데이터가 파일로 쓰여지고요. 설정이 잘 됐는지, 서버가 기대한 결과를 돌려주는지 확인하려고 작게 돌릴 때 유용해요. 단, 그 결과 파일은 금방 엄청나게 커지고 JMeter 성능도 떨어져요. 스트레스 테스트를 할 때는 이 옵션을 꺼야 해요(기본적으로 꺼져 있어요). 데이터를 파일로 기록하지 않는다면 이 옵션은 차이가 없어요. 리스너의 Configuration 버튼으로 어떤 필드를 저장할지 정할 수도 있어요.
3.1 스레드 그룹 (Thread Group)
스레드 그룹 요소는 어떤 테스트 계획이든 시작점이 돼요. 모든 컨트롤러와 샘플러는 스레드 그룹 아래에 있어야 해요. 리스너 같은 다른 요소는 테스트 계획 바로 아래에 둘 수 있고, 그러면 모든 스레드 그룹에 적용돼요. 이름이 뜻하듯 스레드 그룹 요소는 JMeter가 테스트를 실행할 때 사용할 스레드 수를 제어해요. 스레드 그룹의 컨트롤로 다음을 설정할 수 있어요.
- 스레드 수 (number of threads)
- 램프업 시간 (ramp-up period)
- 테스트 실행 횟수 (number of times to execute the test)
각 스레드는 테스트 계획 전체를 다른 테스트 스레드와 완전히 독립적으로 실행해요. 여러 스레드는 서버 애플리케이션에 대한 동시 연결을 시뮬레이션하는 데 사용돼요.
램프업 시간은 JMeter가 선택한 전체 스레드 수까지 "램프업"하는 데 걸리는 시간을 알려줘요. 10개의 스레드에 램프업 시간이 100초라면, JMeter는 10개 스레드를 모두 기동하는 데 100초가 걸려요. 각 스레드는 이전 스레드가 시작된 후 10(100/10)초 뒤에 시작돼요. 스레드 30개에 램프업 120초라면 각 연속 스레드는 4초씩 지연돼요.
램프업은 테스트 시작 시 작업 부하가 너무 커지지 않도록 충분히 길어야 하고, 첫 스레드가 끝나기 전에 마지막 스레드가 시작될 만큼(그렇게 되길 원하지 않는다면) 짧아야 해요. 램프업 = 스레드 수에서 시작해서 필요에 따라 위아래로 조정해보세요.
기본적으로 스레드 그룹은 요소를 한 번 루프하도록 설정돼요. 스레드 그룹은 스레드 수명(Thread lifetime)도 지정할 수 있어요. 스레드 그룹 패널 아래쪽 체크박스를 클릭하면 테스트 기간(duration)과 시작 지연(startup delay)을 입력할 수 있는 추가 필드가 활성화돼요. Duration(초)과 Startup Delay(초)를 설정해 각 스레드 그룹의 지속 시간과 몇 초 후 시작할지를 제어할 수 있어요. 테스트가 시작되면 JMeter는 스레드 그룹의 스레드를 시작하기 전에 Startup Delay(초)만큼 기다리고, 설정된 Duration(초) 시간 동안 실행해요.
3.2 컨트롤러 (Controllers)
JMeter에는 두 종류의 컨트롤러가 있어요: 샘플러(Samplers)와 논리 컨트롤러(Logical Controllers). 이 둘이 테스트 처리를 이끌어요.
- 샘플러는 JMeter가 서버에 요청을 보내도록 해요. 예를 들어 HTTP 요청을 보내려면 HTTP Request 샘플러를 추가하면 돼요. 샘플러에 구성 요소(Configuration Element)를 하나 이상 추가해서 요청을 커스터마이즈할 수도 있어요.
- 논리 컨트롤러는 JMeter가 언제 요청을 보낼지 결정하는 로직을 커스터마이즈하게 해줘요. 예를 들어 Interleave 논리 컨트롤러를 추가해서 두 HTTP Request 샘플러를 번갈아 실행할 수 있어요.
3.2.1 샘플러 (Samplers) — 샘플러는 JMeter가 서버에 요청을 보내고 응답을 기다리게 해요. 트리에 나타난 순서대로 처리되고, 컨트롤러로 샘플러의 반복 횟수를 바꿀 수 있어요. JMeter 샘플러에는 FTP Request, HTTP Request(SOAP 또는 REST 웹서비스에도 사용 가능), JDBC Request, Java object request, JMS request, JUnit Test request, LDAP Request, Mail request, OS Process request, TCP request가 있어요. 각 샘플러는 설정할 수 있는 여러 프로퍼티가 있고, 테스트 계획에 구성 요소를 하나 이상 추가해 더 커스터마이즈할 수 있어요. 같은 서버에 같은 유형의 요청(예: HTTP Request)을 여러 번 보낸다면 Defaults 구성 요소 사용을 고려해보세요. 각 컨트롤러에는 하나 이상의 Defaults 요소가 있어요. 요청 결과를 보거나 디스크에 저장하려면 테스트 계획에 리스너를 추가하는 걸 잊지 마세요. 요청 응답에 대해 기본적인 검증을 수행하고 싶다면 샘플러에 어서션(Assertion)을 추가해요. 예를 들어 웹 애플리케이션 스트레스 테스트에서 서버가 성공적인 "HTTP Response" 코드를 돌려줬어도 페이지에 오류가 있거나 섹션이 빠져 있을 수 있어요. 특정 HTML 태그, 흔한 오류 문자열 등을 확인하도록 어서션을 추가할 수 있고, JMeter는 이런 어서션을 정규표현식으로 만들 수 있게 해줘요.
3.2.2 논리 컨트롤러 (Logic Controllers) — 논리 컨트롤러는 JMeter가 요청을 보낼 때를 결정하는 로직을 커스터마이즈해요. 자식 요소에서 오는 요청의 순서를 바꾸거나, 요청 자체를 수정하거나, 요청을 반복하게 만들 수도 있어요. 논리 컨트롤러가 테스트 계획에 미치는 효과를 이해하기 위해 다음 테스트 트리를 생각해보세요.
Test Plan
Thread Group
Once Only Controller
Login Request (an HTTP Request)
Load Search Page (HTTP Sampler)
Interleave Controller
Search "A" (HTTP Sampler)
Search "B" (HTTP Sampler)
HTTP default request (Configuration Element)
HTTP default request (Configuration Element)
Cookie Manager (Configuration Element)
이 테스트에서 로그인 요청은 첫 번째 통과 때만 실행돼요. 이후 반복에서는 건너뛰는데, 이는 Once Only Controller의 효과예요. 로그인 후 다음 샘플러가 검색 페이지를 로드해요(사용자가 로그인하고 검색 페이지로 가서 검색하는 웹 애플리케이션을 떠올려보세요). 이건 단순 요청이라 논리 컨트롤러를 거치지 않아요. 검색 페이지를 로드한 다음 검색을 하고 싶은데, 서로 다른 두 가지 검색을 하고 싶어요. 그러나 각 검색 사이에 검색 페이지를 다시 로드하고 싶어요. HTTP 요청 요소 4개(load search, search "A", load search, search "B")로 이걸 할 수 있겠지만, Interleave Controller를 쓰면 테스트를 통과할 때마다 자식 요청을 하나씩 넘겨줘요. 자식 요소의 순서를 유지하는데, 무작위로 넘기지 않고 자기 위치를 "기억"해요. 자식 요청 2개를 인터리브하는 건 과할 수 있지만, 8개나 20개가 될 수도 있으니 유용해요. Interleave Controller에 속한 HTTP Request Defaults를 주목해보세요. "Search A"와 "Search B"가 같은 PATH 정보를 공유한다고 해볼게요(HTTP 요청 사양은 도메인, 포트, 메서드, 프로토콜, 경로, 인자 및 기타 선택 항목을 포함해요). 두 샘플러의 PATH 필드에 같은 정보를 넣는 대신, 그 정보를 단일 구성 요소로 추출할 수 있어요. Interleave Controller가 "Search A"나 "Search B"의 요청을 "넘겨줄" 때 HTTP default request 구성 요소의 값으로 빈칸을 채워줘요. 그래서 그 요청들의 PATH 필드는 비워두고 정보는 구성 요소에 넣으면 돼요. 이 경우 이득이 크진 않지만 기능을 보여주는 예시예요. 트리의 다음 요소는 Thread Group 자체에 추가된 또 다른 HTTP default request예요. 스레드 그룹에는 내장 논리 컨트롤러가 있어서 설명한 대로 이 구성 요소를 사용해요. 통과하는 모든 Request의 빈칸을 채워줘요. 웹 테스트에서 모든 HTTP Sampler 요소의 DOMAIN 필드를 비워두고, 대신 그 정보를 Thread Group에 추가한 HTTP default request 요소에 넣는 건 매우 유용해요. 그러면 테스트 계획의 한 필드만 바꿔서 다른 서버에서 애플리케이션을 테스트할 수 있어요. 그렇지 않으면 모든 샘플러를 일일이 편집해야 해요. 마지막 요소는 HTTP Cookie Manager예요. Cookie Manager는 모든 웹 테스트에 추가해야 해요. 추가하지 않으면 JMeter가 쿠키를 무시하거든요. Thread Group 수준에 추가하면 모든 HTTP 요청이 같은 쿠키를 공유해요. 논리 컨트롤러는 조합해서 다양한 결과를 만들어낼 수 있어요.
3.2.3 테스트 프래그먼트 (Test Fragments) — Test Fragment 요소는 Thread Group 요소와 같은 수준으로 Test Plan 트리에 존재하는 특별한 종류의 컨트롤러예요. Module Controller나 Include Controller가 참조하지 않는 한 실행되지 않는다는 점에서 스레드 그룹과 구별돼요. 이 요소는 오로지 Test Plan 내 코드 재사용을 위한 거예요.
3.3 리스너 (Listeners)
리스너는 JMeter가 실행하는 동안 테스트 케이스에 대해 모은 정보에 접근하게 해줘요. Graph Results 리스너는 응답 시간을 그래프로 그려주고, "View Results Tree" 리스너는 샘플러 요청·응답의 세부 정보를 보여주며 응답의 기본 HTML·XML 표현을 표시할 수 있어요. 다른 리스너는 요약이나 집계 정보를 제공해요. 또한 리스너는 데이터를 나중에 쓰도록 파일로 보낼 수 있어요. JMeter의 모든 리스너는 데이터를 저장할 파일을 지정하는 필드를 제공하고, CSV 또는 XML 형식 중 무엇을 쓸지·어떤 필드를 저장할지 고르는 Configuration 버튼도 있어요. 모든 리스너는 같은 데이터를 저장하며, 차이는 화면에 표시하는 방식뿐이에요. 리스너는 테스트 어디에든 추가할 수 있고, 자기 수준 이하의 요소에서만 데이터를 수집해요. JMeter에는 여러 리스너가 들어 있어요.
3.4 타이머 (Timers)
기본적으로 JMeter 스레드는 샘플러를 쉬지 않고 순서대로 실행해요. Thread Group에 사용 가능한 타이머를 하나 추가해 지연을 지정하는 걸 권장해요. 지연을 추가하지 않으면 아주 짧은 시간에 요청을 너무 많이 만들어 JMeter가 서버를 압도할 수 있어요. 타이머는 자기 스코프 안의 각 샘플러 앞에서 일정 시간 지연시켜요. 스레드 그룹에 타이머를 하나 이상 추가하면 JMeter는 타이머 시간을 합산해 그만큼 멈췄다가 적용되는 샘플러를 실행해요. 타이머는 샘플러나 컨트롤러의 자식으로 추가해 적용되는 샘플러를 제한할 수도 있어요. 테스트 계획의 한 지점에서만 멈추게 하려면 Flow Control Action Sampler를 사용할 수 있어요.
3.5 어서션 (Assertions)
어서션은 테스트 대상 서버에서 받은 응답에 대해 사실을 주장하게 해줘요. 어서션을 쓰면 애플리케이션이 기대한 결과를 돌려주는지 본질적으로 "테스트"할 수 있어요. 예를 들어 응답에 특정 텍스트가 포함되어야 한다고 어서션할 수 있어요. 지정하는 텍스트는 Perl 스타일 정규표현식일 수 있고, 응답에 텍스트가 포함되어야 한다거나 응답 전체가 매치해야 한다고 지정할 수도 있어요. 어서션은 어떤 샘플러에도 추가할 수 있어요. 예를 들어 HTTP Request에 "