Evitando falso-positivo em testes: Não use a mesma informação
Digamos que eu tenha essa classe para testar:
require "date"
class User
attr_accessor :created_at, :started_at
def initialize(created_at = nil, started_at = nil)
@created_at = created_at
@started_at = started_at
end
def created_at_or_started_at
@started_at || @created_at
end
end
E que eu escrevi esse teste:
describe "User" do
context "when there is only created_at" do
subject do
User.new(Date.new(2018, 1, 1))
end
it "should return created_at" do
expect(subject.created_at_or_started_at).to eq Date.new(2018, 1, 1)
end
end
context "when there are created_at and started_at" do
subject do
User.new(Date.new(2018, 1, 1), Date.new(2018, 1, 1))
end
it "should return started_at" do
expect(subject.created_at_or_started_at).to eq Date.new(2018, 1, 1)
end
end
end
Se eu substituir o método created_at_or_started_at
com algo como:
def created_at_or_started_at
@created_at
end
Meus testes nunca vão quebrar.
Teste você mesmo, baixe este arquivo e rode os tests:
$ rspec user_spec.rb
..
Finished in 0.00476 seconds (files took 0.16384 seconds to load)
2 examples, 0 failures
Agora edite o arquivo user_spec.rb
que você acabou de baixar: mude o segundo context
para:
context "when there are created_at and started_at" do
subject do
User.new(Date.new(2018, 1, 1), Date.new(2018, 12, 31))
end
it "should return started_at" do
expect(subject.created_at_or_started_at).to eq Date.new(2018, 12, 31)
end
end
Se você rodar novamente, aí sim, o teste vai falhar: If you run again you will see if failing:
$ rspec user_spec.rb
.F
Failures:
1) User when there are created_at and started_at should return started_at
Failure/Error: expect(subject.created_at_or_started_at).to eq Date.new(2018, 12, 31)
expected: #<Date: 2018-12-31 ((2458484j,0s,0n),+0s,2299161j)>
got: #<Date: 2018-01-01 ((2458120j,0s,0n),+0s,2299161j)>
(compared using ==)
Diff:
@@ -1,2 +1,2 @@
-#<Date: 2018-12-31 ((2458484j,0s,0n),+0s,2299161j)>
+#<Date: 2018-01-01 ((2458120j,0s,0n),+0s,2299161j)>
# ./user_spec.rb:29:in `block (3 levels) in <top (required)>'
Finished in 0.02495 seconds (files took 0.16475 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./user_spec.rb:28 # User when there are created_at and started_at should return started_at
O principal ponto aqui é sempre usar valores diferentes para diferentes campos, desta forma você sempre vai ter certeza de qual campo está acessando.
#ProTip
Quando eu escrevo teste com Ruby on Rails eu normalmente escrevo algo como:
User.new(
created_at: 2.days.ago,
started_at: 2.days.from_now,
)
Veja que é muito mais fácil escrever 2.days.ago
ou 2.days.from_now
do que Date.new(YYYY, MM, DD)
.