서론
개인 프로젝트를 진행하면서 테스트 코드를 명확한 이해 없이 대략적인 느낌대로 작성하고 있다고 느꼈다.
이 글을 통해 테스트 코드에 대한 개념을 명확히 하여 체계적이고 효과적인 테스트 코드를 작성하고자 한다.
테스트 코드의 정의
테스트 코드는 소프트웨어의 특정 기능이나 모듈이 예상대로 작동하는지 검증하기 위해 작성하는 코드다.
이러한 테스트 코드의 단위는 어떻게 나누고 구성하냐에 따라 다양하게 존재한다. 여기서는 주요 테스트 단위를 3가지를 설명한다.
테스트 코드의 종류
출처 - https://academy.pega.com/topic/test-pyramid/v1
위 이미지는 테스트 피라미드의 사진이다. 아래에 있는 테스트일수록 범위가 작고 실행 속도가 빠르며 비용이 적다. 반대로 위로 갈수록 범위가 넓고 실행 속도가 느려지며 비용이 증가하게 된다. 피라미드에 위치한 각각의 테스트를 보다 이해하기 쉽게 인스타그램을 예로 알아보았다.
1. 유닛 테스트 (Unit Test)
유닛 테스트는 테스트의 가장 작은 단위로 개별 함수나 메서드와 같은 소프트웨어를 구성하는 가장 작은 단위를 검증한다. 가장 작은 단위를 테스트하기에 외부 의존성이 최소화되고 독립적으로 실행 가능해진다.
단위가 작아 테스트 실행 시간이 짧고 자주 실행 가능하여 코드 오류를 빠르게 찾아낼 수 있고 코드 변경에 대해 빠른 피드백을 제공하지만 전체적인 동작, 외부 시스템과의 통합 문제를 발견하지 못한다.
ex) 인스타그램에서 게시글을 작성할 때 단순히 게시물을 생성하는 함수가 의도대로 작동하는지 확인한다. 이때 데이터베이스, 네트워크와 같은 외부 의존성은 mocking(가짜 객체 사용)하여 독립적으로 테스트를 수행한다.
2. 통합 테스트(Integration Test)
통합 테스트는 여러 모듈이나 컴포넌트가 함께 작동할 때의 상호작용을 검증한다. 개별 함수나 메서드뿐만 아니라 데이터베이스와 외부 API, 네트워크 등의 요소들의 상호작용을 테스트하기에 유닛 테스트보다 복잡하다.
여러 모듈이나 컴포넌트를 함께 작동시켜 통합 문제를 조기에 발견할 수 있지만 모든 상호작용을 완벽하게 커버하기는 어렵다.
ex) 인스타그램 게시글을 작성하면 게시글 작성 함수가 실행되고 실제 데이터베이스에서 저장되어야 한다. 이러한 과정을 테스트 하는것을 통합 테스트라고 한다.
3. E2E 테스트(End-to-end Test)
E2E테스트는 어플리케이션 전체의 흐름을 처음부터 끝까지 올바르게 작동하는지를 검증한다. 실제 사용자의 시나리오를 기반으로 전체 시스템의 동작을 검증하여 시스템이 의도대로 작동하는지 확인한다.
실제 사용자의 시나리오를 기반으로 검증하기에 프론트, 백엔드, 데이터베이스 등 모든 구성요소를 테스트하여 전체 시스템의 안정성을 보장하지만 실행 시간, 설정과 같은 비용이 높고 테스트 범위가 넓어 디버깅 및 특정 문제 원인을 찾기가 어렵다.
ex) 인스타그램에서 로그인, 게시글 작성, 게시글 확인과 같은 순차적인 절차를 테스트한다.
이 외에도 피라미드에 포함되지 않는 성능, 부하, 보안 등 여러 테스트가 존재한다. 그렇다면 테스트 코드는 어떤 장점을 갖기에 사용하는 것일까? 그리고 단점은 무엇이 있을까?
테스트 코드의 장점
테스트 코드는 아래의 5가지 장점을 가진다.
1. 버그 조기 발견 - 테스트 코드를 통해 개발 초기에 버그를 발견할 수 있고 발견된 버그를 조기 해결하여 비용과 시간을 절약하게 해준다.
2. 리팩토링 안정성 - 코드 리팩토링 시 테스트 코드를 사용하여 기능이 제대로 동작하는지 확인할 수 있다.
3. 검증 자동화 - 테스트를 자동화함으로써 반복 검증을 줄여 개발 효율성을 높일 수 있다. 이 개념은 CI/CD와 연결된다.
4. 문서화 - 테스트 코드는 그 자체로 코드의 동작 방식을 설명하는 역할을 할 수 있다. 따라서 새로운 이해관계자에게 코드 사용법을 이해시키는데 도움을 준다.
5. 신뢰성 향상 - 테스트 코드를 통해 배포 후 발생할 수 있는 오류를 줄여 코드의 신뢰성을 높일 수 있다.
테스트 코드의 단점
테스트 코드는 5가지 단점을 가진다.
1. 초기 작성 비용 - 테스트 코드 또한 개발자가 작성해야하므로 초기 개발 비용이 증가할 수 있다.
2. 유지 보수 부담 - 코드 변경 시 테스트 코드 또한 유지 보수가 필요하기에 테스트 코드가 많을수록 작업량이 증가할 수 있다.
3. 잘못된 안정망 - 테스트 코드를 잘못 작성할 경우 오히려 안정성을 해쳐 실제 코드의 문제를 놓칠 수 있다.
4. 복잡성 증가 - 규모가 큰 시스템의 경우 모든 시나리오를 테스트 코드로 커버하는 비용이 증가하게 된다. 이는 복잡성을 증가시키고 관리를 어렵게 한다.
5. 과잉 테스트 - 필요 이상의 테스트 코드 작성 시 개발 속도가 느려져 오히려 개발 효율성을 떨어뜨릴 수 있다.
결론
테스트 코드는 코드의 정확성과 안정성을 보장하여 보다 완전한 소프트웨어를 개발할 수 있도록 돕는다. 테스트 코드를 작성함으로써 얻을 수 있는 많은 장점이 존재하지만 테스트 코드의 목적과 범위를 명확하게 하지 않고 적절하지 않은 수준의 코드를 작성한다면 오히려 안 좋은 영향을 줄 수 있다. 따라서 테스트 코드를 작성하기 전 목적과 범위를 명확히 하여 효율적인 소프트웨어 개발을 하는 것이 중요하게 여겨진다.