For methods that return True or False, there is a convention in Ruby to end the method name with a ?. RSpec provides a shortened test notation, so-called predicate matchers for that convention. Thus the test expectation can be expressed way more concisely.
Long RSpec Tests
First, an exemplary starting point: a city is a metropolis when it has more than a million citizen. The implementation is meant to take place in the method City#metropolis?.
The expectations in RSpec:
describe City do
subject { City.new }
describe '#metropolis?' do
context 'without population' do
it 'is false' do
expect(subject.metropolis?).to be false
end
end
context 'when population is less than a million' do
before { city.population = 999_999 }
it 'is false' do
expect(subject.metropolis?).to be false
end
end
context 'when population is equal to a million' do
before { city.population = 1_000_000 }
it 'is true' do
expect(subject.metropolis?).to be true
end
end
end
end
However, the same expectations can be expressed way more concisely.
Concise RSpec Tests
The same tests:
describe City do
subject { City.new }
describe '#metropolis?' do
context 'without population' do
it { is_expected.to_not be_metropolis }
end
context 'when population is less than a million' do
before { subject.population = 999_999 }
it { is_expected.to_not be_metropolis }
end
context 'when population is equal to a million' do
before { city.population = 1_000_000 }
it { is_expected.to be_metropolis }
end
end
end
Like the RSpec’s built in matchers be_empty or be_nil, RSpec expects the test object to have a method that can be derived from the matcher: be_xxx => xxx?, which then is called.
Implementation
The implementation of the example:
class City
METROPOLIS_POPULATION = 1_000_000
attr_accessor :population
def metropolis?
population.to_i >= METROPOLIS_POPULATION
end
end
and the test results:
City
#metropolis?
without population
should not be metropolis
when population less than a million
should not be metropolis
when population equal to a million
should be metropolis
Finished in 0.00358 seconds (files took 0.48847 seconds to load)
3 examples, 0 failures