////
Search
Duplicate
🎱

1. 단위 테스트의 목표

1장에서 다루는 내용
단위 테스트의 상태
단위 테스트의 목표
좋지 않은 테스트 스위트의 결과
테스트 스위트 커버리지 지표
성공적인 테스트 스위트의 속성
단위 테스트는 단순히 테스트를 작성하는 테스트 프레임워크, 모킹 라이브러리를 공부하며 기술을 익히는 것을 포함하는 아주 큰 범주의 개념이다.
단위 테스트을 작성할 때는 들이는 노력을 가능한 줄이고 이득을 최대화하는 것을 목표로 해야 한다.
이러한 프로젝트들은 무난하게 성장하고 유지보수가 많이 필요하지 않으며 변화하는 요구사항에 신속히 대응할 수 있다.
그렇지 않은 경우, 노력을 많이 들이고 단위 테스트를 매우 많이 작성하더라도 많은 버그와 유지비로 프로젝트 진행이 느려지게 된다.
이런 차이는 단위 테스트를 어떻게 하는가에서 온다.
이 책에서 다루는 내용은 어떤 단위 테스트 기술이 좋은지를 구별하는 데 도움을 준다.
테스트에 대한 비용 편익 분석 방법을 배우고 특정 상황 별 적절한 테스트 기술을 학습한다.
공통적인 안티 패턴을 피하는 방법도 배운다.
이 장에서는 단위 테스트의 현황을 살펴보고 테스트 작성과 유지보수의 목표를 설명하며 테스트 스위트를 잘 작성하기 위한 방법을 소개한다.

1. 단위 테스트 현황

대부분의 프로그래머는 단위 테스트를 실천하고 그 중요성을 알고 있다. 단위 테스트를 적용해야 하는가는 더이상 논쟁거리가 되지 못한다.
논쟁거리는 좋은 단위 테스트를 작성하는 것은 어떤 의미인가로 바뀌었다.

2. 단위 테스트의 목표

단위 테스트를 작성하면 제품 코드 또한 더 나은 설계로 이어진다.
이는 단위 테스트의 주목표가 아니다. 더 나은 설계는 단지 좋은 사이드 이펙트일 뿐이다.
코드의 단위 테스트를 작성하기 어렵다면 코드 개선이 반드시 필요하다는 것을 의미한다.
보통은 코드 간의 결합도가 높을 때, 개선이 필요한 코드임을 의미하는데, 코드가 서로 충분히 분리되지 않아서 테스트하기가 어렵기 때문이다.
단위 테스트의 목표는 소프트웨어 프로젝트의 지속 가능한 성장을 가능하게 하는 것이다.
지속 가능하다는 것이 핵심이다. 이는 프로젝트가 시간이 지나도 생산성을 잃지 않는다는 것을 의미한다.
생산성이 빠르게 저하되는 현상을 소프트웨어 엔트로피라고도 한다. 코드를 작성하면 무조건 엔트로피는 증가한다. 지속적인 정리와 리팩토링없이 방치한다면 엔트로피는 점점 더 복잡해지고 무질서해진다.
테스트로 이를 막을 수 있다. 새로운 기능을 도입하거나 새로운 요구 사항에 더 잘 맞게 리팩토링한 후에도 기존 기능이 잘 작동하는지 확인하는 데 도움이 된다.
소스 코드를 지속적으로 검증하는 테스트없이는 소프트웨어는 쉽게 확장되지 않는다.
소프트웨어는 지속성확장성이 핵심이며 이는 장기적으로 생산성을 유지하기 위한 요소들이다.

1. 좋은 테스트와 좋지 않은 테스트를 가르는 요인

좋은 테스트는 프로젝트의 생산성을 유지시켜준다. 나쁜 테스트는 오히려 악화시킨다.
테스트의 가치유지 비용을 모두 고려해야 한다.
비용이란 다양한 활동에 소모되는 시간에 따라 결정된다.
테스트의 기반이 되는 코드를 리팩토링할 때, 테스트 코드도 리팩토링해야 한다.
코드가 변경되는 경우, 테스트를 실행해야 한다.
테스트가 실패하거나 의도대로 동작하지 않는 경우 수정해야 한다.
테스트 코드는 기반 코드를 이해할 수 있게 도와준다.
프로젝트의 생산성을 유지하기 위해서는 고품질 테스트에 집중해야 한다.
제품 코드 vs 테스트 코드
제품 코드와 테스트 코드가 별개로 취급되는 경향 때문에 테스트 코드는 우리의 시스템과 독립되어있다고 생각한다.
테스트 코드도 역시 코드다. 특정 문제를 해결하는 것을 목표로 작성된 코드로 시스템에선 애플리케이션의 정확성을 보장하는 것을 목표로하는 소스 코드의 일부로 보아야 한다.
다른 코드와 마찬가지로 단위 테스트도 버그에 취약하고 유지보수가 필요하다.

3. 테스트 스위트 품질 측정을 위한 커버리지 지표

현재 테스트의 품질 측정을 위해 널리 사용되는 커버리지 지표는 코드 커버리지분기 커버리지다.
일반적으로 커버지리 수치가 높을수록 더 좋다는 인식이 만연하다.
생산성을 위한 피드백으로 사용될 순 있어도 스위트 품질을 나타내는 지표로 활용하기엔 어렵다.
이는 괜찮은 부정 지표이면서 좋지 않은 긍정 지표다.
커버리지가 낮다면 테스트가 충분치 않다는 좋은 증거지만 커버리지가 높다고 해서 테스트가 좋다는 증거로 활용될 수는 없다.

1. 코드 커버리지 지표에 대한 이해

코드 커버리지는 제품 코드 라인 수 / 전체 라인 수로 표현된다.
단순히 조건문의 내용을 메소드로 추출하기만 해도 해당 내용을 테스트하지 않지만 해당 테스트 코드의 코드 커버리지는 향상된다.

2. 분기 커버리지 지표에 대한 이해

분기로 인해 발생하는 경로들을 얼마나 테스트했는가에 대한 지표이다.
분기 커버리지는 코드 커버리지보다 더 정확한 결과를 제공한다.
분기 커버리지 지표는 코드 라인 수를 사용하는 대신 if, switch 문과 같은 제어 구조에 중점을 둔다.
분기 커버리지는 테스트 스위트에서 통과하는 테스트의 제어 구조의 수전체 분기 수로 나눈 것이다.

3. 커버리지 지표에 관한 문제점

아쉽게도 어떤 커버리지 지표도 사용할 수 없는 이유는 다음과 같다.
테스트 대상 시스템의 모든 경로를 검증한다고 보장할 수 없다.
외부 의존성의 경로를 고려할 수 있는 커버리지 지표는 없다.

4. 특정 커버리지 숫자를 목표로 하기

커버리지 지표를 보는 가장 좋은 방법은 지표에 의미 부여를 하지 않으면서도 목표로 두는 것이다.
커버리지는 좋은 부정 지표이지만 좋지 않은 긍정 지표다. 커버리지 숫자를 낮게 두지만 말자.

4. 무엇이 성공적인 테스트 스위트를 만드는가?

좋은 테스트 스위트의 요소는 다음과 같다.

1. 개발 주기에 통합되어 있다.

모든 테스트는 개발 주기에 포함되어 있어야 한다. 이상적으로는 코드가 변경될 때마다 테스트가 실행되는 것이다.

2. 코드베이스에서 가장 중요한 부분만을 대상으로 한다.

시스템의 가장 중요한 부분에 노력을 기울이고 다른 부분은 간략, 간접적으로 검증하는 것이 좋다.
보통 가장 중요한 부분은 비즈니스 로직(도메인 모델)이 있는 부분이다. 비즈니스 로직의 테스트 코드가 시간 투자 대비 최고의 이득을 낼 수 있다.
다른 부분들은 세 가지 범주로 나눌 수 있다.
인프라 코드
데이터베이스나 서드파티 시스템같은 외부 서비스 및 종속성
모든 것을 하나로 묶는 코드
이 지침에서 의미하는 말은 도메인 모델을 중요하지 않은 부분(외부 종속성)과 분리하라는 것이다.

3. 최소한의 유지비로 최대의 가치를 끌어낸다.

단위 테스트에서 가장 어려운 것은 최소 유지비로 최대 가치를 달성하는 것이다.
이는 이 책에서 주장하는 핵심이다.
가치가 유지비를 상회하는 테스트만 스위트에 유지하는 것이 중요하다.
마지막 속성은 다음과 같은 두 가지로 나눠질 수 있다.
가치 있는 테스트 식별하기, 가치가 낮은 테스트 식별하기
가치 있는 테스트 작성하기

5. 이 책을 통해 배우는 것

이 책을 통해 모든 테스트를 분석하는 데 사용할 수 있는 기준을 배워갈 수 있을 것이다.
새로운 관점에서 어떤 것이 가치있고 어떤 것을 리팩토링하거나 제거해야 하는 지 알 수 있을 것이다.
다음 방법들도 배워갈 수 있다.
제품 코드와 관련 테스트 스위트를 리팩토링하는 방법
단위 테스트를 다양한 스타일로 적용하는 방법
통합 테스트로 시스템 전체 동작 검증하기
단위 테스트 안티 패턴을 식별하고 예방하기
4장에서 기초를 다진 후, 4~6장 그리고 7장 일부에서 기존 단위 테스트 기술과 실천을 살펴 본다.
이 책은 자동화된 테스트의 전체 주제를 다루기 때문에 단위 테스트 뿐만 아니라 E2E, 통합 테스트에 대해서도 알 수 있다.

요약

단위 테스트의 목표
코드를 변경, 확장할 때마다 생산성이 낮아진다.
지속적인 리팩토링과 같은 적절한 관리가 없으면 생산성은 저하된다.
테스트가 이를 막아줄 수 있다. 또한 우리에게 신뢰성을 제공한다.
좋은 단위 테스트를 작성하는 것이 중요하다. 잘못된 테스트를 가진 프로젝트는 생산성이 낮다.
단위 테스트의 목표는 생산성을 유지시키는 것이다.
모든 코드에 테스트를 작성할 필요는 없다. 존재할 가치가 있는 테스트만 남겨두어라.
커버리지 지표
커버리지 지표는 좋은 부정 지표지만 나쁜 긍정 지표다. 낮지 않게만 유지하라.
분기 커버리지로 코드 커버리지를 어느정도 보완할 수 있지만 테스트 스위트의 품질을 확인할 순 없다. 여전히 모든 경로를 확인하지 않으며 외부 의존성의 경로도 다루지 않는다.
특정 커버리지 숫자를 목표로 삼는다면 이는 부적절한 행위다. 시스템의 비즈니스 로직에 커버리지를 높게 갖는 것은 좋지만 이 높은 수치를 목표로 삼는 것은 부적절한 행위라는 것이다.
성공적인 테스트 스위트는 다음과 같은 특성을 갖는다.
개발 주기에 포함되어 있다.
코드베이스 중 가장 중요한 부분만을 대상으로 한다.
최소한의 유지비로 최대의 가치를 끌어낸다.
단위 테스트의 목표인 생산성의 유지를 달성하기 위한 유일한 방법은 다음과 같다.
좋은 테스트와 좋지 않은 테스트를 식별한다.
테스트를 리팩토링해서 가치를 끌어올린다.