Normally when testing objects with RSpec, I prefer to setup the object state in top-level as context. Inside those contexts, the behavior (messages) are then each tested inside of that state. See ("TBD FILL IN HERE")[] for more details on this.
However, there are times you find yourself needing to pass in a lot of test cases for some behavior.
module FrequencyCounter
def self.count(s1, s2)
[-1, 0, 1]
end
end
It leads to more lines, however, it is a bit more explicit in what the intent.
describe FrequencyCounter do
subject(:counter) { FrequencyCounter }
shared_examples "counting word frequencies" do |source:, target_words:, with_frequency:, description: nil|
it (description || "parses #{source.inspect} and #{target_words.inspect} into #{with_frequency.inspect}") do
expect(counter.count(source, target_words)).to eq with_frequency
end
end
include_examples "counting word frequencies",
source: "foo bar",
target_words: "having fun",
with_frequency: [-1,0,1]
include_examples "counting word frequencies",
source: "baz bar",
target_words: "not fun",
with_frequency: [-1,0,1],
description: "edge case for something"
end
It's also possible to use plain Ruby enumerables for this type of repeated example testing.
describe FrequencyCounter do
subject(:counter) { FrequencyCounter }
context "counting word frequencies" do
examples = [
[ "foo bar", "having fun", [-1, 0, 1] ],
[ "baz bar", "not fun", [-1, 0, 1], "edge case for something" ],
]
examples.each do |source, target_words, with_frequency, description|
it (description || "parses #{source.inspect} and #{target_words.inspect} into #{with_frequency.inspect}") do
expect(counter.count(source, target_words)).to eq with_frequency
end
end
end
end
Of course there's nothing stopping you from combining these together.
describe FrequencyCounter do
subject(:counter) { FrequencyCounter }
shared_examples "counting word frequencies" do |examples:|
examples.each do |opts|
source = opts.fetch(:source)
target_words = opts.fetch(:target_words)
has_frequency = opts.fetch(:has_frequency)
description_text = opts.fetch(:description){
"parses #{source.inspect} and #{target_words.inspect} into " \
"#{has_frequency.inspect}"
}
it description_text do
expect(counter.count(source, target_words)).to eq has_frequency
end
end
end
it_behaves_like "counting word frequencies", examples: [
{
source: "foo bar",
target_words: "having fun",
has_frequency: [-1, 0, 1]
},
{
source: "baz bar",
target_words: "not fun",
has_frequency: [-1, 0, 1],
description: "edge case for something"
},
]
end