LYnLab 로고

블로그취미로그

Rails와 GitHub Actions에 커버리지 레포트를 달아보자

이 블로그의 CMS이기도 한 Shiori를 대폭 리팩토링하면서 테스트가 얼마나 잘 작성되어있는지 궁금해졌습니다.

2023-07-09#프로그래밍#Ruby

💡 이 글은 작성된지 1년 이상 지났습니다. 정보글의 경우 최신 내용이 아닐 수 있음에 유의해주세요.

앞으로도 종종 궁금할 일이 있을테니, 이참에 아예 CI 수준에서 커버리지 레포트를 달아보기로 했습니다.

SimpleCov 추가

Codecov와 같은 무료로 사용 가능한 상용 서비스도 존재합니다. 그러나 Codecov는 프라이빗 레포지토리를 포함한 소스 코드 및 시크릿 정보 등의 사용자 정보가 유출된 사고가 터진 바 있습니다.

개인 프로젝트야 큰 영향이 없겠지만, 만약 회사 프로젝트였다면 어떤 영향이 생겼을지 상상하기 어렵습니다. 때문에 조금 번거롭더라도 모든 행위가 통제 가능한 영역에 있는 오픈 소스 프로젝트를 사용하기로 했습니다.

우선 아래와 같이 의존성을 추가, 설치합니다.

# Gemfile
gem "simplecov"
gem "simplecov-lcov"

LCOV는 리눅스에서 사용하는 커버리지 정보를 담는 포맷입니다. Ruby 혹은 Rails에 의존적이지 않기 때문에 다른 언어에서도 동일하게 플러그인을 사용할 수 있다는 장점이 있죠.

이후 spec_helper.rb 혹은 그에 준하는 파일에 다음을 추가합니다.

# spec/spec_helper.rb
require "simplecov"
require "simplecov-lcov"

SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
  SimpleCov::Formatter::HTMLFormatter,
  SimpleCov::Formatter::LcovFormatter,
])

SimpleCov.start "rails" do
  add_filter "/spec/"
end

LCOV 파일은 프로그램을 위한 포맷이기 때문에 사람이 읽기 어렵습니다. 때문에 HTMLFormatter를 함께 설정하여 브라우저를 통해 확인할 수 있도록 하였습니다.

또한 SimpleCov가 소스 코드를 파악할 수 있도록 Rails 코드가 로드되기 전에 설정되어야 한다는 점에 주의해야합니다. 때문에 웬만하면 spec_helper.rb 의 최상단에 추가하는 것이 좋습니다.

위와 같이 설정한 후 테스트를 한 바퀴 돌려봅시다.

$ bundle exec rspec
................................................................

Finished in 1.34 seconds (files took 1.53 seconds to load)
64 examples, 0 failures

Coverage report generated for RSpec to ./coverage. 520 / 706 LOC (73.65%) covered.
Lcov style coverage report generated for RSpec to ./coverage/lcov/shiori.lcov

간단하게 73.65% 라는 커버리지가 표시되고, 커버리지 레포트 파일이 생성되었음을 볼 수 있습니다. 생성된 coverage/index.html 파일을 열어서 구체적인 커버리지를 시각적으로 확인할 수도 있습니다.

브라우저에서 커버리지 레포트를 확인하는 화면

각 분기에 대한 커버리지가 표현된 화면

GitHub Actions 설정

생성된 LCOV 파일을 통해 GitHub의 pull request에 커버리지가 보고되도록 설정해봅시다. 다행히도 LCOV 파일을 읽어 보고해주는 오픈 소스 액션은 여럿 존재합니다.

name: Run tests

on: [ push, pull_request ]

jobs:
  test:
    # ... 설정 과정은 프로젝트마다 다양하므로 생략
    steps:
      - uses: actions/checkout@v2
      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2
          bundler-cache: true
      - name: Run tests
        run: |
          bundle exec rails db:migrate
          bundle exec rspec
      - name: Report coverage
        if: ${{ github.event_name == 'pull_request' }}
        uses: romeovs/[email protected]
        with:
          # 아래 파일 이름은 프로젝트의 설정에 따라 달라집니다.
          lcov-file: ./coverage/lcov/project_name.lcov

여기서는 if 조건을 통해 pull request에서만 댓글이 달리도록 하였습니다. 만약 해당 조건이 없다면 각 커밋 단위로 커버리지 레포트를 측정할 수도 있습니다.

커버리지가 NaN%?

커버리지가 NaN으로 표시되는 모습

오류는 발생하지 않았지만 커버리지가 NaN%로 보고되는 문제가 있었습니다. 이는 simplecov-lcov gem이, lcov-reporter-action이 사용하는 "LH", "LF" 정보를 출력하지 않기 때문입니다.

이를 해결하기 위한 PR을 누군가 생성해놓은 상태이며, 해당 PR이 머지되기 전까지는 simplecov-lcov를 포크 레포지토리를 지정하여 사용할 수 있습니다.

# Gemfile
gem "simplecov-lcov", require: false, github: "t-mario-y/simplecov-lcov", branch: "feature/write-LF-LH"

최종적으로 아래와 같이 커버리지 레포트가 잘 생성된 것을 확인할 수 있습니다.

커버리지가 정상적으로 표시되는 모습

관련된 글

Rails Global ID로 전역 객체 식별하기

Global ID는 Rails의 모든 객체를 식별할 수 있는 URI(Uniform Resource Identifier)입니다.

Ruby on WebAssembly: 살짝 맛보기

Ruby 3.2에 추가된 WebAssembly 지원을 간단하게 테스트해봅시다.

Ruby의 and와 &&는 다르다

Ruby로 프로그램을 짜다보면 반드시 밟게되는 지뢰가 있습니다. 바로 or 과 ||, 혹은 and 와 && 연산자의 우선순위가 달라서 발생하는 일입니다.

작성한 댓글은 giscus를 통해 GitHub Discussion에 저장됩니다.

크리에이티브 커먼즈 라이선스크리에이티브 커먼즈 저작자표시크리에이티브 커먼즈 동일조건변경허락

본 사이트의 저작물은 별도의 언급이 없는 한 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

LYnLab, 2011 - 2024.