analisando um exemplo de quando podemos usar o before hook para reduzir a
duplicação de código dos nossos testes.
4.1. Reduzindo duplicação com hooks do RSpec
Casa do Código
Usando o before hook para reduzir duplicação
Imagine que você está escrevendo um jogo. Parte da especificação desse jogo diz
que, quando o jogador está na última fase, se ele acertar o alvo, o jogo deve fazer as seguintes ações:
parabenizar o jogador;
setar o pontuação para 100.
Como bom praticante de TDD, antes de começar a desenvolver essa funcionali-
dade, você especifica esse comportamento com a seguinte estrutura de testes:
describe Game, "in the final phase" do
context "when the player hits the target" do
it "congratulates the player"
it "sets the score to 100"
end
end
Antes de continuarmos falando sobre os testes em si, vamos analisar algumas
novidades nele.
A primeira novidade é a string sendo passada como segundo argumento do mé-
todo describe:
describe Game, "in the final phase"
Como vimos no capítulo 3, o método describe serve para agrupar os testes de
modo semântico. A forma mais simples de agrupar os seus testes é por classe. No
entanto, há outros modos. No código que vimos, estamos agrupando nossos testes
por classe e um determinado estado do objeto dessa classe, no caso, o estado em que
o game está na última fase. Uma dos benefícios de utilizar essa string como segundo
argumento é o modo como ela fica no output de execução dos nossos testes quando
executamos o RSpec com o formato de saída documentation :
$ rspec --format documentation hooks_spec.rb
Game in the final phase
when the player hits the target
congratulates the player
sets the score to 100
60
Casa do Código
Capítulo 4. Organização, refatoração e reuso de testes com o RSpec
A segunda novidade que fizemos nesse teste é o uso do método context. Esse
método é apenas um alias do método describe e também serve para agrupar nos-
sos testes de forma semântica. Nesse caso preferimos usar o context porque a
leitura dele nesse contexto fica melhor do que usar o método describe. Compare
ambos os modos a seguir, primeiro usando context:
describe Game, "in the final phase"
do
context "when the player hits the target" do
E agora usando o describe:
describe Game, "in the final phase" do
describe "when the player hits the target" do
Explicadas as novidades, vamos continuar a trabalhar nos nossos testes. Vamos
começar escrevendo o primeiro:
context "when the player hits the target" do
it "congratulates the player"
# (...)
O setup desse teste envolve criar um objeto game e colocá-lo na fase final:
context "when the player hits the target" do
it "congratulates the player" do
game = Game.new
game.phase = :final
end
# (...)
end
O resto do teste envolve verificar que dado esse setup, quando o jogador acertar
o alvo, o jogo deve dar parabéns para o jogador:
context "when the player hits the target" do
it "congratulates the player" do
game = Game.new
game.phase = :final
game.player_hits_target
61
4.1. Reduzindo duplicação com hooks do RSpec
Casa do Código
expect(game.output).to eq("Congratuations!")
end
# (...)
end
Beleza, esse teste já está pronto. Vamos pular a parte de escrever o código para
fazer esse teste passar, porque não é o foco agora, vamos escrever o próximo teste.
O próximo teste é o:
context "when the player hits the target" do
# (...)
it "sets the score to 100"
end
As fases de setup e exercício desse teste são iguais a do teste anterior, devemos
criar um jogo na fase final e depois fazer com que o jogador acerte o alvo:
context "when the player hits the target" do
# (...)
it "sets the score to 100" do
game = Game.new
game.phase = :final
game.player_hits_target
end
end
A única parte que muda para esse teste é a etapa de verificação, onde queremos
verificar que a pontuação do jogo fica em 100:
context "when the player hits the target" do
# (...)
it "sets the score to 100" do
game = Game.new
game.phase = :final
game.player_hits_target
62
Casa do Código
Capítulo 4. Organização, refatoração e reuso de testes com o RSpec
expect(game.score).to eq(100)
end
end
Agora vamos analisar como ficou o arquivo de testes inteiro depois de termos
escrito os dois testes:
describe Game, "in the final phase" do
context "when the player hits the target" do
it "congratulates the player" do
game = Game.new
game.phase = :final
game.player_hits_target
expect(game.output).to eq("Congratuations!")
end
it "sets the score to 100" do
game = Game.new
game.phase = :final
game.player_hits_target
expect(game.score).to eq(100)
end
end
end
Perceba que existe duplicação entre os testes. Assim como você segue o DRY
(dont repeat yourself ) no seu código de produção, você também pode usar a mesma
idéia no código dos seus testes. O RSpec facilita a redução de duplicação através do
before hook. O before é um método do RSpec para o qual você pode passar um
bloco de código que vai ser executado antes de cada teste ou antes de todos os testes: before(:each) do