단위 테스트 목표

Jaeyoung·2024년 1월 23일
0
post-thumbnail

단위 테스트를 작성하는 이유는 무엇일까요? 더 나은 설계를 위해서? 아니면 잠재적인 오류를 찾기 위해서?

물론 단위테스트를 작성하면서 더 나은 설계로 나아갈 가능성이 높습니다. 하지만 이건 단위테스트의 목표라기 보다는 좋은 사이드 이팩트라고 볼 수 있습니다.

단위 테스트의 궁극적인 목표는 저비용으로 지속가능한 프로젝트를 유지하는게 목표입니다. 그러면 지속가능한 프로젝트를 위한 좋은 테스트에 대해서 한번 알아보도록 하겠습니다.

단위 테스트와 코드 설계의 관계

만약 내가 작성한 로직이 단위 테스트하기 어렵다면 내 코드가 유지보수가 어려운 코드인지 좀 의심해 볼만 합니다.

일단 단위 테스트하기가 어려운 로직은 일반적으로 여러 코드와 강결합되어 있어 어떤것을 테스트 해야할지 판단하기가 어렵습니다. 또한 여러 코드가 강결합 되어 있는 경우는 관심사의 분리가 제대로 안되어있을 수 있습니다. 이러한 코드들은 대부분 코드개선이 필요하고 이러한 코드를 저품질 코드라고 부릅니다.

단위테스트를 작성하기 위해 코드를 개선하면서 코드 설계에 대해 신경쓰게 되고 테스트하기 어려운 코드보다는 설계가 잘 되어 있을 가능성이 높습니다.

프로젝트의 지속가능한 성장

저품질의 코드는 사이드이팩트로 인해 버그를 트래킹하기가 어렵고 코드가 강결합이 되어 있기 때문에 버그를 트래킹하는데 시간을 많이 소모해야하고 해당 코드를 수정하거나 추가할 때 강결합이 되어 있기 때문에 코드 변경시 파생되는 부분들을 변경하는데도 시간을 많이 소모해야하기 때문에 유지비수 비용이 많이듭니다.

저품질의 코드는 리팩토링 하지 않으면 시스템이 점점 더 복잡해지고 무질서 해집니다. 이로 인해 해당 프로젝트에서 새로운 코드를 작성하더라도 강결합된 코드와 연관이 아예없을 수 없기 때문에 새로만드는 다른 코드들도 저품질의 코드로 양산될 가능성이 높습니다.

테스트코드를 도입하면 초반에는 좀 많이 힘들 수 있지만 코드를 리팩토링하거나 어떤 기능을 추가할 때 안전망 역할을 할 수 있습니다. 또한 QA팀에서 테스트케이스를 만들어주면 해당 부분에 대한 테스트코드를 작성하면 좀 더 안전하게 프로젝트를 운영할 수 있습니다.

좋은 테스트와 좋지 않은 테스트

테스트코드를 작성하는게 프로젝트의 지속가능한 성장과 관계가 있지만 이렇다해서 모든 테스트를 작성할 필요는 없습니다. 단순 코드 커버리지를 높이기 위해 잘못작성된 테스트나 의미없는 테스트를 작성하는건 프로젝트를 오히려 느리게하고 용량만 차지하게 됩니다. 또한 이러한 테스트코드를 작성하기 위한 시간을 소모하면서 쓸데없이 자원만 낭비하게 됩니다.

그러면 의미있는 좋은 테스트는 무엇일까라는 생각이 들 수 있는데 좋은 테스트는 기반 코드가 어떻게 동작하는지 이해할 수 있어야하고 테스트를 기반으로 프로젝트의 시스템을 이해할 수 있어야합니다.

테스트코드도 코드의 일부분이라고 볼 수 있기 때문에 아무래도 관리 포인트가 생긴다고 볼 수 있어서 어떻게 보면 하나의 책임으로도 볼 수 있습니다. 그렇기 때문에 테스트의 가치와 유지 비용을 고려해서 의미있는 테스트를 작성하는게 가장 중요합니다.

테스트 품질을 위한 커버리지

코드 커버리지

  • 코드 커버리지 : 제품 코드 라인 수 / 전체 라인 수
  • 테스트 스위트를 개선하지 않고도 제품 코드 라인 수를 줄일 수 있기 때문에 고품질 테스트인지 판단하기가 어렵습니다.

분기 커버리지

  • 분기 커버리지 : 통과 분기 / 전체 분기 수
  • 코드 커버리지의 단점 극복
  • 분기 갯수로 판단
  • 전체 분기 수는 아래와 같이 구할 수 있습니다.
    public static boolean isLongString(String input) {
    		return input.length > 5;
    }
    해당 코드의 분기는 input의 length가 5이상 그리고 Input의 length가 5 미만 이렇게 2개 존재
  • 통과 분기 수는 아래와 같이 구할 수 있습니다.
    @Test
    public void input으로 abc가 주어졌을 때 isLongString은 false를 반환() {
    		boolean result = isLongString("abc");
    		Assertions.equals(result, false);
    }
    분기중 input의 length가 5 미만인 경우만 테스트 했기 때문에 통과 분기 수는 1개가 됩니다.

테스트 품질을 결정하는데 어떤 커버리지 지표도 의존할 수 없다

테스트 품질은 객관적이지 않고 주관적 이기 때문에 커버리지 지표로 테스트 품질을 판단하기가 쉽지 않습니다. 또한 외부 라이브러리를 사용하는 경우 해당 라이브러리의 코드까지 고려할 수 없기도하고 검증이 존재하지 않는 테스트도 커버리지 지표에 포함될 수 있기 때문에 참고용으로만 보고 테스트 품질은 직접 보면서 확인해야합니다.

성공적인 테스트 스위트

테스트 스위트가 고품질인지 저품질인지 품질은 자동으로 평가가 불가능하기 때문에 개인판단으로 평가해야하기 때문에 판단하기 위한 성공적인 테스트 스위트의 특징을 알려드리겠습니다.

성공적인 테스트 스위트의 특징

  • 개발 주기에 통합
    • 성공적인 테스트 스위트는 개발 주기에 포함시켜 빌드하거나 배포할 때 지속적으로 테스트하도록 합니다.
  • 코드베이스에서 가장 중요한 부분만을 대상으로 합니다.
    • 도메인 모델에 관심을 가지고 비즈니스 로직에 대해 테스트를 합니다.
    • 가치없는 테스트에 시간을 쓰지 않습니다.
    • 여유가 된다면 시스템에 대한 이해를 위해 통합 테스트를 작성하면 좋습니다.
  • 최소한의 유지비로 최대의 가치를 끌어내야합니다.
profile
Programmer

1개의 댓글