본문 바로가기

Daylogs/Java

Testing private method - Methods Should Be Public?

발생일: 2009.12.08

문제:
xper 그룹스 메일링을 받아보고 있는데,
오늘 누군가가 TDD(Test Driven Development) 진행 중 생긴 문제점에 대해 질문을 한 내용이 있다.

유닛 테스트를 위해 모든 메서드를 public 으로 선언하다보니,
"public 메서드가 너무 남발되는 게 아닌가, 객체지향의 원칙을 깨버리는 게 아닌가." 하는 생각이 들었다고 한다.

나도 예전에 같은 문제로 질문한 적이 있었는데,
그 당시에 멤버 변수는 private 으로, 메서드는 모두 public 으로 설정하는 쪽으로 결론을 냈었다.

그에 따라 (테스트를 위해) private 으로 작성된 메서드의 접근자를 단순히 모두 public 으로 바꾸는 식으로 구현했었다.
이 때는 마틴파울러의 Refactoring 책을 읽고 있어서 Replace Temp With Query 기법을 쓴답시고
마침 private 메서드가 굉장히 많을 때이기도 했다.
(결국 한 클래스에 잘게 쪼개진 public 메서드가 꽤 많이 생기게 됐다.)

헌데 요새 디자인 패턴에 대해 공부하다 보니,
요 놈들을 클래스로 빼내고 프록시 패턴이나 퍼사드 패턴을 써서 정리할 수도 있을 것 같다.


여튼, 그건 그렇고, 나도 아직 궁금하다.
과연 단지 유닛 테스트를 하기 위해서 모든 메서드를 public 으로 선언해야 할까?

해결책:
이에 대한 토론이 활발하게 있었다고 한다.

일단 토론은 'private 메서드를 어떻게 테스트 할 것인가? (Testing Private Interfaces)' 부터 시작됐겠다.

그러다 모든 메서드는 public 이어야 한다. 라는 주장이 나오게 된 듯 하다.



"모든 메서드를 Public 으로 하자"는 토론에 대해 정리해보면 아래와 같다.
(각자의 의견을 주거니 받거니 하고 있어 재밌다.^^)




어느 쪽의 의견이 맞다고는 할 수 없겠다.^^;

나는 개인적으로 private 메서드를 쓰는 걸 좋아하긴 하지만,
이 참에 한 번 모든 메서드를 public 으로 쓰는 쪽으로 시도해보려고 한다.

단순히 private 제한자를 public 으로 replace 하는 것 말고,
디자인 자체를 변경하면서 말이다.


그렇다면 어떻게 적용해야 할까....?
위 토론 중에도 있던 내용인데, 참고가 될 것 같아 내용을 덧붙여 적어본다.







  • sunho 2009.12.09 10:53

    오호~ 좋은 내용이네.
    그런데 테스트를 위해 궂이 모든 메서드를 public으로 변환 한다는건...
    사실 JUnit 등의 테스트 프레임 웍을 필요할때만 쓰기 때문에 그런지 몰라도,
    모든 메서드를 테스트 해야 된다는것 자체에 의문이 있긴 해 ㅎㅎ

    private의 의미는 외부에 공개 하진 않겠다는 의미이기 때문에 private 메서드를 public으로
    변환 할 필요 없이, 외부에서 호출되는 public 메서드만 테스트 하는게 맞는게 아닐까 하는 생각이 드네.

    private 메서드를 꼭 테스트 해야 한다면, protected로 변환 한 다음 test source 폴더를 따로 생성해서
    동일한 패키지 구조로 가게 되면 testcase를 적용해서 테스트 할 수 있더라고. 보통은 꼭 protected를
    사용하지 않아도 이렇게 구성하고. (근데 protected도 논란이 많은 접근 지시자라던데 -_- )

    어쨌던 요즘 개발하는것 중에 웹이 아닌 경우에는 testcase를 쓰는데, 편할때도 있고 귀찮을때도 있고 ㅋㅋ

    * 맨날 메신져로 이야기 하다가 블로그에 답글로 올리니까 영 쑥스럽네 ;;

    • ohgyun 2009.12.09 11:16 신고

      ㅇㅇ 확실히 테스트 케이스를 작성하는 건 쫌 귀찮아.^^:

      테스트 케이스 사용을 위해서는,
      public 으로 바꾸는 방법도 있지만 니말처럼 대체로 proteced 를 사용하거나, 또는 default를 사용해서 package 단위로 작성한다고 하더라. 나도 이런 방식으로 사용하고 있고~

      위 토론에서는 protected 나 default 모두, private 으로 취급하는 것 같아. 모두 public 으로 하자는 거니까.

      내가 모든 메서드를 public 으로 바꿔보려는 시도는,
      단지 테스트 케이스를 작성하려는 것 뿐만 아니라-
      이렇게 작성할 때에 (예전에는 생각하지 못했던) 디자인에 대해 더 고민하게 될 것 같아서야.
      오히려 이쪽에 더 의미가 있을 것 같아.