Understand code coverage with Rspec, the Ruby on Rails test framework

When I write a test case, I get a story about how much coverage is covered.

What is code coverage? I thought, so I will summarize it as my memorandum.

What is code coverage?

In software testing, all program code (internal logic) to be tested It is the ratio (coverage rate) of the part of the body that has been tested. Reference

Typical coverage

C0: Instruction coverage

Each statement is executed at least once

C1: Branch coverage

Execute at least once for each judgment condition

C2: Condition coverage

Authenticity in each conditional statement is executed at least once

MCC: Comprehensive condition coverage

All combinations of truth and falsehood that can be placed in each condition are executed

In fact, write tests with coverage in mind with Rspec

Ruby code to test

sample.rb


module CodeCoverage
  class << self
  # main
  # @params [interger] x
  # @params [interger] y
  # @return [String]Strings that differ depending on the values of x and y
  #
  #Argument assumes only interger
  def main(x, y)
    result = ''
    if x >= y || x % 2 == 0
      result << 'Process 1'
    else
      result << 'Process 2'
    end
    if x*y > 10
      result << 'Process 3'
    else
      result << 'Process 4'
    end
    return result
  end
  end
end

Test code written in Rspec

What is Rspec

One of the frameworks to realize TDD (Test Driven Development) which is one of the development methods of Ruby on Rails Reference

Test code body

RSpec.describe CodeCoverage do
  shared_examples 'Process 1 and process 3 pass' do
    it 'The wording of process 1 and process 3 is returned' do
      expect(subject).to eq 'Process 1 Process 3'
    end
  end
  shared_examples 'Process 1 and process 4 pass' do
    it 'The wording of process 1 and process 4 is returned' do
      expect(subject).to eq 'Process 1 Process 4'
    end
  end
  shared_examples 'Process 2 and process 3 pass' do
    it 'The wording of process 2 and process 3 is returned' do
      expect(subject).to eq 'Process 2 Process 3'
    end
  end
  shared_examples 'Process 2 and process 4 pass' do
    it 'The wording of process 2 and process 4 is returned' do
      expect(subject).to eq 'Process 2 Process 4'
    end
  end

  describe 'main' do
    subject { described_class.send(:main, x, y) }
      # C0:Instruction coverage
    #Write to execute at least once with few instructions
      context 'For C0' do
        context 'Go through process 1 and process 3' do
          let(:x) { 11 }
          let(:y) { 1 }
          it_behaves_like 'Process 1 and process 3 pass'
        end
        context 'Go through process 2 and process 4' do
          let(:x) { 1 }
          let(:y) { 9 }
          it_behaves_like 'Process 2 and process 4 pass'
        end
      end
      # C1:Branch coverage
      #Execute at least once for each judgment condition
      context 'For C1' do
        context 'Go through process 1 and process 3' do
          let(:x) { 11 }
          let(:y) { 1 }
          it_behaves_like 'Process 1 and process 3 pass'
        end
        context 'Go through process 1 and process 4' do
          let(:x) { 3 }
          let(:y) { 2 }
          it_behaves_like 'Process 1 and process 4 pass'
        end
        context 'Go through process 2 and process 3' do
          let(:x) { 3 }
          let(:y) { 5 }
          it_behaves_like 'Process 2 and process 3 pass'
        end
        context 'Go through process 2 and process 4' do
          let(:x) { 1 }
          let(:y) { 4 }
          it_behaves_like 'Process 2 and process 4 pass'
        end
      end
      
      # C2:Condition coverage
      #Authenticity in each conditional statement is executed at least once
      context 'For C2' do
        context 'x>=y and x*y>10' do
          context 'Go through process 1 and process 3' do
            let(:x) { 11 }
            let(:y) { 1 }
            it_behaves_like 'Process 1 and process 3 pass'
          end
        end
        context 'x>=y and x*y<10' do
          context 'Go through process 1 and process 4' do
            let(:x) { 3 }
            let(:y) { 2 }
            it_behaves_like 'Process 1 and process 4 pass'
          end
        end
        context 'x<y and x are even and x*y>10' do
          context 'Go through process 1 and process 3' do
            let(:x) { 4 }
       let(:y) { 5 }
            it_behaves_like 'Process 1 and process 3 pass'
          end
        end
        context 'x<y and x are even and x*y<10' do
          context 'Go through process 1 and process 4' do
            let(:x) { 2 }
            let(:y) { 3 }
            it_behaves_like 'Process 1 and process 4 pass'
          end
        end
        context 'x<y and x are odd and x*y>10' do
          context 'Go through process 2 and process 3' do
            let(:x) { 3 }
            let(:y) { 5 }
            it_behaves_like 'Process 2 and process 3 pass'
          end
        end
        context 'x<y and x are odd and x*y<10' do
          context 'Go through process 2 and process 4' do
            let(:x) { 1 }
            let(:y) { 4 }
            it_behaves_like 'Process 2 and process 4 pass'
          end
        end
      end
    end
  end
end

It's easy to understand if you write it like this. How much code coverage is satisfied is appropriate, but at work it is up to about C1.

Recommended Posts

Understand code coverage with Rspec, the Ruby on Rails test framework
[Ruby on Rails] View test with RSpec
[Ruby on Rails] Controller test with RSpec
[Ruby on Rails] Model test with RSpec
Introducing Rspec, a Ruby on Rails test framework
[Rails] Test with RSpec
I rewrote the Rails tutorial test with RSpec
[Ruby on Rails] Until the introduction of RSpec
Introducing Rspec with Ruby on Rails x Docker
Publish the app made with ruby on rails
Determine the current page with Ruby on Rails
[Ruby on Rails Tutorial] Error in the test in Chapter 3
Run Ruby on Rails RSpec tests with GitHub Actions
[Rails] Test code using Rspec
Solve the N + 1 problem with Ruby on Rails: acts-as-taggable-on
[Ruby on Rails] Automatically enter the address from the zip code
Programming with ruby (on the way)
Let's unit test with [rails] Rspec!
[RSpec on Rails] How to write test code for beginners by beginners
[Ruby on Rails] Code check using Rubocop-airbnb
part of the syntax of ruby ​​on rails
Notes on using FCM with Ruby on Rails
[Rails] Procedure for linking databases with Ruby On Rails
[Ruby on Rails] Upload multiple images with refile
I made a portfolio with Ruby On Rails
How to resolve errors that occur in the "Ruby on Rails" integration test
I understand Ruby on Rails params (with Hanshin Tigers poker faceman, Atsushi Nomi)
[Ruby On Rails] Error in test using RSpec MySQL client is not connected
[Ruby On Rails] When a model unit test is performed with RSpec using FactoryBot, an error occurs because the foreign key is not entered.
[Ruby] Basic code list. Keep the basics with examples
RSpec test code execution
[Ruby on Rails] Delete s3 images with Active Strage
[Ruby On Rails] How to use simple_format to display the entered text with line breaks
Test run on rails
Ruby on Rails Elementary
Ruby on Rails basics
Challenge the settings for developing with vue.js on Rails 6
Test Nokogiri with Rspec.
Ruby On Rails Association
[Rails] Put together the same code with controller actions
(Ruby on Rails6) Reflecting the posted content from the form
Created RSS / Atom format sitemap with Ruby on Rails
Try using the query attribute of Ruby on Rails
[Ruby on Rails] Only the user who posted can edit
I tried installing Ruby on Rails related plugin with vim-plug
Definitely useful! Debug code for development in Ruby on Rails
[Ruby on Rails] Quickly display the page title in the browser
<Dot installation> Introduction to Ruby on Rails5 Source code comparison
[Ruby on Rails] Understand why Set # include? Is so fast
(Ruby on Rails6) Display of the database that got the id of the database
[Environment construction] Get the Ruby on Rails 6 development environment within 1 hour
Delete all the contents of the list page [Ruby on Rails]
A note about the seed function of Ruby on Rails
[Ruby on Rails] Implement login function by add_token_to_users with API
[Apple login] Sign in with Apple implementation procedure (Ruby on Rails)
[Note] About the Fizz_Buzz problem (How Ruby on Rails works)
Ruby on rails learning record -2020.10.03
Portfolio creation Ruby on Rails
Ruby on rails learning record -2020.10.04
[Ruby on Rails] Debug (binding.pry)
Ruby on rails learning record -2020.10.05