Blog Post

Getting Started with Code Coverage for Ruby

January 26, 2023 Tom Hu

Codecov and Ruby

Ruby, developed in 1995, is one of the most popular programming languages in the world. This article will walk you through an example Ruby project to get up and running with testing and code coverage. You can view the entire source code of this post at our example repository.

For our project, we will be using Ruby 3.1.3. You will need to create a new public repository in GitHub. You should also go ahead and create a Codecov account.

Getting started with Ruby

We will start with a simple calculator app that exposes two functions: add and subtract. Both functions accept two arguments and return a number. We can paste the code below into the file lib/calculator.rb

# frozen_string_literal: true

class Calculator
  def self.add(x, y)
    x + y
  end

  def self.subtract(x, y)
    x - y
  end
end

Now, let’s add a test for our add function.

test/calculator_test.rb

​​# frozen_string_literal: true

require 'test_helper'

class TestCalculator < Minitest::Test
  def test_add
    assert_equal(3.0, Calculator.add(1, 2))
  end
end

To run our tests, we will be taking advantage of the minitest gem. We will also need to update our Gemfile and build out the testing infrastructure to use minitest

Gemfile

source 'https://rubygems.org'

gem 'rake'
gem 'minitest'

test/test_helper.rb

# frozen_string_literal: true

require "calculator"
require "minitest/autorun"

Run your tests and get coverage

To run our coverage, we will need to set up a rake task. Create a Rakefile in the root directory.

Rakefile

# frozen_string_literal: true

require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
  test.libs << 'lib' << 'test'
  test.pattern = 'test/**/*_test.rb'
  test.verbose = true
end

task default: :test

Install the dependencies by running bundle install. You can run the test locally by calling rake test. This should bring up the following output.

--> rake test
…/3.1.3/bin/ruby -w -I"lib:lib:test" …/3.1.3/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb "test/calculator_test.rb"
Run options: --seed 11374

# Running:

.

Finished in 0.000866s, 1154.7344 runs/s, 1154.7344 assertions/s.

1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

To get coverage results, we will need to add two more gems, simplecov and simplecov-cobertura.

Add the following lines to the Gemfile

gem 'simplecov'
gem 'simplecov-cobertura'

You will also need to update the test/test_helper.rb file. Insert the following code directly below the first comment line.

require "simplecov"
SimpleCov.start

require 'simplecov-cobertura'
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter

Install the dependencies and run the tests to view coverage

--> bundle install && rake test
Fetching gem metadata from https://rubygems.org/..
…
Run options: --seed 46797

# Running:

.

Finished in 0.000864s, 1157.4075 runs/s, 1157.4075 assertions/s.

1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
Coverage report generated for Unit Tests to …/coverage/coverage.xml. 4 / 5 LOC (80.00%) covered

Note the last line shows we have covered 4/5 lines, or 80% coverage.

How to upload to Codecov

Now that we are able to collect coverage locally, let’s learn how to upload these reports to Codecov. Codecov is a code coverage tool that provides reports on how much of a project’s codebase is tested. It is often used in conjunction with continuous integration (CI) systems to ensure that new code changes are adequately covered by tests.

We will be using GitHub Actions as the Ci and the Codecov Action to upload coverage reports.

Create a file called .github/workflows/ci.yml.

name: Workflow for Ruby code coverage
on: [push, pull_request]
jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up Ruby latest
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 'head'
      - name: Install dependencies
        run: bundle install
      - name: Run tests and collect coverage
        run: bundle exec rake
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3

It is recommended that you install the Codecov app for this repository to prevent rate-limiting issues. Save your code and push up to GitHub.

git checkout -b 'initial-commit'
git add .
git commit -m 'Initial commit and upload coverage to Codecov'
git push origin initial-commit

In GitHub, open the pull request and wait for CI and Codecov to finish running and analyzing. You should see the following pull request commit.

You should also see four status checks, two of which come from Codecov.

Our documentation contains more information on the meaning of each status check. When you are ready, merge the pull request.

Covering uncovered code

Now that we can get coverage data in our pull request. Let’s take a look at how to increase coverage.

Let’s take a look at the coverage report from Codecov. Navigate to your repository from the Codecov UI. You should see a dashboard like this.

Notice that there are only 4 covered lines in the Code tree. If we click on lib, and calculator.rb, we’ll come to the file view.

From this view, we can tell that we haven’t written a test for our subtract function!

Create a new branch in your terminal

git checkout main
git pull
git checkout -b 'subtract-test'

and update the test file test/calculator_test.rb with the following code below the add test.

  def test_subtract
    assert_equal(-1.0, Calculator.subtract(1, 2))
  end

Save the code and open a new pull request.

git add .
git commit -m 'fix: add tests for subtract fn'
git push origin subtract-test

Notice the Codecov comment shows the coverage increasing from 80.00% to 100.00%.

Advanced Codecov configurations

Now that you have uploaded your first Ruby coverage reports successfully to Codecov, you can check out some of our other features including

Before we redirect you to GitHub...
In order to use Codecov an admin must approve your org.