최근에는 애플리케이션을 개발할 때 테스트 코드로 로직을 확인하는 과정이 점점 더 중요하게 여겨지고 있습니다. 많은 개발자들이 어떻게 하면 테스트 코드를 더 잘 작성하고 활용할 수 있는지를 고민하고 있으며, 그 결과로 애자일 방법론 중 하나인 테스트 주도 개발(TDD ; Test-Driven-Development)도 등장했습니다.
테스트 코드를 작성하는 이유
- 개발 과정에서 문제를 미리 발견할 수 있습니다.
- 리팩토링의 리스크가 줄어듭니다.
- 애플리케이션을 가동해서 직접 테스트하는 것보다 테스트를 빠르게 진행할 수 있습니다.
- 하나의 명세 문서로서의 기능을 수행합니다.
- 몇 가지 프레임워크에 맞춰 테스트 코드를 작성하면 좋은 코드를 생산할 수 있습니다.
- 코드가 작성된 목적을 명확하게 표현할 수 있으며, 불필요한 내용이 추가되는 것을 방지합니다.
테스트 코드를 작성하는 가장 큰 이유
- 테스트 코드를 작성하는 가장 큰 이유는 개발 과정에서 문제를 미리 발견할 수 있다는 것입니다.
- 테스트 코드를 먼저 작성하고, 비즈니스 로직을 먼저 작성하든, 테스트 코드를 먼저 작성하든 테스트 코드를 작성하고 테스트하는 것은 코드에 잠재된 문제를 발견하는데 큰 도움이 됩니다.
- (발생할 수 있는 여러 상황에 맞춰 테스트 코드를 작성했다는 전제를 가지고 있습니다.)
- 일부러 오류가 발생할 수 있는 테스트 코드를 작성해서 예외 처리가 잘 작동하는지를 확인하거나, 정확히 의도한 비즈니스 로직에 맞춰 테스트 코드를 작성해서 결과값이 잘 나오는지 검토하는 등 개발 단계에서는 여러 테스트 코드를 통해 애플리케이션 코드를 통해 검증하게 됩니다.
테스트 코드를 작성하는 두번째 이유
- 두번쨰 이유는 리팩토링의 리스크가 줄어든다는 점입니다.
- 애플리케이션이 개발되면 거기에서 멈추지 않고 서비스 업데이트를 위해 계속해서 코드를 축다하고 수정하는 작업을 진행합니다.
- 코드를 추가하거나 수정하는 것은 그 코드와 연관된 다른 코드에 영향을 주는 작업입니다.
- 만약 테스트 코드가 작성돼 있지 않다면 코드를 수정하는 과정에서 수시로 메뉴얼에 따라 애플리케이션의 동작을 검토해야 합니다.
- 하지만 테스트 코드가 작성돼 있다면 테스트 코드를 실행해보는 것만으로도 혹시 모를 부작용에 대비할 수 있습니다.
단위 테스트와 통합 테스트
테스트 방법은 여러 기준으로 분류할 수 있습니다.
그 중 테스트 대상 범위를 기준으로 구분하면 크게 단위테스트(Unit Test)와 통합테스트(Integrationg Test)로 분류 됩니다.
- 단위테스트 : 애플리케이션의 개발 모듈을 독립적으로 테스트 하는 방식입니다.
- 통합 테스트 : 애플리케이션을 구성하는 다양한 모듈을 결합하여 전체적인 로직이 의도한 대로 동작하는지 테스트 하는 방식입니다.
단위 테스트의 특징
- 단위 테스트는 테스트 대상의 범위를 기준으로 가장 작은 단위의 테스트 방식입니다.
- 일반적으로는 메서드 단위로 테스트를 수행하게 되며, 메서드 호출을 통해 의도한 결과값이 나오는지 확인하는 수준으로 테스트를 진행합니다.
- 단위 테스트는 테스트 비용이 적게 들기 때문에 테스트 피드백을 빠르게 받을 수 있습니다.
통합 테스트의 특징
- 통합 테스트는 모듈을 통합하는 과정에서의 호환성 등을 포함해 애플리케이션이 정상적으로 동작하는지 확인하기 위해 수행되는 테스트 방식입니다.
- 단위 테스트는 일반적으로 특정 모듈에 대한 테스트만 진행하기 때문에 데이터베이스나 네트워크 같은 외부 요인들을 제외하고 진행하는데 비해 통합 테스트는 외부 요인들을 포함하고 테스트를 진행하므로 애플리케이션이 온전히 동작하는지 테스트하게 됩니다.
- 다만 테스트를 수행할 때마다 모든 컴포넌트가 동작해야하기 때문에 테스트 비용이 커지는 단점이 있습니다.
테스트 코드를 작성하는 방법
Given-When-Then Pattern
Given
- 테스트를 수행하기 전에 테스트에 필요한 환경을 설정하는 단계입니다.
- 테스트에 필요한 변수를 정의하거나 Mock객체를 통해 특정 상황에 대한 행동을 정의합니다.
When
- 테스트의 목적을 보여주는 단계입니다. 실제 테스트 코드가 포함되며, 테스트를 통한 결과값을 가져오게 됩니다.
Then
- 테스트의 결과값을 검증하는 단계입니다.
- 일반적으로 When 단계에서 나온 결과값을 검증하는 작업을 수행합니다.
- 결과값이 아니더라도 이 테스트를 통해 나온 결과에서 검증해야 하는 부분이 있다면 이 단계에 포함이 됩니다.
Given-When-Then Pattern 은 테스트 주도 개발에서 파생된 BDD(Behacior-Driven-Development ; 행위 주도 개발) 을 통해 탄생한 테스트 접근 방식입니다.
- 일반적으로 단위 테스트 보다는 비교적 많은 환경을 포함하는 테스트에서 사용하는 것이 적합하다고 알려져 있지만 개인적으로는 단위 테스트에서도 유용하게 사용할 수 있다고 생각합니다.
좋은 테스트를 작성하는 5가지 속성 (F.I.R.S.T)
Fast(빠르게)
- 테스트는 빠르게 수행되어야 합니다.
- 테스트가 느려지면 코드를 개선하는 작업이 느려져 코드 품질이 떨어질 수 있습니다.
- 테스트 속도에 절대적인 기준은 없지만 목적을 단순하게 설정해서 작성하거나 외부 환경을 사용하지 않는 단위 테스트를 작성하는 것 등을 빠른 테스트라고 할 수 있습니다.
Isolated(고립,독립)
- 하나의 테스트 코드는 목적으로 여기는 하나의 대상에 대해서만 수행되어야 합니다.
- 만약 하나의 테스트가 다른 테슽트코드와 상호작용하거나 관리할 수 없는 외부 소스를 사용하게 되면 외부 요인으로 인해 테스트가 수행되지 않을 수 있습니다.
Repeatable(반복 가능한)
- 테스트는 어떤 환경에서도 반복 가능하도록 작성해야 하빈다.
- 테스트는 개발 환경의 변화나 네트워크의 연결 여부와 상관없이 수행되어야 합니다.
Self-Validating(자가 검증)
- 테스트는 그 자체만으로도 테스트의 검증이 완료되어야 합니다.
- 테스트가 성공했는지 실패 하였는지 확인할 수 있는 코드를 함께 작성해야 합니다.
- 만약 결과값과 기대값을 비교하는 작업을 코드가 아니라 개발자가 직접 확인하고 있다면 좋지 못한 테스트 코드입니다.
Timely(적시)
- 테스트 코드는 테스트하려는 애플리케이션 코드를 구현하기 전에 완성 되어야 합니다.
- 너무 늦게 작성된 테ㅡ크 코드는 정상적인 역할을 수행하기 어려울 수 있습니다.