Testing fundamentals


Introduction to Rspec


The Fundamentals

The fundamentals: why test?

  • Verification : Does this feature work?
  • Spotting regression: Something broke something else 
  • Specification: The machine should work this way 
  • Documentation: Test describes how it should behave 
  • Developer feedback:
    • ​What I thought and what client wanted are different 
    • What I thought will not work
  • ​Code design: Decoupling, cleaner interfaces, better OOP 

The fundamentals: why test?

  • Manual tests are the default solution to the problem
  • Is also important, and unavoidable (UI/aesthetics)
  • Easy to get started
  • Economical: 
    • ManualTester.price < Developer.price (generally)

Manual Tests

Semi automated tests

  • Partially automated, needs some human involvement.
  • Record and playback / Export and compare
  • Not as repeatable as fully automated tests

The fundamentals: who writes the tests?

  • The developer

  • Testers/QA should write tests is an outdated idea, not practiced in Ruby world 

The fundamentals: when to start?

When to start testing

  • As early as possible

  • No tests are fine for very few situations, like prototype level or experimental projects

When to absolutely start testing

  • When the following signs show-up:

    • ​Regressions

    • Implementation slowness

    • Poor quality in general

    • Developer stress

The fundamentals: TDD

  • Test first, then code

  • Needs specifications beforehand, as examples
  • Ideal when specs are available (requirements)
  • Leads to good design of code
  • This talk/workshop is not about TDD
  • This may be a stepping stone towards TDD

The fundamentals: Test environment

  • Rails comes with a test environment.

  • The idea is: the database should be separate

  • And some settings/config/gems should also be separate

  • Test scripts are programs written as part of the same code base

  • The scripts are executed using a test runner

  • Test scripts contain a bunch of test-cases

  • Every test-case undergoes a setup and a teardown phase

  • Data creation/setup needed for the test-case happens in the setup-phase

  • Teardown is for cleanup, deletes all data created by the test

  • (Ideally) each test-case runs in complete isolation, and should not be dependent on any other tests

The fundamentals: Minitest and RSpec

  • Rails ships with the MiniTest test framework. RSpec is a popular alternative

  • All Rails project get MiniTest by default, and can be replaced with RSpec

  • The default data creation technique in Rails is fixtures, while the popular one is factories.

  • The difference has been a subject of much debate

  • We will cover RSpec for this workshop. Switching between the two is not very difficult after knowing the fundamentals

The fundamentals: TDD controversy

  • There is also a debate over whether TDD is the correct way to approach software development

  • Rails creator David H Hansen has written articles opposing, and there have been several in-depth arguments from both sides

  • It is worth looking into the entire discussion before arriving at a decision

RSpec Introduction

Rspec introduction


  • It is a test framework and a test runner
  • We write test-cases using Rspec recommended syntax
  • For verification, we use Rspec provided assertion methods
  • We create data on our own (or using factories or fixtures) – Rspec has no involvement there 
  • RSpec gives a mocking framework too


Rspec introduction: the test case

## Code under test:

def add(a, b)
  a + b

## The test

RSpec.describe 'add' do                ## mention what is being tested

  it 'should give 5 for 2 and 3' do    ## The test case
    c = add(2, 3)                      ## Invoke the code
    expect(c).to eq(5)                 ## Verify the result

Rspec introduction: primary syntax

  • There are many more methods and concepts, but this is enough to get started

Holds the test case



The assertion statement. Does the verification



Wraps the test cases, and declares what is being tested

Rspec introduction: running the tests

  • Just one necessity: code under test should be loaded (require) before the describe block starts
  • The commend to run the test: 
    • ​​​ rspec test_file.rb 

Rspec Introduction: samples-1

  • The above code can be placed in a file, and be run using the rpsec command.
  • Will work if rspec gem is installed
## Tautology

require 'rspec'

RSpec.describe 'the truth' do

  it 'should be true' do
    expect(true).to eq(true)

  it 'should not be false' do
    expect(true).to_not eq(false)

## rspec sample1.rb

Rspec Introduction: samples-2

    ## Addition

    def add(a, b)
      a + b

    ## The test
    require 'rspec'

    RSpec.describe 'add' do

      it 'should give 5 for 2 and 3' do
        c = add(2, 3)
        expect(c).to eq(5)

    ## rspec sample2.rb

Rspec Introduction: samples-3

## prime_number.rb
class PrimeNumber
  def self.is_it?(num)
    (2...num).each { |x| return false if num % x == 0 }

## prime_number_spec.rb
require 'rspec'
require File.expand_path('../prime_number.rb', __FILE__)

RSpec.describe 'PrimeNumber' do
  describe 'is_it?' do

    it 'should be true for 5' do
      expect(PrimeNumber.is_it?(5)).to eq(true)

    it 'should be false for 77' do
      expect(PrimeNumber.is_it?(77)).to eq(true)

RSpec: common conventions

  • Test code is kept in the spec directory
  • There is generally a spec_helper.rb file that loads the necessary code and any plugins or even configs
  • The .rspec file contains some config too

Introduction to Rspec

By Abhishek Yadav

Introduction to Rspec

  • 1,158