Working Effectively With Legacy Code 내용 중에 테스트 가능한 프로그래밍 기법이 있는데, 재밌는 예제였습니다.
올바른 값을 가져오는지 테스트하기 위해서 탐침(probe)과도 같은 클래스를 만들어냅니다. 보통 메소드 안에서 흘러가는 흐름을 테스트 때문에 감지를 위한 것이지요.

package net.okjsp;
public class Car {
 public void 급정거(int level) {
  // ...
  System.out.println("버럭! "+level+"번");
  // ...
 }
}

저 부분을 테스트하기 위해서 코드를 분리합니다.

package net.okjsp;
public class Car {
 public void 급정거(int level) {
  // ...
  CarSpeaker speaker = new CarSpeaker();
  speaker.yell("버럭! "+level+"번");

  // ...
 }
}

CarSpeaker 는 내용을 감지하기 위한 미끼역할을 하게 됩니다.
package net.okjsp;
public class CarSpeaker {
 public void yell(String string) {
  System.out.println(string);
 }
}

테스트를 위해서 인터페이스를 뽑아냅니다.
package net.okjsp;
public class CarSpeaker implements Speaker {
 public void yell(String string) {
  System.out.println(string);
 }
}

package net.okjsp;
public interface Speaker {
 public void yell(String string);
}


그리고 speaker를 외부에서 지정할 수 있도록 필드로 만듭니다. 지정은 생성자에서 담당합니다.
package net.okjsp;
public class Car {
 private Speaker speaker;
 
 public Car(Speaker speaker) {
  this.speaker = speaker;
 }
 
 public void 급정거(int level) {
  // ...
  speaker.yell("버럭! "+level+"번");
  // ...
 }
}

이렇게 코드의 구성이 끝나면 감지를 전담하는 FakeSpeaker를 만들 수 있습니다.
package net.okjsp;
public class FakeSpeaker implements Speaker {
 String string;
 public void yell(String string) {
  this.string = string;
 }

 
 public String getString() {
  return string;
 }
}

테스트케이스는 다음과 같이 됩니다.
package net.okjsp;
import junit.framework.TestCase;
public class CarTest extends TestCase {
 public void test급정거() {
  FakeSpeaker speaker = new FakeSpeaker();
  Car car = new Car(speaker);
  car.급정거(1);
  assertEquals("버럭! 1번", speaker.getString());

 }
}


처음 코드 보다 설계는 복잡해졌지만, 테스트를 자동화하는 효과를 얻었습니다.
선택의 시간입니다. 그냥 System.out.println(">>>>"+level); 로 원본 클래스를 바꿔서 테스트할 것입니까, 아니면 테스트 케이스를 위해서 소스 코드의 설계를 바꿔서 하시겠습니까.

참고자료
Working Effectively With Legacy Code, Michael C. Features, Prentice Hall, P23-28
까오기님이 정리한 글
http://kkaok.pe.kr/servlet/KBoard?cmd=view&tableName=kmytip&flag=0&search=&findword=&gotoPage=1&seq=124
  1. Unit tests
  2. Test coverage
  3. Black-box testing
  4. White-box testing
  5. Regression tests
  6. Boundary-value tests
  7. Acceptance tests
  8. Load tests
  9. Stress tests

from: J2EE Design and Development, Rod Johnson, 75p

1 유닛테스트가 모이면 5 Regression tests 는 자동적으로 풀리게 됩니다.
8 Load tests는 비즈니스 요구사항에 포함되어야할 것이구요. 9 Stress tests는 8 Load tests를 벗어난 수치에 동작하는 모습을 테스트하게 됩니다.

제 특성 중 하나가 이것 저것 알기는 들은 것은 있는데, 실제로 쓰는 것은 별로 없다는 것이죠. 심한 단점일 수도 있고, 제네럴리스트의 장점일 수도 있죠.
어제 오픈소스 프로젝트 세미나에서 김승권님의 테스트에 대한 내용을 들으면서 나온 테스트 커버리지에 관련된  얘기를 듣고 clover를 이제는 써야겠다 생각이 들었습니다.

해서 연구 시작했습니다.
clover 라는 툴이 있습니다.
http://www.cenqua.com/clover/ 에서 30일 평가판을 다운로드 받을 수 있습니다. 물론 이메일 요구합니다.
 

cenqua clover

clover

흔히 하던대로 zip파일 받아서 eclipse의 plugins 디렉토리 아래에 폴더를 놓아둡니다. 그리고 재시동.

다음과 같은 뷰를 볼 수 있습니다.
사용자 삽입 이미지

clover view


html, pdf, xml의 리포트도 뽑아줍니다.
JUnit 테스트에 날개를 달아준 것 같다는 생각이 듭니다.

+ Recent posts