모든 소프트웨어는 ‘입력-처리-출력’의 함수로 볼 수 있으며, 이 본질은 테스트의 핵심 원리를 이룹니다. 강연자는 CSV 파일에서 통계 데이터를 추출하는 간단한 예시를 통해, 테스트 없는 코드 배포가 리팩토링 및 확장 시 심각한 문제를 야기하고 결국 운영 환경에서 실패할 수 있음을 강조합니다. 그는 ‘테스트 나중 개발’의 함정을 지적하며, AI가 생성한 테스트 코드조차도 확장성이나 유지보수성 측면에서 한계를 가질 수 있음을 보여줍니다.
기존의 ‘Better Specs’ 방식은 described_class
, subject
, let
등을 활용하여 DRY(Don’t Repeat Yourself) 원칙을 강조하지만, 강연자는 이러한 접근 방식이 테스트 코드의 가독성과 자체 포함성을 저해하여 디버깅 및 이해를 어렵게 한다고 비판합니다. 대신, ‘Even Better Specs’의 원칙을 지지하며 다음과 같은 효과적인 테스트 작성 가이드라인을 제시합니다:
효과적인 테스트 작성 가이드라인
- 테스트는 자체 포함적이어야 합니다 (Not DRY):
- 테스트 코드는 복사하여 붙여넣기만 해도 실행 가능해야 합니다.
- 이는 코드베이스에 익숙하지 않은 개발자나 미래의 자신에게 훌륭한 문서 역할을 합니다.
- Arrange-Act-Assert 패턴을 따라야 합니다:
- 테스트의 설정(Given), 실행(When), 검증(Then) 단계가 명확하게 구분되어야 합니다.
let
사용을 피해야 합니다:let
은 지연 평가(lazy evaluation) 특성으로 인해 복잡한 중첩 컨텍스트에서 추적하기 어려워 자체 포함성을 저해합니다.
- 공유 예제(Shared Examples)를 지양해야 합니다:
- 테스트 템플릿 사용보다는 일반 Ruby 메서드를 활용하는 것이 코드 추적 및 이해에 더 효과적입니다.
- 필요한 데이터만 사용해야 합니다:
- 테스트에 불필요한 데이터를 생성하지 않음으로써, 테스트의 목적을 명확히 하고 ‘null과 null 비교’와 같은 오류를 방지합니다.
- 외부 시스템은 반드시 모킹해야 합니다:
- S3와 같은 외부 서비스 호출을 모킹하여 테스트 속도를 높이고 외부 의존성 없이 안정적인 테스트 환경을 구축합니다.
described_class
대신 명확한 클래스 이름을 사용해야 합니다:- 예외 발생 시 특정 클래스 이름을 검색하여 관련 테스트를 쉽게 찾을 수 있도록 돕습니다.
또한, 강연자는 테스트 실패 메시지가 “true is not false”와 같이 모호하지 않고 구체적인 정보를 제공하도록 작성해야 한다고 조언합니다. 중요하지 않은 테스트 데이터(예: UID, API 키)는 실제 값 대신 00000000-0000-0000-0000-000000000001
과 같은 의미 없는 플레이스홀더를 사용하여 테스트의 목적을 명확히 하고, Swagger 문서 생성 시 충돌을 방지하는 사례를 공유합니다. 궁극적으로, 그는 ‘DAMP(Descriptive And Meaningful Phrases)’ 원칙을 강조하며, 테스트 코드에서는 반복을 감수하더라도 명확하고 이해하기 쉬운 것이 DRY보다 중요하다고 주장합니다.