Why should we write tests redundantly?
During the development of Ruby on Rails applications, we often fall into the pitfalls of writing tests in a DRY way. DRY might be the most well-known principle of software development. Developers are likely to follow the guide and try to write DRY codes immediately whenever they find some "duplications." Of course, DRY is important in some situations, but I want to articulate this phrase.
Don't make your tests DRY excessively.
As Testing on the Toilet: Tests Too DRY? Make Them DAMP! describes,
code readers have to do some mental computation to understand the tests themselves.
When other developers refactor codes and hit the failure of DRY tests, they must move their eyes up and down.
Here is an example of the situation; this code uses subject
and makes it expect the variable named a
to be declared with let
.
It requires developers to understand how subject
is declared and what is a
.
Bad:
describe SomeModel, type: :model do
describe '#do_something' do
subject { instance.do_something(a) }
let(:instance) { SomeModel.new }
# Many lines appear...
context 'when a is true' do
let(:a) { true }
it 'gets true' do
expect(subject).to be true
end
end
context 'when a is false' do
let(:a) { false }
it 'gets false' do # <-- If this test fails, developers must understand what `subject` is, and they must move their eyes upward.
expect(subject).to be false
end
end
end
end
On the other hand, the code below is good because code readers don't have to care about external variables out of the test case.
Good:
describe SomeModel, type: :model do
describe '#do_something' do
it 'gets true' do
expect(SomeModel.new.do_something(true)).to be true
end
it 'gets false' do # <-- It's obvious because `do_something` and its parameter are put into this test case
expect(SomeModel.new.do_something(false)).to be false
end
end
end
By the way, Testing on the Toilet: Tests Too DRY? Make Them DAMP! also explains helper functions. Helper functions are sometimes necessary to make tests readable. Yes, they are DRY codes, but I think it's good to go with them as long as they help us to reduce cognitive load. For example, take_screenshot is a good DRY and helpful since it's descriptive and meaningful; it's easy to comprehend just by seeing the method name.
That's what I wanted to say here. Please don't make your tests DRY excessively, or other developers, including you in the future, will have to use their energy to understand the DRY codes and get lost in why tests fail.