Figura 2.1: Ciclo red - green - refactor
O primeiro teste com RSpec
Na minha aula de estrutura de dados da Poli aprendi a implementar uma pilha.
Naquele tempo eu não conhecia TDD, então fiz na raça, sem testes (e em C). Hoje,
olhando pra trás, fica a curiosidade: como seria implementar aquela pilha, só que
com testes?
Hora de matar essa curiosidade!
Uma pilha (Stack) é uma estrutura de dados LIFO (last in, first out), ou seja, é
uma coleção de elementos na qual o último que você colocou é o primeiro a sair.
Vamos especificar esse comportamento em formato de teste.
Não se importe por enquanto com a sintaxe do RSpec, o código será simples o
bastante para que você possa entendê-lo mesmo sem nunca ter visto RSpec.
Vamos começar especificando o método push (empilha). Quando você empilhar
6
Casa do Código
Capítulo 2. Primeiros passos com RSpec e Cucumber
um elemento, então esse elemento deve poder ser visualizado no topo da pilha.
Figura 2.2: Pilha com elementos sendo empilhados
Vamos criar um arquivo chamado stack_spec.rb com o seguinte código, que
especificará esse comportamento:
describe
Stack do
describe "#push" do
it "puts an element at the top of the stack" do
stack = Stack.new
stack.push(1)
stack.push(2)
expect(stack.top).to eq(2)
end
end
end
Novamente, não se assuste com a sintaxe. Atente-se apenas ao fato de que esta-
mos chamando o método push para adicionar primeiro o elemento 1 e em seguida
o elemento 2 na pilha e por fim, indicamos que o topo da pilha deve conter o
elemento 2, seguindo assim a ideia de last in, first out.
Esse é um teste escrito com RSpec e para rodá-lo, precisamos antes instalá-lo,
através de sua gem. Para fazer a instalação, execute o seguinte comando no seu con-
sole:
$ gem install rspec
Com ele instalado, para rodar seus testes basta executar no seu console:
7
2.1. Olá RSpec
Casa do Código
$ rspec --color stack_spec.rb
Ao rodar o RSpec, o teste quebra, como esperado. Esse é o passo red, do ciclo
red - green - refactor. Ele quebrou porque até agora só implementamos o teste, não
implementamos nenhum código que o faça passar. Nesse momento, o importante é
ver que o teste quebrou e porquê ele quebrou. Após ter rodado o RSpec, você deve
ter visto uma mensagem de erro contendo a seguinte saída:
$ rspec --color stack_spec.rb
(...)
uninitialized constant Stack (NameError)
A mensagem de erro nos diz que o teste quebrou porque a constante Stack
ainda não foi definida. Ou seja, precisamos criar a classe Stack. Para simplificar,
escreva a definição da classe no mesmo arquivo stack_spec.rb de modo que ele
fique assim:
class Stack
end
describe Stack do
describe "#push" do
it "puts an element at the top of the stack" do
stack = Stack.new
stack.push(1)
stack.push(2)
expect(stack.top).to eq(2)
end
end
end
Ao rodar o RSpec agora, vemos o seguinte:
$ rspec --color stack_spec.rb
(...)
Failures:
8
Casa do Código
Capítulo 2. Primeiros passos com RSpec e Cucumber
1) Stack#push puts an element at the top of the stack
Failure/Error: stack.push(1)
NoMethodError:
undefined method `push' for #<Stack:0x007fa91b919b70>
Figura 2.3: Teste no vermelho
Evoluímos, mas o teste ainda quebrou e a mensagem de erro agora nos diz que
foi porque o método push ainda não está definido, precisamos implementar esse
método ainda.
Para implementar o método push, precisamos pensar no que ele irá fazer. Te-
mos que colocar um elemento dentro da pilha, de modo que o último item colocado
é o que ficará no topo da pilha. Como mecanismo para guardar os elementos, pode-
mos usar um Array e ir colocando os elementos dentro dele. Faça isso editando a
classe Stack do seguinte modo:
class Stack
def initialize
@elements = []
end
def push(element)
@elements << element
end
end
9
2.1. Olá RSpec
Casa do Código
# (...)
Com o método push implementado, vamos rodar o RSpec novamente:
$ rspec --color stack_spec.rb
(...)
Failures:
1) Stack#push puts an element at the top of the stack
Failure/Error: expect(stack.top).to eq(2)
NoMethodError:
undefined method `top' for #<Stack:0x007fce55c55e38 >
Evoluímos mais um pouco e o teste quebrou novamente. Não desanime! Dessa
vez a mensagem de erro foi diferente, o quer quer dizer que estamos progredindo.
Agora ela nos diz que o motivo da falha é que o método top ainda não foi imple-
mentado.
O que o método top precisa fazer é apenas retornar o último elemento que foi
empilhado. Para sabermos qual o último elemento adicionado na nossa pilha, va-
mos criar uma variável de instância chamada @last_element_index para salvar
o índice do último elemento, no array interno @elements, adicionado a pilha. Mo-
difique o código para seguir essa ideia e ficar assim:
class Stack
def initialize
@elements = []
@last_element_index = -1
end
def push(element)
@elements << element
@last_element_index += 1
end
def top
@elements[@last_element_index]
end
end
10
Casa do Código
Capítulo 2. Primeiros passos com RSpec e Cucumber