Hashrocket의 통합 테스트 접근 방식
Hashrocket은 개발 수명 주기에서 통합 테스트를 매우 중요하게 여깁니다. 컨트롤러 및 뷰 테스트를 전혀 수행하지 않고, 모델 계층의 테스트와 헬퍼 테스트를 기반으로 통합 테스트 계층을 매우 두텁게 구축합니다. 이는 클라이언트와의 계약을 코드로 구현하는 것과 같으며, 기능에 대한 명확한 책임감을 부여하고 미래 유지보수성을 보장합니다.
핵심 도구 및 프레임워크
1. Capybara
-
브라우저 드라이빙 프레임워크: Jonas Nicholas가 개발한 강력하고 유연한 Gem으로, 브라우저를 구동하여 웹 애플리케이션을 테스트합니다.
-
DSL (Domain Specific Language):
visit,click_link,fill_in,page.should have_content등 직관적인 메서드를 제공하여 테스트 코드 작성을 용이하게 합니다. -
교체 가능한 드라이버: Rack Test (헤드리스, JavaScript 없음, 빠름)와 Selenium (헤드, JavaScript 지원) 드라이버를 기본으로 제공하며, 필요에 따라 쉽게 전환할 수 있습니다. MJS와 같은 외부 드라이버도 지원하여 생태계를 확장했습니다.
-
XPath/CSS Selector: 복잡한 요소 선택 시 XPath 사용을 권장하며, Capybara는 내부적으로 XPath를 활용합니다.
2. Fabrication
-
테스트 데이터 생성: Factory Girl, Machinist와 유사한 프레임워크로, 테스트에 필요한 데이터를 효율적으로 생성하고 관리합니다.
-
문법적 이점: 블록 변수 없이 깔끔한 문법을 제공하며, Active Record 연관 관계는 접근 시에만 생성되는 ‘게으른(lazy)’ 특성을 가집니다.
-
Fabricator 설계:
user_fabricator.rb와 같이 객체별로 파일을 분리하고, 역할(role)이나 특수 케이스(예: 이메일 인증)에 따라 Fabricator를 확장하여 재사용성을 높입니다. -
랜덤 데이터: 테스트 데이터에 랜덤 값을 포함하여 데이터의 고유성을 보장하고, 해당 필드의 실제 값이 중요하지 않음을 나타냅니다. 단, 외부 서비스 연동 시에는 주의해야 합니다.
3. RSpec Integration Gem
-
Capybara 연동: RSpec Rails 2의
request예제 그룹에 Capybara를 통합하여, RSpec 내에서 Capybara의 강력한 기능을 활용할 수 있도록 합니다. -
테스트 서술(Narrative):
describe,context,it블록을 활용하여 사용자 스토리와 일치하는 서술적인 테스트 코드를 작성하며, 이는 로그 출력 시 가독성을 높여 클라이언트에게도 유용하게 활용될 수 있습니다.
복잡한 시나리오 처리
-
JavaScript 상호작용: Selenium 드라이버를 사용하여 JavaScript 기반의 동적 UI (예: 팝업, 호버 효과)를 테스트합니다.
execute_script를 통해 직접 JavaScript 코드를 실행할 수 있습니다. -
외부 서비스 연동: Ephemeral Response Gem을 사용하여 결제 게이트웨이, Google Maps 등 외부 API 호출을 캐싱하고 응답을 기록하여 테스트 속도를 크게 향상시킵니다.
-
날짜/시간 의존성: Timecop Gem을 사용하여 특정 날짜로 시스템 시간을 고정함으로써, 날짜에 민감한 테스트를 안정적으로 수행합니다.
-
동적 로딩 요소: Capybara의
page.should have_xpath또는locate메서드는 요소가 나타날 때까지 기다리는 기능을 제공하여 Ajax 등으로 동적으로 로드되는 요소를 안정적으로 테스트합니다. -
오탐(False Positives) 방지: ‘긍정적인 부정 테스트(positively negative test)’ 기법을 사용하여, 특정 요소가 존재하지 않아야 할 영역에서 실제로 존재하지 않는지 명확히 검증합니다.
-
데드 코드 발견: 포괄적인 통합 테스트 스위트를 Archive와 함께 실행하여, 실제로 사용되지 않거나 테스트되지 않는 코드를 식별하고 제거하는 데 도움을 줍니다.