tdd - prática com rspec
DESCRIPTION
Prática de TDD baseada no livro RSpec Book. Código fonte inicial em https://github.com/dudumendes/tdd_aulas/tree/master/jogo_senhaTRANSCRIPT
Desenvolvimento Baseado em TestesRSpec - PráticaEduardo Mendes [email protected]
@dudumendes
Dicas com RSpec
@dudumendes
Executando spec
rspec arquivo.rb
executa um único spec
rspec path/para/meus/specs
executar todos os specs contidos no diretório
@dudumendes
rspec formatosFormatando para documentação
rspec path/para/meus/spec --format documentation
rspec path/para/meus/spec --format d
rspec path/para/meus/spec -f d
Gerando um arquivo html
rspec path/para/meus/spec -f html > relatorio.html
rspec path/para/meus/spec -f h > relatorio.html
@dudumendes
@dudumendes
Colorindo o resultadorspec spec --color
@dudumendes
TDD
@dudumendes
O que veremos?
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
Sempre refatorar na fase verde
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
Sempre refatorar na fase verde
Buscar sempre o cenário mais simples
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
Sempre refatorar na fase verde
Buscar sempre o cenário mais simples
Pequenos passos
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
Sempre refatorar na fase verde
Buscar sempre o cenário mais simples
Pequenos passos
Utilizar contextos para melhor compreensão dos testes
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
Sempre refatorar na fase verde
Buscar sempre o cenário mais simples
Pequenos passos
Utilizar contextos para melhor compreensão dos testes
Extrair métodos para tornar código mais claro
@dudumendes
O que veremos?Iniciar os testes baseados em cenários previamente definidos
Nunca codifique uma funcionalidade nova sem um teste falhando
Utilizar 01 expectativa por exemplo
Sempre refatorar na fase verde
Buscar sempre o cenário mais simples
Pequenos passos
Utilizar contextos para melhor compreensão dos testes
Extrair métodos para tornar código mais claro
Adicionar complexidade gradativamente
@dudumendes
TDD com RSpec
@dudumendes
IntroduçãoConstrução de um Jogo chamado Senha
Estrutura inicial disponibilizada no Github https://github.com/dudumendes/tdd_aulas/tree/master/jogo_senha
Specs separados dos fontes
Classes com nomes qualificados
Jogo SenhaUm Jogo que gera uma senha de 04 posições com os algarismos 1, 2, 3, 4 !O jogador tenta adivinhar a senha através de uma contra-senha !O Jogo é capaz de avaliar a contra-senha
@dudumendes
Jogo Senha
Uma contra-senha é avaliada através dos seguintes sinais e regras:
+ : um sinal de “positivo” é apresentado para cada valor correto na posição correta
- : um único sinal de “negativo” é apresentado para cada valor correto na posição errada
!
Precedência dos sinais: + > -
@dudumendes
Jogo SenhaExemplos de avaliação para a Senha: 1232
Contra-senha Avaliação1232 Parabens, fulano voce quebrou a senha!44442321143242321322
@dudumendes
Senha - estrutura
@dudumendes
github.com/dudumendes/tdd_aulas/ jogo_senha
@dudumendes
Funcionalidade: iniciar jogo Cenário 1 - Iniciar o jogo
Cenário: iniciar o jogo
Dado que eu ainda não estou jogando
Quando eu vir “Bem-vindo ao Senha”
Então eu espero ver “Informe jogador:”
@dudumendes
@dudumendes
“Nunca codifique uma funcionalidade nova
sem um teste falhando”
@dudumendes
O ciclo básico do TDD
Escrever um teste unitário
que falha
Fazer um código passar no teste
Refatorar
@dudumendes
require 'spec_helper' !module Senha describe Jogo do describe "#iniciar" do it "envia uma mensagem de boas-vindas" it "solicita pelo 1.o jogador" end end end
spec/senha/jogo_spec.rb
@dudumendes
module Senha class Jogo end end
lib/senha/jogo.rb
@dudumendes
executando o RSpec
@dudumendes
Adicionando algo
@dudumendes
Adicionando algo
O jogo será jogado no terminal
@dudumendes
Adicionando algo
O jogo será jogado no terminal
O jogo enviará mensagens para uma saída [output]
@dudumendes
Adicionando algo
O jogo será jogado no terminal
O jogo enviará mensagens para uma saída [output]
boas-vindas
@dudumendes
Adicionando algo
O jogo será jogado no terminal
O jogo enviará mensagens para uma saída [output]
boas-vindas
retornos sobre as tentativas de adivinhar a senha
@dudumendes
Adicionando algo
O jogo será jogado no terminal
O jogo enviará mensagens para uma saída [output]
boas-vindas
retornos sobre as tentativas de adivinhar a senha
nosso output será um dublê
@dudumendes
Adicionando algo
O jogo será jogado no terminal
O jogo enviará mensagens para uma saída [output]
boas-vindas
retornos sobre as tentativas de adivinhar a senha
nosso output será um dublê
faremos expectativas sobre este comportamento
@dudumendes
require 'spec_helper' !module Senha describe Jogo do describe "#iniciar" do it "envia uma mensagem de boas-vindas" do output = double('output') ! jogo = Jogo.new(output) output.should_receive(:puts).with("Bem-vindo ao Senha") ! jogo.iniciar end it "solicita pelo 1.o jogador"
end end end
@dudumendes
rspec spec -c -f -d
@dudumendes
module Senha class Jogo def initialize(output) @output = output end def iniciar end end end
@dudumendes
@dudumendes
module Senha class Jogo def initialize(output) @output = output end def iniciar @output.puts 'Bem-vindo ao Senha' end end end
@dudumendes
@dudumendes
Resolva a pendência
Resposta no próximo slide
@dudumendes
it "solicita pelo 1.o jogador" do output = double('output') jogo = Jogo.new(output) output.should_receive(:puts).with("Informe jogador:") jogo.iniciar end
@dudumendes
@dudumendes
module Senha class Jogo def initialize(output) @output = output end def iniciar @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end end end
@dudumendes
@dudumendes
02 exemplos falhandoOs doubles reagem exatamente da maneira como foram programados
1.º exemplo
“Bem-vindo ao Senha” e somente isso
2.º exemplo
“Informe jogador:” e somente isso
Possível solução
combinar as 02 coisas em um único exemplo
@dudumendes
@dudumendes
“01 expectativa por exemplo”
@dudumendes
“01 expectativa por exemplo”Se 02 expectativas falharem, só veremos a 1.ª
@dudumendes
02 expectativas em um 1 exemplo
Se ambas expectativas falharem, só veremos a 1.ª
01 expectativa por exemplo
Veremos ambas falharem
01 expectativa por exemplo
@dudumendes
método as_null_object
Informa ao double para responder somente às mensagens configuradas nas expectativas
as outras são ignoradas
baseado no padrão Null Object
@dudumendes!module Senha describe Jogo do describe "#iniciar" do it "envia uma mensagem de boas-vindas" do output = double('output').as_null_object jogo = Jogo.new(output) ! output.should_receive(:puts).with("Bem-vindo ao Senha") jogo.iniciar end ! it "solicita pelo 1.o jogador" do output = double('output').as_null_object jogo = Jogo.new(output) output.should_receive(:puts).with("Informe jogador:") jogo.iniciar end end end end
@dudumendes
@dudumendes
O ciclo básico do TDD
Escrever um teste unitário
que falha
Fazer um código passar no teste
Refatorar
@dudumendes
Refatorando“Refatoração é o processo de mudança de um sistema de software de tal forma que não se altere o comportamento externo do código e ainda melhore a sua estrutura interna”
Martin Fowler
Se alguma mudança fizé-lo falhar, é porque foi ela quem causou o problema
É possível retornar para o verde novamente
@dudumendes
@dudumendes
Refatorar na fase verde
@dudumendes
Refatorar na fase verdeRefatorar com confiança
@dudumendes
Refatorando
Buscar duplicações
na implementação
e nos exemplos
@dudumendes!module Senha describe Jogo do describe "#iniciar" do it "envia uma mensagem de boas-vindas" do output = double('output').as_null_object jogo = Jogo.new(output) ! output.should_receive(:puts).with("Bem-vindo ao Senha") jogo.iniciar end ! it "solicita pelo 1.o jogador" do output = double('output').as_null_object jogo = Jogo.new(output) output.should_receive(:puts).with("Informe jogador:") jogo.iniciar end end end end
@dudumendes
Crie o before
@dudumendes
before(:each) do @output = double('output').as_null_object @jogo = Jogo.new(@output) end ! it "envia uma mensagem de boas-vindas" do @output.should_receive(:puts).with("Bem-vindo ao Senha") @jogo.iniciar end ! it "solicita pelo 1.o jogador" do @output.should_receive(:puts).with("Informe jogador:") @jogo.iniciar end
@dudumendes
método let evitando os @
Se o bloco before é só para criar variáveis de instâncias com valores
utilize o let
!
let(:output) {double(‘output’).as_null_object }
@dudumendes
describe Jogo do describe "#iniciar" do let(:output) { double('output').as_null_object } let(:jogo) { Jogo.new(output) } it "envia uma mensagem de boas-vindas" do output.should_receive(:puts).with("Bem-vindo ao Senha") jogo.iniciar end ! it "solicita pelo 1.o jogador" do output.should_receive(:puts).with("Informe jogador:") jogo.iniciar end end end
@dudumendes
Funcionalidade o jogador submete uma contra-senha
O jogador submete uma contra-senha de 04 dígitos.
O jogo avalia a contra senha com sinais + e -
Para cada dígito na contra-senha que casa com um dígito na posição correta
a avaliação inclui um sinal de +
Para cada dígito na contra-senha que casa com um dígito, mas não na posição
a avaliação inclui um sinal de -
@dudumendes
Esquema do Cenário: o jogador informa a contra-senha
Dado que a senha é “<senha>”
Quando eu informar uma “<contra-senha>”
Então a avaliação deve ser “<avaliação>”
@dudumendes
Cenáriossem acertos
!
!
com 01 dígito correto
!
!
com 2 dígitos corretos
!
com 03 dígitos corretos
!
!
!
com todos corretos
senha contra-senha avaliacao
1234 5555
senha contra-senha avaliacao1234 1555 +1234 2555 -
senha contra-senha avaliacao1234 5254 ++1234 5154 +-1234 2545 --
senha contra-senha avaliacao1234 5234 +++1234 5134 ++-1234 5124 +--1234 5123 ---
senha contra-senha avaliacao1234 1234 ++++1234 1243 ++--1234 1423 +---1234 4321 ----
@dudumendes
Criação da senha
Vamos informar a senha na hora da chamada ao início do jogo
@dudumendes
it "envia uma mensagem de boas-vindas" do output.should_receive(:puts).with("Bem-vindo ao Senha") jogo.iniciar('1234') end !it "solicita pelo 1.o jogador" do ! output.should_receive(:puts).with("Informe jogador:") jogo.iniciar('1234') !end !
@dudumendes
@dudumendes
module Senha class Jogo def initialize(output) @output = output end def iniciar(senha) @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end end end
@dudumendes
Avaliação
@dudumendes
14 cenários identificados
Qual deles é o mais importante?
Por qual cenário começar?
@dudumendes
@dudumendes
“Utilize o cenário mais simples”
@dudumendes
“Utilize o cenário mais simples”Que permita progredir facilmente
@dudumendes
“Utilize o cenário mais simples”Que permita progredir facilmente
Pequenos passos
@dudumendes
Cenáriossem acertos
!
!
com 01 dígito correto
!
!
com 2 dígitos corretos
!
com 03 dígitos corretos
!
!
!
com todos corretos
senha contra-senha
avaliacao
1234 5555
senha contra-senha avaliacao1234 1555 +1234 2555 -
senha contra-senha avaliacao1234 5254 ++1234 5154 +-1234 2545 --
senha contra-senha avaliacao1234 5234 +++1234 5134 ++-1234 5124 +--1234 5123 ---
senha contra-senha avaliacao1234 1234 ++++1234 1243 ++--1234 1423 +---1234 4321 ----
@dudumendes
describe "#avaliar" do it "envia ‘’ quando receber ‘5555’" do end end
@dudumendes
@dudumendes
“Utilize contextos”
@dudumendes
“Utilize contextos”organizam seus testes
@dudumendes
“Utilize contextos”organizam seus testes
tornam-os mais compreensíveis
@dudumendes
describe "#avaliar" do ! context "sem acertos" do ! it "envia uma avaliacao com ''" do jogo.iniciar('1234') output.should_receive(:puts).with('') jogo.avaliar('5555') end ! end ! end
@dudumendes
@dudumendes
module Senha class Jogo def initialize(output) @output = output end def iniciar(senha) @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end def avaliar(contra_senha) end end end
@dudumendes
@dudumendes
Qual a solução mais simples?
@dudumendes
module Senha class Jogo def initialize(output) @output = output end def iniciar(senha) @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end def avaliar(contra_senha) @output.puts '' end end end
@dudumendes
@dudumendes
Próximo cenário?sem acertos
!
!
com 01 dígito correto
!
!
com 2 dígitos corretos
!
com 03 dígitos corretos
!
!
!
com todos corretos
senha contra-senha
avaliacao
1234 5555
senha contra-senha avaliacao1234 1555 +1234 2555 -
senha contra-senha avaliacao1234 5254 ++1234 5154 +-1234 2545 --
senha contra-senha avaliacao1234 5234 +++1234 5134 ++-1234 5124 +--1234 5123 ---
senha contra-senha avaliacao1234 1234 ++++1234 1243 ++--1234 1423 +---1234 4321 ----
@dudumendes
context "com 01 digito correto" do it "envia uma avaliacao com '-'" do jogo.iniciar('1234') output.should_receive(:puts).with('-') jogo.avaliar('2555') end end
@dudumendes
@dudumendesmodule Senha class Jogo def initialize(output) @output = output end def iniciar(senha) @senha = senha @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end def avaliar(contra_senha) if @senha.include?(contra_senha[0]) @output.puts '-' else @output.puts '' end end end end
@dudumendes
@dudumendes
O ciclo básico do TDD
Escrever um teste unitário
que falha
Fazer um código passar no teste
Refatorar para remover
duplicação
@dudumendesmodule Senha class Jogo def initialize(output) @output = output end def iniciar(senha) @senha = senha @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end def avaliar(contra_senha) if @senha.include?(contra_senha[0]) @output.puts '-' else @output.puts '' end end end end
@dudumendesmodule Senha class Jogo def initialize(output) @output = output end def iniciar(senha) @senha = senha @output.puts 'Bem-vindo ao Senha' @output.puts 'Informe jogador:' end def avaliar(contra_senha) if @senha.include?(contra_senha[0]) avalicao = '-' else avaliacao = '' end @output.puts avaliacao end end end
@dudumendes
Próximo cenário?sem acertos
!
!
com 01 dígito correto
!
!
com 2 dígitos corretos
!
com 03 dígitos corretos
!
!
!
com todos corretos
senha contra-senha
avaliacao
1234 5555
senha contra-senha avaliacao1234 1555 +1234 2555 -
senha contra-senha avaliacao1234 5254 ++1234 5154 +-1234 2545 --
senha contra-senha avaliacao1234 5234 +++1234 5134 ++-1234 5124 +--1234 5123 ---
senha contra-senha avaliacao1234 1234 ++++1234 1243 ++--1234 1423 +---1234 4321 ----
@dudumendes
context "com 01 digito exatamente correto" do it "envia uma avaliacao com '+'" do jogo.iniciar('1234') output.should_receive(:puts).with('+') jogo.avaliar('1555') end end
@dudumendes
@dudumendes
def avaliar(contra_senha) if @senha[0] == contra_senha[0] avaliacao = '+' elsif @senha.include?(contra_senha[0]) avaliacao = '-' else avaliacao = '' end @output.puts avaliacao end
@dudumendes
@dudumendes
O ciclo básico do TDD
Escrever um teste unitário
que falha
Fazer um código passar no teste
Refatorar para expressar
intenção
@dudumendes
Refatorar para expressar intenção
À medida que o projeto vai evoluindo
aparecem novas duplicações
Remover duplicação
melhorar o projeto
dar mais semântica ao código
@dudumendes
def avaliar(contra_senha) if @senha[0] == contra_senha[0] avaliacao = '+' elsif @senha.include?(contra_senha[0]) avaliacao = '-' else avaliacao = '' end @output.puts avaliacao end
As intenções estão claras?
@dudumendes
@dudumendes
“Extraia métodos”
@dudumendes
“Extraia métodos”elimina duplicação
@dudumendes
“Extraia métodos”elimina duplicação
introduz abstrações que expressam com mais clareza
a intenção do código
@dudumendes
Extrair Método
@dudumendes
Extrair Método• Contexto
• métodos muito longos
• lógicas de complexo entendimento
@dudumendes
Extrair Método• Contexto
• métodos muito longos
• lógicas de complexo entendimento
• Solução
• fracionar o método em métodos menores mais coesos
@dudumendes
Extrair Método• Contexto
• métodos muito longos
• lógicas de complexo entendimento
• Solução
• fracionar o método em métodos menores mais coesos
• Extração de comportamentos para novos métodos
@dudumendes
def init content_pane.layout(FlowLayout.new) movie_list = List.new(my_editor.movies) scroller = ScrollPane.new(movie_list) content_pane.add(scroller) movie_field = TextField.new(16) content_pane.add(movie_field) add_button = Button.new(“Add") .... end
@dudumendes
def init // set the layout content_pane.layout(FlowLayout.new) ! // create the list movie_list = List.new(my_editor.movies) scroller = ScrollPane.new(movie_list) content_pane.add(scroller) ! // create the field movie_field = TextField.new(16) content_pane.add(movie_field) ! // create theadd button add_button = Button.new(“Add") .... end
@dudumendes
def init setLayout initMovieList initMovieField initAddButton end def setLayout contentPane.layout(FlowLayout.new) end def initMovieList movie_list = List.new(my_editor.movies) scroller = ScrollPane.new(movie_list) content_pane.add(scroller) end def initMovieField movie_field = TextField.new(16) content_pane.add(movie_field) end def initAddButton addButton = Button.new(“Add") addButton.addActionListener(ActionListener()) {
@dudumendes
Extrair Método outro caso
Se um trecho de código duplicado diferentes do programa
Classe1
@dudumendes
Extrair Método outro caso
• Se as duplicatas de código devem permanecer sempre iguais, ou seja, uma vez que se realize uma alteração em uma delas, as demais devem refletir a alteração
Classe1
@dudumendes
Extrair Método outro caso
• Se as duplicatas de código devem permanecer sempre iguais, ou seja, uma vez que se realize uma alteração em uma delas, as demais devem refletir a alteração
Classe1
@dudumendes
def edit id = params[:id] @personagem = Personagem.find(id) //Mais código end !def create id = params[:id] @personagem = Personagem.find(id) //Mais código end
@dudumendes
Extraindo o método• Concentre o código que se repete em um único
lugar, por exemplo, em um método e leve as dependências para lá
@dudumendes
Extraindo o método• Concentre o código que se repete em um único
lugar, por exemplo, em um método e leve as dependências para lá
def edit id = params[:id] @personagem = Personagem.find(id) //Mais código end
@dudumendes
Extraindo o método• Concentre o código que se repete em um único
lugar, por exemplo, em um método e leve as dependências para lá
def edit id = params[:id] @personagem = Personagem.find(id) //Mais código end
def novo_metodo id = params[:id] @personagem = Personagem.find(id) //Mais código end
@dudumendes
def edit self.novo_metodo end !!def create self.novo_metodo end !!def novo_metodo id = params[:id] @personagem = Personagem.find(id) //Mais código end
@dudumendes
Extração de método no Senha
@dudumendes
def avaliar(contra_senha) if digito_exato?(contra_senha, 0) avaliacao = '+' ! elsif digito_correto?(contra_senha, 0) avaliacao = '-' ! else avaliacao = '' end @output.puts avaliacao ! end def digito_exato?(contra_senha, index) @senha[index] == contra_senha[index] end def digito_correto?(contra_senha, index) @senha.include?(contra_senha[index]) end
@dudumendes
@dudumendes
@dudumendes
“Adicione complexidade gradativamente”
@dudumendes
“Adicione complexidade gradativamente”
confiança ao programar
@dudumendes
Próximo cenário?sem acertos
!
!
com 01 dígito correto
!
!
com 2 dígitos corretos
!
com 03 dígitos corretos
!
!
!
com todos corretos
senha contra-senha
avaliacao
1234 5555
senha contra-senha avaliacao1234 1555 +1234 2555 -
senha contra-senha avaliacao1234 5254 ++1234 5154 +-1234 2545 --
senha contra-senha avaliacao1234 5234 +++1234 5134 ++-1234 5124 +--1234 5123 ---
senha contra-senha avaliacao1234 1234 ++++1234 1243 ++--1234 1423 +---1234 4321 ----
@dudumendes
! context "com 02 digitos corretos" do it "envia uma avaliacao com '--'" do jogo.iniciar('1234') output.should_receive(:puts).with('--') jogo.avaliar('2355') end end
@dudumendes
@dudumendes
Obtendo resultado
Como já foram realizadas algumas refatorações
o código já passa a nos ajudar
@dudumendes
def avaliar(contra_senha) avaliacao = '' (0..3).each do |index| ! if digito_exato?(contra_senha, index) avaliacao << '+' ! elsif digito_correto?(contra_senha, index) avaliacao << '-' ! end ! end @output.puts avaliacao end
@dudumendes
@dudumendes
Próximo cenário?sem acertos
!
!
com 01 dígito correto
!
!
com 2 dígitos corretos
!
com 03 dígitos corretos
!
!
!
com todos corretos
senha contra-senha
avaliacao
1234 5555
senha contra-senha avaliacao1234 1555 +1234 2555 -
senha contra-senha avaliacao1234 5254 ++1234 5154 +-1234 2545 --
senha contra-senha avaliacao1234 5234 +++1234 5134 ++-1234 5124 +--1234 5123 ---
senha contra-senha avaliacao1234 1234 ++++1234 1243 ++--1234 1423 +---1234 4321 ----
@dudumendes
context "com 01 digito correto e 01 digito exato (nesta ordem)" do it "envia uma avaliacao com '+-'" do jogo.iniciar('1234') output.should_receive(:puts).with('+-') jogo.avaliar('2535') end end
@dudumendes
@dudumendes
def avaliar(contra_senha) avaliacao = '' (0..3).each do |index| if digito_exato?(contra_senha, index) avaliacao << '+' end end (0..3).each do |index| if digito_correto?(contra_senha, index) avaliacao << '-' end end @output.puts avaliacao end
@dudumendes
@dudumendes
def digito_correto?(contra_senha, index) @senha.include?(contra_senha[index]) && !digito_exato?(contra_senha, index) end
@dudumendes
@dudumendes
Em seguida?
@dudumendes
Em seguida
Remover bad smells
Variáveis temporárias
Métodos longos estruturados
Classes com responsabilidades demais
Extrair classe
@dudumendes
O que vimos?
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
Refatorar na fase verde
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
Refatorar na fase verde
Utilizar o cenário mais simples
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
Refatorar na fase verde
Utilizar o cenário mais simples
Pequenos passos
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
Refatorar na fase verde
Utilizar o cenário mais simples
Pequenos passos
Utilizar contextos
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
Refatorar na fase verde
Utilizar o cenário mais simples
Pequenos passos
Utilizar contextos
Extrair métodos para tornar código mais claro
@dudumendes
O que vimos?Iniciar os testes baseados em cenários previamente
Nunca codifique uma funcionalidade nova sem um teste falhando
01 expectativa por exemplo
Refatorar na fase verde
Utilizar o cenário mais simples
Pequenos passos
Utilizar contextos
Extrair métodos para tornar código mais claro
Adicionar complexidade gradativamente
@dudumendes
Bibliografia
FOWLER, Martin. “Mocks aren’t Stubs”.
FOWLER, Martin; BECK, Kent; BRANT, John; Opdyke, William; ROBERTS, Don. Refactoring: Improving The Design of Existing Code.
CHELIMSKY, David. The RSpec Book. PragBook, 2011.