I got a class like that:
class Calculation
def initialize
heavy_calculation
end
def result
'ok'
end
def errors
nil
end
private
def heavy_calculation
p "Performing CPU-heavy calculations"
end
end
And RSpec for checking both public methods
describe Calculation do
let(:calculations) { Calculation.new }
it 'result equal ok' do
expect(calculations.result).to eq('ok')
end
it 'errors equal nil' do
expect(calculations.errors).to be_nil
end
end
Running this code we got two times "Performing CPU-heavy calculations"
in the terminal, so the Calculation constructor was called twice
I was trying to refactor this code so the constructor run only once - but didn't find any solution which works flawless, without running the calculation code twice, or without leaking values to other spec files
So any advice on how to solve that correctly?
CodePudding user response:
Ok. I think that there is no proper way to solve that problem
I basically have two choices:
- Leak data (
Heavy calculation
) between examples via usingbefore(:all)
and thus not properly isolation tests cases - Isolate but perform heavy calculations several times
So either of those choices comes with different tradeoffs and I must choose one of them
And seems that leave tests in current way be more correct choice
CodePudding user response:
let
is intended to be lazily evaluated. The values declared by let are reset for each test so it makes sense that you see the constructor called once for each test.
If you are looking purely for a test optimization, then the solution is probably to abandon the use of let
. Rspec blocks are like any other ruby code so you can declare local variables. The code below gives two passing results with only one (expensive) call to the constructor:
describe Calculation, type: :model do
calculations = Calculation.new
it 'result equal ok' do
expect(calculations.result).to eq('ok')
end
it 'errors equal nil' do
expect(calculations.errors).to be_nil
end
end
If the issue is broader -- that you really only need to instantiate the class once and then track changes -- then you might want to investigate Singleton