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
- configuring Codecov settings
- adding Flags to isolate coverage reports
- labelling critical files