////
Search
4️⃣

4장. 맛있는 테스트

이 장에서 다룰 내용

왜 우리가 테스트를 싫어하는지와 왜 그것을 사랑하는지
테스트를 더 즐기는 방법
TDD, BDD와 같이 세 글자로 된 용어를 피하기
테스트 대상을 결정하기
테스트로 일을 줄이기
테스트가 내게 기쁨을 가져다주게 하기
개발자들이 테스트를 싫어하는 이유는 테스트가 제품과 분리된 것으로 보기 때문이다.
그러나 테스트는 개발자의 작업에 필수적이며 개발자에게 도움이 된다. 지금부터 자세히 알아보자.

1. 테스트의 유형

소프트웨어 테스트는 소프트웨어의 동작에 대한 자신감을 높이는 작업이다.
테스트의 유형을 분류하는 기준에는 여럿이 있지만 가장 널리 사용되는 기준은 테스트를 실행하거나 구현하는 방식이다.
이는 테스트가 개발 시간에 많은 영향을 끼치기 때문이다.

1. 수동 테스트

개발자가 직접 코드를 실행하고 그 동작을 검사하여 테스트하는 방법이다.
코드 리뷰 역시, 효과가 약하긴 하나 테스트 방법 중의 하나로 간주된다.

2. 자동 테스트

테스트 역시, 우리를 위해 컴퓨터에게 실행해달라고 할 수 있다.
자동 테스트는 소프트웨어의 동작에 대한 신뢰도를 어느 정도까지 높이느냐에 따라 다르다.
단위, 통합 테스트 등이 속하며 단위에 대한 정의는 저마다 다르다.

3. 위험을 감수하라: 프로덕션 환경에서의 테스트

프로그래밍 세계에서 프로덕션 환경에서 테스트하는 것은 나쁜 행위에 속한다.
오류에 화가난 고객이나 사용자가 떠나갈 수 있기 때문이다.
그러나 이 역시 항상 나쁘기만 한 것은 아니다. 테스트해야 할 시나리오가 자주 사용되는 중요한 코드 경로와 연관이 적다면 프로덕션에서 테스트해도 무리가 없을 수 있다.
오류가 발생해도 사용자가 이 앱을 지속적으로 사용할 것이라고 생각한다면 이런 시나리오에서는 테스트를 수행해도 괜찮을 수 있다.

4. 적합한 테스트 방법 선택하기

테스트 방법을 결정하려면 각 방법이 가지는 비용과 위험을 잘 이해하고 있어야 한다.
비용
특정 테스트를 구현/실행하는 데 얼마나 많은 시간이 필요한가?
몇 번 정도 반복해야 할까?
테스트 코드를 변경하면 테스트할 줄 아는 사람이 있는가?
이 테스트를 신뢰할 수 있게 유지하는 것이 얼마나 어려운가?
위험
이 시나리오가 깨질 가능성은 얼마나 될까?
시나리오가 깨지면 사업에 얼마나 큰 영향을 줄까? 손해가 클까? 혹시 이걸 망치면 해고될까?
시나리오가 깨지면 얼마나 많은 시나리오가 함께 깨지게 될까? 예를 들어 우편물 발송과 관련된 기능이 중지되면 이 기능에 의존하는 다른 여러 기능도 역시 깨질 것이다.
이 코드는 얼마나 자주 변경될까? 앞으로는 얼마나 바뀔 것으로 예상하는가? 모든 변화는 새로운 위험을 가져온다.
두 요소를 고려하여 보다 우리 서비스에 적합한 테스트 방법을 선택해야 한다.

2. 걱정을 멈추고 테스트를 사랑하는 법

테스트 작성이 너무 어려울 것이라고 지레 겁먹지 말자. 테스트 프레임워크는 정말 잘 되어 있다.
테스트 프레임워크를 사용해 테스트를 작성하다보면 간편하고 빠른 피드백 덕분에 테스트를 작성하는 일이 신나게 될 것이다.

3. TDD와 같이 약어로 된 용어를 사용하지 마라

너무 특정 방법론에 매몰되어 본질을 놓칠 수 있다.
테스트는 매우 중요하나 우리는 제품을 개발하고 있으며 제품 코드가 먼저다.
테스트 때문에 고민해서는 안 된다. 테스트는 작성이 쉽고, 빠르게 끝나야 한다.

4. 자신의 이득을 위해 테스트를 작성하라

만들어둔 테스트는 나중에 보험처럼 동작한다.
테스트는 개발자가 깰 수 없는 코드와 명세 사이의 계약을 강요하며 이는 소프트웨어와 개발자 모두를 더 나아지게 한다.
효율적인 개발자가 되고 싶다면 테스트를 작성하자.

5. 테스트 대상 결정하기

테스트할 대상을 어떻게 찾아낼 수 있을까?
제품 코드를 무작위로 몇 줄 지우더라도 실패하게 되는 테스트를 어떻게 하면 작성할 수 있을까?

1. 경계를 존중하라

경계 조건에서부터 시작하라.

2. 코드 커버리지

너무 코드 커버리지를 맹신해서는 좋지 않다.
대신에 가능한 모든 입력을 고려하고 경계 값을 현명하게 처리하면서 테스트 적용 범위를 항상 의식하고 있어야 한다.

6. 테스트를 작성하지 마라

어떤 기능들은 테스트가 필요 없을까?

1. 테스트를 작성하지 마라

우리가 작성하지 않은 기능은 테스트를 작성할 필요가 없다.
가져다 쓴 패키지나 라이브러리의 기능이 정상적인 입력에도 오류를 내뱉는다면 Repository로 가서 Issue에 글을 남기면 된다.

2. 모든 테스트를 작성하려 애쓰지 마라

모두가 잘 알고 있는 파레토 법칙은 80%의 결과는 20%의 원인으로부터 기인한다고 말한다.
버그는 균일하게 발생하지 않는다. 보통 더 자주 사용되거나 변경되는 코드에서 버그가 발생할 가능성이 높다.
이처럼 버그 발생 가능성이 높은 영역을 핫 패스라고 부른다.
웹 사이트의 홈페이지를 여는, 가장 기초적인 동작만으로도 연결된 기능들까지 테스트하므로 꽤나 괜찮은 범위를 커버한다.
이를 거리에서는 스모크 테스트라고 부른단다. 컴퓨터의 최초 프로토타입을 개발했을 때, 연기가 나는지 안나는지 보기 위해 컴퓨터를 켰던 것에서 기인했단다.
마찬가지로 중요한 공유 의존성에 적절한 테스트 적용 범위를 갖게하는 것이 코드 커버리지 100%보다 더 중요하다.

7. 컴파일러가 코드를 테스트하도록 하라

1. 널 검사를 제거하라.

목적을 위해 특정 타입을 사용하면 테스트의 필요성이 줄어들 수 있다.
함수가 문자열 대신 객체를 입력으로 할 때 함수에서는 해당 인수의 유효성을 검증하지 않아도 된다.
컴파일러가 대신해줄 것이다.

2. 범위 점검을 제거하라

양수만 받는다면 굳이 타입이 int여야할 필요가 있을까?
타입을 슬기롭게 사용하도록 하자.

3. 유효 값을 확인하는 로직에서 중복을 제거하라

너무 많은 책임을 가지는 함수를 분리한다면 테스트도 쉬워지고 작성해야할 테스트가 줄어들 수 있다.
효과적인 리팩토링을 통해 함수의 책임을 덜고 우리의 일도 덜어보자.

8. 테스트 이름 정하기

테스트는 다음 항목을 구분할 수 있어야 좋은 이름이다.
테스트할 함수의 이름
입력 및 초기 상태
예상 동작
저자는 보통 다음 형식으로 테스트 이름을 짓는다.

9. 요약

애초에 테스트 작성을 많이 하지 않음으로써 테스트 작성에 대한 경멸을 극복할 수 있다.
테스트 주도 개발이나 그와 유사한 패러다임은 테스트 작성이 더욱 싫어지게 만들 수 있다. 내게 행복감을 주는 테스트를 작성하려고 노력하라.
특히 매개변수화된 데이터 기반 테스트와 함께 테스트 프레임워크를 이용하면 테스트 작성을 위한 수고를 크게 줄일 수 있다.
함수 입력의 경계 값을 잘 분석하면 테스트 수를 크게 줄일 수 있다.
데이터 타입을 적절하게 사용하면 불필요한 테스트를 많이 작성하지 않아도 된다.
테스트는 코드의 품질만을 보장하는 것이 아니라 여러분의 개발 기술과 처리량을 향상시키는 데도 도움을 줄 수 있다.