[질문] Test 관련

1 view
Skip to first unread message

ilovemedic

unread,
Oct 19, 2009, 11:19:13 PM10/19/09
to Korea Spring User Group
안녕하세요~
Test 에 대한 질문 좀 하렵니다.
전형적인 비대한(?) Service Layer 를 Test 로 개발합니다.

public interface XYZService {
public void insert(XYZ domain) throws Exception;
......
}

public class XYZServiceImpl implements XYZService {
public void insert(XYZ domain) throws Exception{
//이렇쿵 저렇쿵
.....
}
}

public class XYZServiceImplTest {

@Autowired
public XYZService xyzService ;

@Test
public void testInsert1(){ //-------------------------1
XYZ domain = ......
xyzService.insert(domain);
}
}

XYZServiceImpl 를 구현하기 위해서 XYZServiceImplTest 를 만들고
XYZServiceImpl 수정 -> XYZServiceImplTest 실행 -> ... 이라는 과정을 반복하여
개발을 합니다.

위의 1은 XYZServiceImplTest 는 "만들어진 XYZServiceImpl 를 테스트하는" 모양새인거 같습니다만,
XYZServiceImplTest 가 "XYZServiceImpl 를 만들기 위한 테스트" 가 되려면
다음과 같야야 하지 않을까 생각이 들기도 합니다.
@Test
public void testInsert2(){ //-------------------------2
XYZ domain = ......
//이렇쿵 저렇쿵
}


크게 중요한 이슈인지는 모르겠으나,
테스트가 "정의된 클래스가 잘 동작하는지"를 확인하는 것인지,
아니면 "구현 방안의 선행 확인" 인지 ,
실제 배포되는 테스트 소스는 어느쪽에 더 중점을 두어야 하는 걸까요?
여러분들의 고견을 듣고 싶습니다.

안영회

unread,
Oct 20, 2009, 12:32:45 AM10/20/09
to ks...@googlegroups.com

public interface XYZService {
 public void insert(XYZ domain) throws Exception;
 ......
}

public class XYZServiceImpl implements XYZService {
  public  void insert(XYZ domain) throws Exception{
      //이렇쿵 저렇쿵
      .....
  }
}

public class XYZServiceImplTest {

   @Autowired
   public XYZService xyzService ;

  @Test
  public void testInsert1(){    //-------------------------1
      XYZ domain = ......
      xyzService.insert(domain);
  }
}

XYZServiceImpl 를 구현하기 위해서 XYZServiceImplTest 를 만들고
XYZServiceImpl 수정 -> XYZServiceImplTest 실행 -> ...   이라는 과정을 반복하여
개발을 합니다.

위의 1은 XYZServiceImplTest 는 "만들어진 XYZServiceImpl 를 테스트하는" 모양새인거 같습니다만,
XYZServiceImplTest 가 "XYZServiceImpl 를 만들기 위한 테스트" 가 되려면
다음과 같야야 하지 않을까 생각이 들기도 합니다.
  @Test
  public void testInsert2(){    //-------------------------2
      XYZ domain = ......
       //이렇쿵 저렇쿵
  }


XYZService 구현체 내부에 있던 로직(//이렇쿵 저렇쿵)이 밖으로 나와 테스트 메소드로 옮겨야 로직을 테스트 할 수 있다면, 테스트가 어렵게 설계/프로그래밍한 징후입니다. 테스트 하는 클래스와 테스트 대상 클래스 사이에 주고 받는 것을 명확하게 해야 테스트가 쉬워지죠.  아마 앞서 말씀하신대로 비대한(?) 서비스 레이어에서 많은 내용을 엮어서 처리하다보니 테스트를 위해 로직을 밖으로 빼려고 하시는 것이 아닌가 짐작할 수 있네요.


크게 중요한 이슈인지는 모르겠으나,
테스트가 "정의된 클래스가 잘 동작하는지"를 확인하는 것인지,
아니면 "구현 방안의 선행 확인" 인지 ,
실제 배포되는 테스트 소스는 어느쪽에 더 중점을 두어야 하는 걸까요?

개념적인 면으로 보면 궁금해하시는 내용이 다른 사람들은 "테스트를 먼저 하는 TDD의 절차(Test First)"를 중요하게 생각하는지 아니면 테스트 자체 혹은 테스트를 통해 클래스 정상 작동을 검증하는 면을 중요하게 생각하는지 아닌가 싶네요.

저는 후자를 더 중요하게 생각합니다. 특히 실전 프로젝트에서라면 더욱 그렇죠. 테스트를 안 만들어도 잘 짤 수 있는 코드라고 해도 여러 가지 이유로 프로그램은 변화할 필요가 생깁니다. 테스트를 만들어둠으로 해서 변경에 따른 영향을 알 수만 있어도 대단한 도움이 됩니다. 짧게 보면 코드 개선을 위한 리팩토링도 테스트 코드가 있을 때 마음 놓고 할 수 있으니까요.

절차를 우선하는 방식은 일을 영리하게 하고, 시간을 똑똑하게 쓰는 훈련을 위해 가끔 진행합니다. 굳이 프로그래밍이 아니더라도 어떤 일을 할 때 내가 이 일을 제대로 했는지 검증할 구체적인 방법을 생각해보려고 노력하는데.. 이는 모두 TDD에서 착안한 방식이죠.

wansu yang

unread,
Oct 20, 2009, 1:46:11 AM10/20/09
to ks...@googlegroups.com

고수는 아니지만 많은 생각을 했던 부분이라 저도  코멘트하나 날립니다.
 
우선 XYZService  에 대한 Test 가 이미 레거시 한 코드 에 대한 리펙토링 을 위한 Test 인지 궁금하군요..
 
만약 이렇다면  "정의된 클래스가 잘 동작하는지" 에 대한 용기 적인 측면에서 Test 가 의미를 가지는 것이라 고생각이듭니다.
물론  레거시한 코드가 아닌 구현해야하는 코드 에서도 이런 용기적인 측면에서의 Test가 더 의미를 가지고 구현방안의 선행이 따라온다고 생각이 듭니다.
 
 
  @Test
  public void testInsert2(){    //-------------------------2
      XYZ domain = ......
       //이렇쿵 저렇쿵
  }
 
 //이렇쿵 저렇쿵 이 밖으로 빠져서 Test 가 된다면 XYZService 와 Test 간 연관 관계(?)가 모호하게 되어 나중에 Test case 를 보고 XYZService 에 대한 신뢰를 가지기 힘들것이라 생각이듭니다.
 
 
여기서 질문이.....
 
길어 진 extra method 리펙토링 등을 통해 나온 private method 를 test 를 해야 하나요? 만약 해야한다면 private 라는 접근 에대한 핸디캡은 어떤식으로 극복하시나요?
 
PS ....
그런데 저는 TDD 과정 자체가 마치 저에게는 수학 문제를 풀기 위해 좌변 우변에 살을 붙혀가면 소거해가며 심플한 공식으로 유도해가는 과정처럼 느껴지더군요...
 
 
2009년 10월 20일 오후 1:32, 안영회 <ahnyo...@gmail.com>님의 말:


--
===========================================================

안녕하세요! 양완수 입니다.
+HP      : 010 2008 4167
+Email  : ywsa...@gmail.com , yang...@daumsoft.com
+
===========================================================

안영회

unread,
Oct 20, 2009, 2:56:57 AM10/20/09
to ks...@googlegroups.com
PS ....
그런데 저는 TDD 과정 자체가 마치 저에게는 수학 문제를 풀기 위해 좌변 우변에 살을 붙혀가면 소거해가며 심플한 공식으로 유도해가는 과정처럼 느껴지더군요...

적절한 비유네요. 말씀하신 과정이 저에겐 "자동화 테스트 기반" Refactoring의 효과라 생각하는데, 마치 뒤엉킨 공식(Business Logic)을 점차 명확한 식으로 확립한다면 면에서 두 가지 활동이 매우 닮아 있다 생각합니다.
 

ilovemedic

unread,
Oct 20, 2009, 10:13:11 PM10/20/09
to Korea Spring User Group
생각해보니 제가 그렇게 길고 큰 메소드를 경험한적이 없는것 같기도 하고....
아뭏튼 extra method를 refactoring 하던중에
private method 를 생성해야만 하는 상황을 매우~ 달가워하지 않습니다,
발생하지 않토록 설계부터 다시 다 뜯어 고쳐야 직성이 풀릴것 같네요.. ^^;

제질문이 extra method 테스트에 관련된 것처럼 흘렀지만
영회님의 글중에 다음 부분에서 잘 요약 된것 같습니다.

"테스트를 먼저 하는 TDD의 절차(Test First)"를 중요하게 생각하는지
아니면 테스트 자체 혹은 테스트를 통해 클래스 정상 작동을 검증하는 면을 중요하게 생각하는지"

TDD 순수(?)주의에 의거하여 개발 한다면 다음과 같은 프로세스를 가지게 되지 않나요?
구현 테스트 (//이렇쿵) ->
구현 테스트(//저렇쿵) -> ..... ->
서비스 구현체 완성(XYZServiceImpl)

클래스 정상 작동을 검증하는 면을 중점에 두고 개발 한다면
XYZServiceImplTest 작성 ->
서비스 구현체 수정(//이렇쿵) ->
동작 테스트 ->
서비스 구현체 수정(//이렇쿵) ->
동작 테스트 ->....... ->
서비스 구현체 완성(XYZServiceImpl)

물론 두 과정을 모두 진행하는 프로젝트도 있을것 같고
과연 TDD 를 실전 프로젝트에서는 어떻게 적용하며 그 과정은 어떠한가가 궁금합니다.

Reply all
Reply to author
Forward
0 new messages