2. 케익썰기 모델로 바꾸어 볼 필요도 있습니다.
private 메소드 하나하나를 단위 테스트 하는 것도 유용하지만
그것을 사용하는 public 메소드만을 위한 단위 테스트를 만들 수 없는지 고민해 보면 좋겠지요...
김밥해체하기 보다 김밥썰기를 하도록 애를 쓰면 private을 단위 테스트하는 부분이 줄어 들기도 하거든요...
1번. TDD를 하다보면 코드가 전반적으로 functional로 가는 경향이 있습니다. 저는 대부분 변수는 파라미터로 넘기는
방식으로 탄생시킨 다음, 여러 메소드에서 그 변수를 필요로 하면(즉, 파라미터 리스트에서 메소드간 중복이 발생하면), 그 때
리팩토링을 합니다. 몇가지 방식이 있는데 그 중 하나가 인스턴스 변수로 바꾸는 것이죠.
실제 코드 예(단순화된 예가 아니고)를 보여주시면 제가 비슷한 경우에 어떻게 했는지 말씀드릴 수 있겠습니다.
2번. http://xper.org/wiki/xp/TestingPrivateInterfaces 를 참고하세요. 2004년도에
한창 진행했던 논의입니다.
2009/12/7 ChungHee Lee <dre...@gmail.com>:
2번에 대해서는 항상 말이 많은 부분입니다. 저의 견해는 private 의 경우 public 에서 사용이 되므로 굳이 테스트를
위해 public 으로 열 이유는 없다고 봅니다. 보통 private 이라면 해당 클래스의 public 메소드에 지원을 해주는
helper 의 성격이 강하므로 독립적으로 호출을 하는 것은 그다지 의미가 없다고 봅니다. 독립적인 호출이 의미가 있다면
public 으로 개방을 하는 것이 맞겠죠. 그래도 굳이 private 을 따로 테스트를 해야 마음이 놓이겠다 싶으면
reflection 을 사용해서 테스트를 합니다. 물론 언어차원에서 지원이 되어야 겠죠.
아시아나IDT 손태원입니다.
1. 내부 변수 의존성 문제
A. 테스트를 위해 내부 변수를 다시 파라미터로 전달할 필요는 없다고 생각합니다
B. 내부 변수를 설정하는 함수를 이용해서 테스트를 통제하는 것이 좋겠습니다. 그러면 내부변수 변화에 따른 테스트 결과 의존성을 통제할 수 있다고 봅니다.
C. 그리고 언어환경이 무엇인지는 모르지만, 테스트 함수를 제품 클래스에 넣는 것도 이상하군요. 그게 아니라면….
2. Public 남용 문제
A. 테스트 코드 작성 전에 Private였는데 테스트를 위해 public으로 전환했다면 확실히 문제라고 보여집니다.
B. 테스트 용이성은 테스트 코드 자체만으로는 향상되지 않는다고 보아야 합니다.
C. 테스트 코드를 잘 작성하는 훈련도 필요하지만, 근본적으로 제품 코드의 설계가 테스트 용이하지 않는 경우가 많을 것이라고 보여집니다.
D. 따라서 제품 코드가 테스트 용이하지 않다면, 리팩터링을 선행해야 하는지 검토해보시기를 권해드립니다.
E. 그리고 테스트는 클래스 내부의 모든 함수와 기능을 테스트 하는 것이 아니라고 알고 있습니다.
F. 외부에 노출되고 사용되는 의미 있는 Behavior에 대해서 테스트하는 것이 단위테스트이니 테스트 코드를 과도하게 작성하려는지 살펴보아야겠습니다.
TDD 실전 경험은 그리 많지 없지만 학습하고 이해한 바에 따라 의견을 회신드립니다. 혹시 작성하신 대상 코드를 가지고 실제로 토론을 해도 된다면 저로도서 많은 도움이 될 것 같습니다.
추가적으로 원래의 질문에 나온 코드를 파고들어 급진적으로 질문한다면,
정말로 if 분기가 필요할까요?
2. 외부에서 사용하지 않는 메서드는 사실상 사용하지 않는 메서드와 동일하다고 봅니다.
private 메서드가 필요하다면, 정말로 private으로 만들려는 이유를 찾아
해당 책임을 작은 클래스 하나에 위임하는 게 좋다고 봅니다.
TDD에서 경험하는 것과 단위 테스팅을 혼동하는 케이스가 보이는 것 같은데
저는 두가지를 명백히 구분해 설계 개선에 도움을 주는 게 유용한 전략이라고 봅니다.
2009년 12월 8일 오전 9:27, 손태원-핫메일 <ldst...@hotmail.com>님의 말:
최근에 저는 TDD라기 보다 기존에 작성된 코드 중에 UnitTest를 붙이는 것을
많이 해보고 있습니다.
설계상의 옳고 그름을 떠나 기존 코드를 변경하지 않고 UnitTest를 붙일 수는 있습니다.
1. 내부변수 사용의 경우
Test해야할 class를 상속받아서 Mock class를 만들고 Mock class 에서 내부 변수를 셋팅하는 함
수를 만들고,
Mock Class를 test하면 되겠지요. 그럼 기존 class에는 전혀 손대지 않고 UnitTesting가능하
게 됩니다.
2. Public method의 남발
Public이 싫으시면 가급적 protected로 사용하시고 역시 Mock Class를 이용해서 public 상속
을 받아서,
Mock Class를 test하면 됩니다.
제가 기존 코드를 변경하지 않고 UnitTest를 붙이는 것을 언급한 것은
최근에 제가 이런류의 작업을 많이 하고 있어서 입니다.
저희 회사의 경우 처음부터 TDD로 작성되지 않았으나, 재사용이 상당부분 되어
지속적으로 수정되고 있는 Legacy 코드들이 많고 이런 쪽에 문제점이 지속 발견되다보니,
UnitTest를 이미 짜져있는 코드에 많이 넣을 필요성이 있더군요.
기존 코드에 손을 대지 않고 UnitTest를 넣는 것이 쉬운 부분이 아니더군요.
특히 앞선 예와 같이 내부 state를 가지지 않는 function들은 쉽게 UnitTest가 붙을 수 있으나,
내부 state를 복잡하게 많이 참조하는 것들의 경우는 UnitTest 붙이는 것이 쉽지만은 않습니다.
물론 testable하게 refactoring하면 좋겠지만,
기존 코드에 UnitTest가 이미 많이 작성되어 있으면 refactoring또한 두려움이 없어지나,
그렇지 않기 때문에 refctoring또한 side-effect의 두려움으로 현장에서는 쉽지만은 않은 작업입니다.
이와 관련해서 읽어볼만한 책을 추천합니다.
"Working Effectively With Legacy Code" by Michael C. Feathers from
PRENTICE HALL
Public의 남발의 경우 대신 protected를 사용하면
JAVA가 아니라 C++ 관련입니다만,
GoogleTest에서는 FRIEND_TEST() 라는 macro를 지원해줘서 test case에 대한
friend ship을 이용해서 처리할 수 있습니다.
저의 회사의 경우 UnitTest++ framework을 사용하다 여러 이점 때문에 최근에 GoogleTest로 옮겼탓습니다.
간단한 python script으로 기존 UnitTest++ 로 작성된 코드를 전부 GoogleTest로 쉽게 옮겨서,
생각만큼 Framework 옮기는 것의 overhead는 커지 않은 듯 합니다.
여하튼 지금 갖고 있는 정보에서 말씀드리면,
설계를 바꿔서 해결하는 방법으로는 다음 두가지 방법이 생각이 나네요.
1) Downloader를 몇 개의 class로 쪼갠다 (coherent한 놈들끼리 묶어서 -- 이 경우 새로 생긴
클래스들의 메소드를 테스트함)
2) Downloader를 생성하기 쉽게 "가볍게" 만든다. DI 사용. (이 경우 파라미터를 새로 추가하지 않고 테스트)
인스턴스 변수랑 메소드 파라미터랑 둘 다 중복으로 있는 것은 리팩토링 대상이라고 생각합니다.
그리고 Downloader라는 이름에 대해. http://xper.org/wiki/seminar/OOP_c0_fb 참고하세요.
테스트하기 어려운 것은 대부분 설계 문제입니다.
2009/12/8 ChungHee Lee <dre...@gmail.com>:
--~--~---------~--~----~------------~-------~--~----~
한국 XP 사용자 모임(http://xper.org) 메일링 리스트에 가입하셨기에 이 메시지를 보내드립니다. Google 그룹스 "xper" 그룹
이 그룹에 게시하려면 다음 주소로 이메일을 보내주십시오.
xp...@googlegroups.com
이 그룹에서 탈퇴하시려면 다음으로 이메일을 보내주십시오.
xper+uns...@googlegroups.com
추가 옵션을 보려면 http://groups.google.com/group/xper?hl=ko?hl=ko의 그
룹을 방문하십시오.
-~----------~----~----~----~------~----~------~--~---