단위 테스트는 소프트웨어의 개별적인 부분, 즉 "단위"를 격리된 환경에서 테스트하는 것입니다.
주로 클래스, 메서드, 함수와 같은 작은 코드 조각을 대상으로 합니다.
목적은 개별 단위가 예상대로 동작하는지 검증하고 코드의 신뢰성을 확보하는 것입니다.
통합 테스트는 여러 개의 단위나 컴포넌트를 함께 테스트하여 이들이 올바르게 상호 작용하는지를 확인하는 것입니다.
각 단위 테스트가 개별적으로 잘 작동한다고 해도, 통합할 때 발생할 수 있는 문제를 찾아내기 위해 필요합니다.
데이터베이스 연동, 외부 API 호출 등과 같은 상호 작용을 테스트하는 데 사용됩니다.
인수 테스트는 사용자 또는 고객이 소프트웨어를 수용할 수 있는지를 검증하는 것입니다.
주로 비즈니스 요구사항을 충족하는지를 테스트합니다.
소프트웨어의 최종 산출물에 대한 사용자의 수락 여부를 결정하기 위해 수행됩니다.
사용자 승인 테스트(User Acceptance Testing, UAT)라고도 불립니다.
시스템의 성능을 평가하고 최적화하는 데 사용됩니다. 대량의 트래픽이나 작업을 처리할 때 시스템이 어떻게 동작하는지를 확인합니다.
부하 테스트, 응답 시간 테스트, 스트레스 테스트 등이 포함될 수 있습니다.
시스템의 보안 취약점을 찾고 해결하기 위해 수행됩니다. 인가되지 않은 접근, 데이터 누출, 인증 및 권한 문제 등을 확인합니다.
취약점 스캐닝, 페네트레이션 테스트, 보안 코드 리뷰 등이 포함될 수 있습니다.
시스템이 실패 상황에서 어떻게 회복되는지를 확인하는 것입니다. 예기치 않은 상황에서 시스템이 어떻게 동작하는지를 평가합니다.
테스트 코드를 통해 프로그램의 기능을 자동으로 확인할 수 있습니다. 이를 통해 개발자는 코드 변경 후 예기치 않은 버그나 오류를 미리 발견하고 수정할 수 있습니다. 이는 소프트웨어의 신뢰성을 향상시키고 사용자 경험을 개선합니다.
소프트웨어는 지속적으로 변경됩니다. 테스트 코드가 있으면 새로운 기능을 추가하거나 기존 코드를 수정할 때 변경으로 인한 예기치 않은 부작용을 방지할 수 있습니다. 이는 코드를 유지보수하고 개선하는 과정을 안정화시킵니다.
테스트 코드는 프로그램의 동작을 문서화하는 역할도 합니다. 각 테스트 케이스는 코드의 기능과 사용법을 명확하게 설명해줍니다. 또한 테스트 주도 개발(TDD)을 통해 코드를 작성할 때 테스트 케이스가 코드 설계를 지원할 수 있습니다.
테스트 코드가 있는 경우 코드 변경에 대한 불안감이 줄어들어 코드 변경을 더 자주 시도할 수 있습니다. 이는 빠른 개발과 배포를 가능하게 합니다.
테스트 코드를 자동화된 테스트 스위트에 포함시켜서 반복적인 테스트를 자동으로 실행할 수 있습니다. 이는 개발 프로세스를 자동화하고 개발자의 시간을 절약합니다.
TDD는 테스트 주도 개발을 의미하며, 소프트웨어를 개발할 때 테스트를 먼저 작성하고 이를 통과시키는 코드를 작성하는 방법론입니다.
TDD는 "Red-Green-Refactor" 사이클을 따릅니다. 먼저 실패하는 테스트 케이스를 작성하고, 이를 통과시키는 최소한의 코드를 작성한 후에 리팩토링을 수행합니다.
이 방법론은 소프트웨어의 설계 개선, 품질 향상, 버그 감소 등의 장점을 제공합니다.
DDD는 도메인 중심 설계를 의미하며, 복잡한 도메인과 비즈니스 로직을 모델링하고 이를 소프트웨어에 반영하는 방법론입니다.
DDD는 도메인 모델을 중심으로 개발을 진행하고, 도메인의 복잡성을 해결하기 위해 전문가와의 협업을 강조합니다.
소프트웨어를 도메인에 맞게 설계하고 도메인 모델을 잘 이해하고 구현함으로써 소프트웨어의 품질을 향상시킬 수 있습니다.
BDD는 행위 주도 개발을 의미하며, 비즈니스 요구사항을 이해하고 그에 따른 행위를 개발하는 방법론입니다.
BDD는 테스트 케이스를 행위 또는 동작으로 표현하고, 이를 통해 개발자, 테스터, 비즈니스 분석가 간의 의사소통을 원활하게 합니다.
Given-When-Then 구조를 사용하여 테스트 케이스를 명확하게 정의하고 비즈니스 요구사항을 검증합니다.
ATDD는 인수 테스트 주도 개발을 의미하며, 사용자의 수용 가능한 소프트웨어를 개발하기 위해 인수 테스트를 중심으로 개발하는 방법론입니다.
사용자 승인 테스트를 먼저 작성하고 이를 통과하는 코드를 작성하는 것을 강조합니다. 이를 통해 사용자 요구사항을 충족시키고 사용자와 개발팀 간의 의사소통을 강화합니다.
테스트는 특별한 환경 설정 없이 프로젝트를 바로 다운로드하여 실행한다면 어떤 환경이든 누구든 동일한 결과값으로 실행할 수 있어야 합니다. 보통 테스트 환경에서는 휘발성 데이터베이스인 H2나 인메모리 데이터베이스를 사용하는 것이 좋습니다.
테스트에 필요한 의존성을 적절히 관리해야 합니다. 예를 들어, 외부 서비스와의 통합 테스트를 위해 테스트 컨테이너를 사용할 수 있습니다. Testcontainers 라이브러리를 사용하여 Docker 컨테이너 내에서 외부 서비스를 실행할 수 있습니다.
외부 의존성을 대체하기 위해 모의 객체를 사용하여 테스트의 격리성을 확보하는 것이 중요합니다. Mockito나 MockMvc와 같은 라이브러리를 사용하여 모의 객체를 생성하고 행위를 검증할 수 있습니다.
테스트 코드는 다른 개발자들이 쉽게 이해하고 유지보수할 수 있도록 작성되어야 합니다. 명확하고 간결한 테스트 케이스 작성, 주석 추가, 테스트 메서드의 명확한 네이밍 등이 중요합니다.
코드의 테스트 커버리지를 높이는 것이 중요합니다. 모든 핵심 기능과 경로를 테스트해야 하며, 가능한 많은 상황을 고려하여 테스트 코드를 작성해야 합니다. 하지만 테스트 커버리지 함정에 빠져 커버리지만 늘리는 러프한 테스트 코드를 작성하지 않도록 주의해야 합니다.
테스트의 실행 속도를 최적화하여 빠른 피드백을 제공하는 것이 중요합니다. 테스트가 느리면 개발자들이 테스트를 자주 실행하지 않게 되어 품질이 저하될 수 있습니다.
https://github.com/juno-choi/test_code/commit/978595c2a2a139c3d23147cbebcc972ac1639c08
https://github.com/juno-choi/test_code/commit/c719999cee7cc64e06961d3e68f0bcab657e36b3
https://github.com/juno-choi/test_code/commit/5971d5ab900952116ea3b60c3276d4789c548e6f