I have a process that returns a result set that I want to test for validity using rspec. The process will return different results based on parameters but there are many examples that are common to all of them so I would like to create a set of common examples that I can run against all of them.
I know that the preferred practice is to use let to build the result. The problem is that each process takes a minute or two to generate a result and I have probably 30 examples. With all of the permutations based on different parameters I am running about 500 examples.If I had to rebuild the result for each example the test would run more than a day.
So instead I am building a result in a before(:all) block and assigning it to an attribute something like this:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it 'Looks lik a result' do
expect(result.something).to ...
end
it 'Feels lik a result' do
expect(result.something).to ...
end
end
end
Maybe there is a better way than using an attribute. I want to do something like this:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it_behaves_like "A result" result
end
end
Using an attribute in this context fails. Is there a different way to do this?
Shared examples are a good tool to describe some complex behavior and reuse it across different parts of a spec. Things get more complicated when you have the same behavior, but it has some slight variations for different contexts.
Use shared_context to define a block that will be evaluated in the context of example groups either locally, using include_context in an example group, or globally using config. include_context .
According to the rspec source code, “context” is just a alias method of “describe”, meaning that there is no functional difference between these two methods. However, there is a contextual difference that'll help to make your tests more understandable by using both of them.
Use let to define a memoized helper method. The value will be cached. across multiple calls in the same example but not across examples. Note that let is lazy-evaluated: it is not evaluated until the first time. the method it defines is invoked.
You can pass arguments to shared examples like this:
shared_examples_for "A result" do |argument|
# some tests with argument
end
And then pass in my_argument
like this:
it_behaves_like "A result", my_argument
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With