발표자는 코딩 챌린지 제출 전, Rubocop의 제안에 따라 initialize 메서드에 super 호출을 추가했습니다. 이 작은 변경 후 로컬에서 RSpec을 실행했을 때는 모든 테스트가 통과하는 것처럼 보였습니다. 그러나 면접관으로부터 코드에 여러 오류가 있다는 피드백을 받았고, 특히 복리 이자 계산 부분에서 문제가 발생했다고 전달받았습니다.
문제의 원인 분석
문제의 원인을 파악하기 위해 발표자는 다음과 같은 과정을 거쳤습니다.
-
RSpec의 불일치한 동작: 특정 파일만 지정하여 RSpec을 실행했을 때는 오류가 명확히 나타났지만, 전체 RSpec을 실행했을 때는 오류가 보고되지 않았습니다. 이는 RSpec이 모든 테스트를 실행하지 않았다는 것을 의미했습니다.
-
SystemExit문제: 구글링을 통해 RSpec 코어 저장소에서 “UnhandledSystemExitcauses later specs to silently not run”이라는 10년 이상 된 이슈를 발견했습니다. RSpec은SystemExit가 코드 내부에서 발생했는지, 사용자가 Ctrl+C로 종료했는지 구분할 수 없어, 내부에서 발생한SystemExit도 테스트 실행을 조용히 중단시키는 것으로 밝혀졌습니다. -
코드의 문제점: 발표자의 CLI 애플리케이션
main함수에는ArgumentError를 광범위하게rescue하고exit(1)을 호출하는 로직이 있었습니다.initialize에 추가된super호출이 인자를 받지 못해ArgumentError를 발생시켰고, 이 에러가rescue블록에 잡혀exit(1)을 실행함으로써 RSpec 테스트 스위트 전체를 중간에 종료시켰던 것입니다.
해결책 및 권장 사항
이러한 문제를 방지하고 테스트의 신뢰성을 높이기 위해 발표자는 다음과 같은 방안을 제안했습니다.
-
RSpec 테스트 순서 무작위화: RSpec 설정에서
config.order = :random을 설정하여 테스트 파일 로드 순서를 무작위로 지정함으로써, 특정 순서에 의존하는 숨겨진 오류를 발견할 수 있습니다. -
터미널 프롬프트에 종료 코드 표시: 셸 프롬프트에
$?또는$LASTEXITCODE와 같은 종료 코드를 항상 표시하도록 설정하여, RSpec 실행 후 비정상적인 종료 코드를 즉시 인지할 수 있도록 합니다. -
CI/CD 파이프라인 활용: GitHub Actions와 같은 CI/CD 도구를 사용하여 코드를 푸시할 때마다 자동으로 테스트를 실행하고, 실패 시 명확한 피드백을 받아 문제를 조기에 발견할 수 있도록 합니다.
발표자는 Rubocop의 제안이 의도치 않게 RSpec의 취약점을 드러냈다고 언급하며, AI를 활용하여 RSpec 코어의 오래된 이슈를 해결할 수 있을 것이라는 의견을 덧붙였습니다.