When to use describe/context/it in RSpec07 Apr 2021
The well-structured test suite helps check the necessary cases are covered at a glance. Developers looking into the code, later on, can quickly grasp which case they should add or modify. The famous unit testing framework provides us a way to organize the test cases in that manner.
RSpec is a de facto standard testing framework used in many Ruby projects. Although I have used RSpec in some projects, I did not fully understand how to
it keyword correctly. These keywords are used just for representing the meaningless nested structure in my case. But that does not sound nice. Using these keywords properly leads us to inject an understandable form to the unit test written in RSpec. This article summarizes what we should think in writing RSpec test cases in terms of
describe: Target Object
Let’s assume we have the following
FizzBuzz class to be tested.
class FizzBuzz def self.run(n) if n % 3 == 0 && n % 5 == 0 "FizzBuzz" elsif n % 3 == 0 "Fizz" elsif n % 5 == 0 "Buzz" else n end end end
We want to ensure that FizzBuzz works as expected with RSpec. The target object is an instance of FizzBuzz.
describe FizzBuzz do # Test cases end
context is a place to hold the condition that should be satisfied before running the test. It can be a type of input or precondition imposed on the target class. We put the type of input passed to the
run method of FizzBuzz.
describe FizzBuzz do context '3-multiple' do # Test here end context '5-multiple' do # Test here end context '15-multiple' do # Test here end context 'other' do # Test here end end
We describe the expected output from the method or object in
describe FizzBuzz do context '3-multiple' do it 'Get Fuzz' do expect(FuzzBuzz.run(3)).to eq('Fuzz') expect(FuzzBuzz.run(6)).to eq('Fuzz') end end context '5-multiple' do it 'Get Buzz' do expect(FuzzBuzz.run(5)).to eq('Buzz') expect(FuzzBuzz.run(10)).to eq('Buzz') end end context '15-multiple' do it 'Get FizzBuzz' do expect(FuzzBuzz.run(15)).to eq('FizzBuzz') expect(FuzzBuzz.run(30)).to eq('FizzBuzz') end end context 'other' do it 'Get original number' do expect(FuzzBuzz.run(4)).to eq(4) expect(FuzzBuzz.run(8)).to eq(8) end end end
This guideline is so helpful to me for writing the well-structured test in RSpec. The background information behind the scene is explicit with this structure.