@VisibleForTesting을 활용에 대한 단상

간만에 개발에 대한 글을 써본다.

코드를 잠깐 봐볼까 싶다가 @VisibleForTesting이라는 Annotation을 봤다. 사실 처음보는 Annotation이라 뭐하는 놈인가 싶은 생각이 들어서 찾아봤다.

Annotation Type VisibleForTesting

  •  
    @GwtCompatible public @interface VisibleForTesting
    Annotates a program element that exists, or is more widely visible than otherwise necessary, only for use in test code.Do not use this interface for public or protected declarations: it is a fig leaf for bad design, and it does not prevent anyone from using the declaration—and experience has shown that they will. If the method breaks the encapsulation of its class, then its internal representation will be hard to change. Instead, use RestrictedApiChecker, which enforces fine-grained visibility policies.
    Author:
    Johannes Henkel

대강 내용을 보니 private method를 테스트 코드에서 참조할 수 있게 해준다.!!! 오 이런 신박한게 있었네. 자바 코드를 짤 때는 저런게 없었던 것 같은데. 나도 쓰는 것에 무던히도 안주했던 모양이다. ㅠㅠ;; 다시 코드짜러 돌아갈 시점에는 보충 공부를 꼭 해야만 적응할 수 있을 것 같다. (읽을 줄 아는걸 짤줄 아는 것으로 이야기하지 말아야겠다라는 생각도 ㅎㅎ)

당연히 해당 Annotation이 적용된 private method에 대해 테스트가 잘 적용되어 있었다. 그런데 이 구조를 보다보니 굳이 이 Annotation을 사용해야 했을까 싶은 생각이 들었다.

단상 1. 주목받으니 더 주목받게 하자!

해당 Method를 별도의 상세한 테스트 코드를 작성할만큼 주목도가 있다면 해당 로직을 method 수준으로 두는게 맞을까? 주목할만한 역할이 있다면 이를 별도의 객체(클래스)로 분리해서 관리하는게 맞지 않을까?

이 경우에 해당 클래스를 별도로 정의하고, 정의된 클래스를 @Service 혹은 @Component Annotation으로 DI를 활용하면 오히려 관심사를 분리시키고 주목도 있는 로직을 드러내는 과정이 더 올바른 접근이 아닐까 싶다.

단상 2. 굳이?

아무리 테스트라고 하더라도 Private method를 노출하는게 맞을까? Private method는 언제든 변경될 수 있는 자유도가 있어야 한다. 그런데 private method를 아무리 테스트라고 하지만 외부에 노출한다면 이 후에 변경할 때 이를 신경써야 한다. 물론 IDE가 지원해주는 refactoring 기능을 쓰면 된다고 이야기할 수 있다. 그럼에도 PR을 날리면 상당히 덩치 큰 변경점이 생긴다. PR Reviewer 입장에서 두루 살펴야 하는데 읽는데 방해가 되는 건 분명하다.

Private method에 있는 코드(로직)을 테스트할 필요가 있다면 이를 이용하는 Public method의 호출 조건을 조정해서 테스트 커버리지(Coverage)를 가져가는게 맞지 않을까? 만약 호출 조건으로 커버리지 달성이 어렵다면 전반적인 코드 구조를 다시 한번 돌아볼 기회도 될 수 있을 것이다.

단상 3. 그럼에도 불구하고!

개인적으로 이걸 쓰는 걸 추천할 만한 상황은 Public 대상을 테스트가 통합 테스트(Integration Test) 수준의 테스트 비용이 발생하는 경우다. 테스트 대상 코드에 주의할 점을 명확하게 하고 싶은데, Public 대상을 테스트할려고 할 때 1~3초가 수행된다면? 이런 상황에서 특정 상황에 대한 테스트를 추가하는 건 시간이라는 과한 비용을 수반한다.

테스트 코드를 작성하는 기본이 된 개발자

이러나 저러나 테스트를 작성하겠다는 개발자의 자세는 훌륭하다.

다만 전체 테스트들은 5분 이내로 완료될 수 있어야 한다. 단위 테스트와 통합 테스트를 모두 포함해서. 특히나 통합 테스트는 배포할 코드가 안전함을 개발자 관점에서 보장하기 위해 수행되야 한다. 떄문에 반드시 CI 과정에서 필수적으로 수행되어야 한다. 그런데 이 단계에서 십수분이 소요되면 안된다.

커피한잔하고 왔는데도, 밥먹고 왔는데도 끝나지 않은 CI를, 특히 통합 테스트가 여전히 돌고 있는 걸 경험하면 정말 테스트 코드 관리를 잘 해야 한다.

– 끝 –