Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Minitest로 시작하는 Rails 시스템 테스트 완벽 가이드

오늘 포스팅에서는 Rails 6의 시스템 테스트(System Test)를 살펴보겠습니다. 시스템 테스트는 사용자가 애플리케이션과 상호작용하는 방식을 자동으로 검증하는 테스트로, UI에 포함된 JavaScript 동작까지 함께 확인할 수 있습니다. Rails의 기본 테스트 프레임워크인 Minitest는 시스템 테스트와 아주 잘 어울리며, Rails가 대부분의 설정을 대신 처리해 주기 때문에 몇 단계만 거치면 첫 번째 테스트를 바로 실행할 수 있습니다.

시스템 테스트는 Rails 5.1에 도입되었습니다. 하지만 막상 사용하려고 하면 RSpec 중심의 정보만 넘쳐나서, Minitest 기반의 최신 정보를 찾기가 쉽지 않았습니다. 이 글에서는 Minitest로 시스템 테스트를 작성할 때 알아야 할 핵심 내용을 모두 정리했습니다.

시스템 테스트란 무엇인가?

Rails 용어로 시스템 테스트는 "애플리케이션을 하나의 시스템으로 전체 테스트하는 것"을 의미합니다. 이는 실제 브라우저를 사용해 수행됩니다. 개별 구성 요소만 따로 검증하는 것이 아니라, 사용자가 앱을 사용하며 겪는 전체 워크플로우를 JavaScript 동작까지 포함해 그대로 테스트할 수 있는 것입니다.

실무 관점에서 보면, 시스템 테스트는 사용자가 버튼을 클릭했을 때 데이터베이스에 레코드가 생성되었는지 자체를 검사하는 것이 아니라, 그 결과가 화면에 제대로 나타나는지를 확인합니다. 이런 사용자 상호작용 테스트는 기능 테스트(feature test) 또는 인수 테스트(acceptance test)라고도 불립니다. 통합 테스트와 혼동하기 쉬운데, 통합 테스트는 앱의 여러 부분이 함께 작동할 때의 동작을 UI를 거치지 않고 검증한다는 점에서 다릅니다.

설정 방법

설정이 너무 간단해서 오히려 의심스러울 정도입니다.

브라우저 조작에는 Capybara 젬이 사용됩니다. 페이지 방문, 폼 입력, 링크 및 버튼 클릭 등은 모두 Capybara를 통해 수행됩니다. Capybara를 직접 설정해 본 경험이 있다면, 데이터베이스 클리닝 전략 연계와 브라우저 구성까지 일일이 맞춰야 했던 번거로움을 기억할 것입니다. Rails의 시스템 테스트 환경은 이런 복잡한 설정을 기본으로 모두 제공하기 때문에, 개발자는 실제 테스트 코드 작성에만 집중하면 됩니다.

공식 문서에 따르면 다음과 같습니다. "기본적으로 ActionDispatch::SystemTestCase는 Selenium 드라이버로 구동되며, Chrome 브라우저를 사용하고 브라우저 크기는 1400x1400입니다." Selenium은 Capybara의 기본 드라이버와 달리 JavaScript를 처리할 수 있기 때문에 선택된 것입니다.

모든 설정은 application_system_test_case.rb 파일을 통해 관리되며, 각 테스트 파일에서 이 파일만 require하면 됩니다.

#application_system_test_case.rb (기본값)

require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
end

Rails 6로 새 앱을 생성했다면 사실상 이것이 전부입니다. 즉, 인터넷에 흔한 Selenium 드라이버 설정 가이드나 RSpec의 feature test 설정 방법은 따로 찾아볼 필요가 없습니다.

기존 앱이라면 scaffold를 생성하는 과정에서 application_system_test_case.rb와 시스템 테스트에 필요한 파일들이 자동으로 만들어집니다.

참고로 Eileen Uchitelle이 시스템 테스트를 소개했던 당시에는 Firefox가 Selenium과 호환성 문제가 있어 Chrome이 선택되었습니다. 하지만 이후 Firefox 버전에서는 해결되었으므로, 다음과 같이 Firefox로 변경해 사용할 수도 있습니다.

#application_system_test_case.rb (Firefox로 변경)

require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :firefox, screen_size: [1400, 1400]
end

드라이버를 바꾼 후 $ rails db:test:prepare를 실행해 깨끗하게 초기화했는데, 새로운 테스트 러너가 :prepare를 자동 실행해 주기 때문에 이 과정도 생략 가능합니다.

Rails 6의 변화

시스템 테스트가 5.1에 도입된 이후 chromedriver-helper 젬은 deprecated 되었고, Rails 6 신규 앱에서는 webdrivers 젬으로 대체되었습니다. Rails 5 앱이라면 아직 교체하지 않았다면 webdrivers로 바꾸는 것이 좋습니다. webdrivers 젬이 있으면 selenium-webdriver 젬조차 따로 설치할 필요가 없습니다. 재미있는 사실은, Rails 6에는 selenium-webdriver와 webdrivers 두 젬이 모두 포함되어 있다는 점입니다.

더 이상 필요 없는 것들

Capybara 설정은 예전부터 골칫거리였습니다. 처음부터 설정하려면 올바른 데이터베이스 클리닝 전략을 찾고, capybara-webkit 젬의 의존성과 각종 예상치 못한 요구사항을 파악한 후에야 테스트 작성에 들어갈 수 있었습니다. 지금은 Rails가 필요한 모든 것을 제공하기 때문에, 오히려 가이드와 문서에 남아 있는 낡은(구식) 정보가 혼란을 주는 정도입니다. 더 이상 신경 쓰지 않아도 되는 항목들을 정리하면 다음과 같습니다.

  • minitest-rails-capybara 등 테스트용으로 언급되던 추가 젬이 필요 없습니다. 색상 출력, fail-fast, 특정 라인/테스트만 실행 같은 Minitest 확장 기능은 Rails 5.0에 도입된 테스트 러너에 이미 포함되어 있습니다.
  • database_cleaner 젬도 불필요합니다. Rails가 '트랜잭셔널 테스트' 방식으로 정리 작업을 대신 처리합니다.
  • Rails가 Capybara 기본값 대신 Selenium을 사용하므로 capybara-webkit도 필요 없으며, JavaScript 요소 테스트를 위한 별도 작업도 없습니다.
  • Capybara의 save_and_open_screenshot 대신 Rails가 제공하는 take_screenshot 메서드를 사용하세요. 스크린샷을 /tmp에 저장하고 테스트 출력에 링크를 제공해 손쉽게 확인할 수 있습니다.

실제 브라우저 vs 헤드리스 브라우저

시스템 테스트가 브라우저에서 링크 클릭, 폼 입력 등을 실제로 수행하는 모습을 지켜보는 재미가 있습니다. 하지만 속도가 느립니다. 테스트 실행 속도를 높이려면 헤드리스(headless) 브라우저를 사용할 수 있습니다. 헤드리스 브라우저는 GUI 없이 일반 브라우저와 동일하게 앱에 접근하며, 브라우저 창이 열리지 않을 뿐 동작 방식은 같습니다.

헤드리스 모드를 원한다면 headless_chrome 또는 headless_firefox를 사용하면 되고, 설정 변경도 아주 간단합니다.

#application_system_test_case.rb (headless_* 드라이버로 변경)

require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_firefox
end

주의: Rails 공식 문서와 여러 글에서 Poltergeist가 드라이버 옵션으로 언급되곤 하는데, 이는 한때 Capybara의 헤드리스 PhantomJS 드라이버로 인기가 많았던 도구입니다. 하지만 PhantomJS는 개발이 중단되었으므로 더 이상 고려할 필요가 없습니다. Rails 문서에 여전히 언급되어 있어 참고로 알려드립니다.

추가 커스터마이징 옵션은 더 있지만, 시작하기에는 위 내용만으로 충분합니다.

테스트 실행하기

$ rails test는 시스템 테스트를 제외한 모든 테스트를 실행합니다. 시스템 테스트는 반드시 $ rails test:system으로 명시적으로 실행해야 합니다. (참고로 $ rails 명령은 항상 bin/rails를 통해 실행되므로 더 이상 $ bin/rails라고 입력할 필요가 없습니다.)

  • 모든 시스템 테스트 실행: $ rails test:system
  • 특정 파일의 테스트 실행(users_test.rb): $ rails test/system/users_test
  • 특정 테스트 하나만 실행: $ rails test test/system/users_test.rb:21
  • 전체 테스트 실행(시스템 테스트 먼저): $ rails test:system test

주의: 옵션 플래그는 test:system과 함께 동작하지 않습니다. -f(fail fast)나 -v(verbose) 같은 플래그를 사용하려면 $ rails test test/system -v -f 형태로 실행하세요.

테스트 범위: 무엇을 테스트하고 무엇을 테스트하지 말까?

시스템 테스트는 단위 테스트를 대체하는 것이 아니라 보완하는 것입니다. 해피 패스(happy path) 하나와 오류 메시지나 리다이렉트가 발생하는 경로 하나 정도를 테스트하는 것으로 충분합니다. 브라우저에서 모든 엣지 케이스를 검증하는 용도가 아니라, 주요 기능만 커버하면 됩니다.

테스트 대상을 선정할 때는 사용자가 앱을 실제로 사용하는 흐름을 반영하는 엔티티를 찾으려 노력합니다. 테스트 이름 짓기에는 GitLab의 명명 규칙인 ROLE_ACTION_test.rb 형식을 차용했는데, 이 접근 방식과 잘 맞습니다. 예를 들면 user_shares_card_test.rb 같은 식입니다.

유용한 팁과 트릭

  • Devise 인증: Devise를 사용한다면 통합 헬퍼로 테스트 사용자의 로그인/로그아웃을 처리할 수 있습니다. 테스트 클래스에 include Devise::Test::IntegrationHelpers를 추가하거나 test_helper.rb에 추가해 모든 테스트에서 사용할 수 있습니다. 이후 사용자를 만들고 sign_in(@user)를 호출하면 됩니다. setup 메서드에 넣으면 teardown에서 로그아웃할 필요가 없습니다. Rails가 setup 메서드의 내용을 자동으로 정리해 줍니다.
  • 폼 다루기: Rails가 모델명+필드명으로 자동 생성하는 id(fill_in "user_email", click_on :commit)을 사용하고 싶겠지만, 시스템 테스트는 사용자가 화면에서 실제로 보는 것을 검증하는 것이므로 눈에 보이는 요소, 즉 텍스트를 사용하는 것이 좋습니다. i18n locale 파일에 참조 키를 두고 해당 키를 사용하는 방법(fill_in :user_email)도 좋은 선택입니다. Capybara에서 I18n 텍스트를 찾으려면 전체 문법을 사용해야 합니다: assert_selector "h1", text: I18n.t("activerecord.models.things").
  • 패스 헬퍼: path 헬퍼는 기본 포함되어 있습니다. 일부 라이브러리는 include ActionMailer::TestHelper처럼 헬퍼를 직접 포함해야 assert_emails 메서드를 사용할 수 있습니다.
  • 커스텀 클래스: 서로 다른 화면 크기로 테스트를 실행하려면 커스텀 클래스를 만들 수 있습니다. 공식 가이드를 참고하세요.
  • 스크린샷 활용: 스크린샷 기능은 문서화나 홍보 자료 제작에도 활용할 수 있습니다. 스크린캐스트로 만들어 재생 속도를 늦추면 몇 분 만에 제품 데모 영상이 완성됩니다!
  • 제너레이터: Rails는 시스템 테스트용 제너레이터를 제공합니다.
  • Minitest 문서: Rails의 Minitest는 순수 Minitest와 약간 다르며, Rails 고유의 메서드와 assertion이 추가되어 있습니다. Minitest 문서보다 Rails 문서를 먼저 확인하세요.

시스템 테스트를 사용하면서 정말 즐거웠는데, 그 대부분은 기본 설정만으로 바로 사용할 수 있을 만큼 진입 장벽이 낮았기 때문입니다.

맺음말

이번 글에서는 Rails가 기본으로 제공하는 시스템 테스트 설정과 최소한의 커스터마이징 방법을 살펴보았습니다. Minitest는 시스템 테스트 작성에 훌륭한 선택이며, 위의 팁들을 활용하면 첫 번째 시스템 테스트를 빠르게 구동할 수 있습니다. 브라우저에서 테스트가 마법처럼 작동하는 모습을 직접 확인해 보세요!