'테스트'에 해당되는 글 7

  1. 2011.08.09 테스트가 필요한 이유
  2. 2011.03.30 표준 출력을 사용하는 어플리케이션을 테스트하는 방법
  3. 2011.03.30 인증서를 사용해서 전자서명, 암/복호화를 하는 통신 모듈을 테스트하기
  4. 2011.01.27 시그널 처리 테스트 코드 작성
  5. 2011.01.20 JUnit TestSuite 사용하기
  6. 2010.12.10 BigDecimal - 100 과 100.00
  7. 2010.10.05 이제는 테스트케이스를 만들지 않으면 불안하다.

테스트가 필요한 이유

IDE에서 만든 생성자
Copy & Paste
private String number;

public CourseSession(String department, String number2, Date startDate) {
	this.department = department;
	this.number = number;
	this.startDate = startDate;
}
@Before
public void setUp(){
	startDate = createDate(2003, 1, 6);
	session = new CourseSession("ENGL", "101", startDate);
}

@Test
public void testCreate(){
	assertThat(session.getDepartment(), is("ENGL"));
	assertThat(session.getNumber(), is("101"));
	...
}

표준 출력을 사용하는 어플리케이션을 테스트하는 방법

간혹 UI 를 표준 입/출력을 사용하는 어플리케이션이 있다.
표준 출력으로 메뉴를 보여주고 해당하는 문자를 누르면 다른 기능이 화면에 뿌려진다.
(예전의 PC 통신처럼)

또는 어떤 기능의 실행 성공여부가 표준 출력을 확인해야 하는 경우도 있다.
에러는 나지 않았는데 표준 출력으로 ERROR 이런 문자열만 출력되고 마는 경우가 종종 있는데, 이런 어플리케이션의 테스트를 자동화하는게 힘들다.

고민을 하다보니 표준 출력을 잡아서 비교하면 될거 같다.

System.setOut(PrintStream) 을 사용하면 됨.
바이트 기반 스트림이 필요한데 찾지를 못해서 조금 헤맸다.(감이 떨어지는구나...)
필요하면 File 스트림을 이용해서 파일로 남겨서 처리해도 됨.

인증서를 사용해서 전자서명, 암/복호화를 하는 통신 모듈을 테스트하기

- 서버 to 서버 통신을 하는 모듈
- SendSOAPServlet -> SendSOAPServiceImpl -> SOAPMessage 를 사용하는 구조임.

- SendSOAPServiceImpl#proc(...) 를 수정하고자 함.
이 메서드는
  1. 데이터를 가져와서
  2. XML 문서를 생성하고
  3. SOAPEnvelope 와 SOAPMessage 를 생성하고
  4. 생성된 XML 문서를 MIME 에 추가한다.
  5. 첨부파일을 암호화해서 추가
  6. 전자서명 생성, 검증
  7. MimeBodyPart 생성
  8. XML, SOAP 파일로 저장
  9. 전송
  10. 응답 수신
을 처리한다.

1) 서버에 접속하지 못하므로 전송시 에러가 무조건 발생함.
이 예외를 처리하고 SOAP 메세지에서 MessageDigest, SignatureValue 를 비교해 보면 됨.

2) 굳이 통신까지 가지 않아도 전송 전 SOAP 메세지가 제대로 만들어졌는지만 확인하면 됨.
(proc 메서드가 나누어졌으면 테스트 하기 쉬웠을텐데 덩치가 너무 크다.)
SOAPMessage 클래스를 테스트하면 된다.

- 관련 파일이 많아서 해당 패키지 아래에 res/ 를 만들었다.
(여기에 각 인증서 디렉토리, 로그 디렉토리 등을 둔다.)

- XML 문서는 미리 만들어진 파일을 이용함.(데이터베이스 연결이 필요없음)

- 설정파일에서 읽어오는 부분을 직접 하드코딩함.
(이 부분이 변경되는 것도 아니고, 별도의 테스트용 설정 파일을 만들 필요가 없었다. - 이 부분은 상황마다 다르겠지.)

- 테스트를 위한 인증관련 설정파일을 별도로 만들어서 res/ 에 두었다.
이렇게 테스트하니 인증관련 설정파일에 대한 설정을 이것저것 바꿔가면서 계속 실행해 볼 수 있어 각 설정값의 역할에 대해서 깊게 이해할 수 있었다.

- 인증서 암호파일은 각 머신에서 생성되어야 하므로 테스트 전 직접 생성해야 한다.

- 기존에 문제없이 돌아가던 모듈이므로 먼저 이에 대한 테스트 코드를 작성한다.
그리고 원하는 기능에 대한 테스트  코드를 추가한다.

시그널 처리 테스트 코드 작성

- 인터럽트 거는 부분은 어떻게 작성해야 하나?

- 테스트를 작성하면서 알아낸 사실
testRaise() 에서 시그널을 발생시켜도 바로 전달되지 않는다는 것을 알게 되었다.
sleep 을 하지 않으면 테스트가 실패할 경우도 생긴다.

테스트 작성의 순기능인가...ㅎㅎ

JUnit TestSuite 사용하기

@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class}) //TestCase, TestSuite 가 올 수 있다.
public class AllTests {

    public static Test suite() {
        TestSuite suite = new TestSuite("Test for tt");
        //$JUnit-BEGIN$

        //$JUnit-END$
        return suite;
    }
   
    //@BeforeClass, @AfterClass 는 가장 먼저, 늦게 실행된다.
    //@Before, @After 는 실행 안됨.
}
여기에서 데이터베이스 초기화 작업을 하자.

BigDecimal - 100 과 100.00

합이 100인지 비교하는 코드가 있다.
합이 100.00인데 예외가 발생한다. 테스트케이스를 작성해 본다.
BigDecimal#equals() 는 scale을 비교한다.

데이터베이스에서 데이터를 가져와서 비교할때 primitive type으로 비교하는게 좋을거 같다.

이제는 테스트케이스를 만들지 않으면 불안하다.

업무단에서 에러가 발생해서 응답 XML을 생성하지 못하는 경우 통신단에서 SOAP Envelope에 에러를 넣어준다.(eb:ErrorList)
그러나 에러 메세지를 제대로 처리하지 못해서 테스트를 작성해서 수정했다.

SOAPEnvelope라는 클래스에서 처리하는데 다행히 POJO 형태이고 외부 설정이나 기타 다른 의존성이 없었다.
테스트케이스를 작성하는데 어려움은 없었고, 테스트케이스를 작성하면서 잘못 구현된 부분을 발견하였다.
잘못 구현된 부분이 프로그램에서 영향을 주는 부분이 아니고, 수정한 프로그램을 20개가 넘는 고객사에 다시 배포를 해야 하는 문제때문에 확인만 하고 넘어간다.
이제는 테스트케이스를 만들지 않으면 불안하다.

- SOAP 메세지를 동일 패키지에 있는 파일에서 읽어오도록 한다.(언제든지 테스트가 실행될 수 있도록, 클래스패스로 읽어들이는 것이 가장 좋지 않나?)