[junit + jmock] 자바 멀티 쓰레딩 테스트 케이스 만들기
멀티쓰레딩 테스트는 어떻게 해야 할까?
플랫폼 단에 전문을 송신을 해야 하는 소스는 사용의 빈도가 매우 높다. 한개의 스레드가 아닌 여러개의 쓰레드를 동시에 사용해야 하기 때문에 멀티쓰레딩의 환경에서 어떻게 사용되는가가 시스템의 성능을 좌우 한다고 볼수 있다.
코드를 짜는 것은 여기저기 참고해서 만들수 있지만 이게 정말 멀티 쓰레딩 환경에서 데드락이 걸리지 않는지를 확인 하려면 테스트를 해봐야 한다.
하지만. 어떻게? 수백 수천의 쓰레드를 한번에 어떻게 발생 시킬 것인가?
로컬환경에서 주구장창 개발을 하는 개발자의 입장에서 수천번의 트래픽을 발생시키는 것은 쉽지가 않다. (반복문을 생각했다면 땡이다. 반복문은 쓰레드 1개의 작업이다!)
그러한 고민은 TDD를 신봉하는 진영에서 몰랐을리 없다. 딸랑 자바 클래스 1개의 기능을 확인 하기 위해 고민해야 했던 수많은 삽질을 덜어주는 junit 이 있고 거기에 jmock이라는 걸출한 테스트 기능을 가진 라이브러리가 존재하는 이유도 바로 이와 같을 것이었다.
사전 작업 - maven 라이브러리 등록
<!--...생략...-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-junit4</artifactId>
<version>2.12.0</version>
<scope>test</scope>
</dependency>
<!--...생략...-->
메이븐 라이브러리를 위에 2개 등록 해야 한다. junit과 jmock은 여러버전이 있기 때문에 해당 버전이 맞는 라이브러리를 사용해야한다. 잘보고 찾아라
테스트 케이스 만들기
import java.util.concurrent.atomic.AtomicInteger;
//멀티 쓰레딩을 발생시키는 주요 클래스
import org.jmock.lib.concurrent.Blitzer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.StopWatch;
public class HttpUrlClientTest {
AtomicInteger c;
//10000개 작업 100개 쓰레드 설정
Blitzer blitzer = new Blitzer(10000, 100);
@Before
public void setUp() {
c = new AtomicInteger(0);
}
@Test
public void testSend(){
StringBuffer sb = new StringBuffer() ;
sb.append("<<test_param:필요한거집어넣어>>");
HttpUrlClient client = new HttpUrlClient();
StopWatch sw = new StopWatch();
sw.start();
try {
blitzer.blitz(new Runnable() {
@Override
public void run() {
try {
String retDoc = client.send("http://localhost:8080/mult.xml", sb.toString());
//jmock을 사용해서 mockup 데이터를 호출하는 방법도 있지만,
//이왕이면 서버를 호출하는 작업을 보고 싶어서
//간단하게 다이나믹 웹 프록젝트를 만들고 톰캣에 띄어 봤다.
c.getAndIncrement();
System.out.println(Thread.currentThread().getName() + ": done | job count : "+c.get());
}
catch (Exception e) {
e.printStackTrace();
}
}
});
sw.stop();
System.out.println("execute time : " + sw.getTotalTimeSeconds());
System.out.println("execute count : " + c.get());
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@After
public void tearDown() throws InterruptedException {
//끝나고 반드시 꺼주는 센스
blitzer.shutdown();
}
}
이렇게 테스트 코드를 짜주고 테스트를 돌리면 된다.
테스트 결과 확인
pool-1-thread-81: done | job count : 9977
pool-1-thread-92: done | job count : 9978
pool-1-thread-10: done | job count : 9979
pool-1-thread-19: done | job count : 9980
pool-1-thread-60: done | job count : 9981
pool-1-thread-82: done | job count : 9982
pool-1-thread-33: done | job count : 9983
pool-1-thread-22: done | job count : 9984
pool-1-thread-68: done | job count : 9985
pool-1-thread-52: done | job count : 9986
pool-1-thread-65: done | job count : 9987
pool-1-thread-45: done | job count : 9988
pool-1-thread-57: done | job count : 9989
pool-1-thread-69: done | job count : 9990
pool-1-thread-11: done | job count : 9991
pool-1-thread-34: done | job count : 9992
pool-1-thread-78: done | job count : 9993
pool-1-thread-86: done | job count : 9994
pool-1-thread-61: done | job count : 9995
pool-1-thread-20: done | job count : 9996
pool-1-thread-79: done | job count : 9997
pool-1-thread-12: done | job count : 9998
pool-1-thread-85: done | job count : 9999
pool-1-thread-53: done | job count : 10000
execute time : 11.915
execute count : 10000
PS.
정리하다가 보니 조금 이상한건.. 잡카운트가 일정하게 순서대로 늘어나서 뭔자 좀 꺼림찍 하다. 멀티 쓰레딩인데.. 순서대로 늘어 난다는게 뭔가 맞지 않다. 쓰레드가 여러개가 동시에 돈다고 생각했는데 쓰레드 여러개가 순차적으로 돌고 있는 것 같은 느낌이 든다. 뭔가 다시 확인해 봐야 될것 같다.
Comments