TDD - Prática com RSpec

1.183 visualizações

Publicada em

Prática de TDD baseada no livro RSpec Book. Código fonte inicial em https://github.com/dudumendes/tdd_aulas/tree/master/jogo_senha

Publicada em: Tecnologia
1 comentário
1 gostou
Estatísticas
Notas
Sem downloads
Visualizações
Visualizações totais
1.183
No SlideShare
0
A partir de incorporações
0
Número de incorporações
3
Ações
Compartilhamentos
0
Downloads
34
Comentários
1
Gostaram
1
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

TDD - Prática com RSpec

  1. 1. Desenvolvimento Baseado em Testes RSpec - Prática Eduardo Mendes edumendes@gmail.com
  2. 2. @dudumendes Dicas com RSpec
  3. 3. @dudumendes Executando spec rspec arquivo.rb executa um único spec rspec path/para/meus/specs executar todos os specs contidos no diretório
  4. 4. @dudumendes rspec formatos Formatando 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
  5. 5. @dudumendes
  6. 6. @dudumendes Colorindo o resultado rspec spec --color
  7. 7. @dudumendes TDD
  8. 8. @dudumendes O que veremos?
  9. 9. @dudumendes O que veremos? Iniciar os testes baseados em cenários previamente definidos
  10. 10. @dudumendes O que veremos? Iniciar os testes baseados em cenários previamente definidos Nunca codifique uma funcionalidade nova sem um teste falhando
  11. 11. @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
  12. 12. @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
  13. 13. @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
  14. 14. @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
  15. 15. @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
  16. 16. @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
  17. 17. @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
  18. 18. @dudumendes TDD com RSpec
  19. 19. @dudumendes Introdução Construçã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
  20. 20. Jogo Senha Um 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 contrasenha
  21. 21. @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: + > -
  22. 22. @dudumendes Jogo Senha Exemplos de avaliação para a Senha: 1232 Contra-senha Avaliação 1232 Parabens, fulano voce quebrou a senha! 4444 2321 1432 4232 1322
  23. 23. @dudumendes Senha - estrutura
  24. 24. @dudumendes github.com/dudumendes/tdd_aulas/ jogo_senha
  25. 25. @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:”
  26. 26. @dudumendes
  27. 27. @dudumendes “Nunca codifique uma funcionalidade nova sem um teste falhando”
  28. 28. @dudumendes O ciclo básico do TDD Escrever um teste unitário que falha Fazer um código passar no teste Refatorar
  29. 29. @dudumendes spec/senha/jogo_spec.rb 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
  30. 30. @dudumendes lib/senha/jogo.rb module Senha class Jogo end end
  31. 31. @dudumendes executando o RSpec
  32. 32. @dudumendes Adicionando algo
  33. 33. @dudumendes Adicionando algo O jogo será jogado no terminal
  34. 34. @dudumendes Adicionando algo O jogo será jogado no terminal O jogo enviará mensagens para uma saída [output]
  35. 35. @dudumendes Adicionando algo O jogo será jogado no terminal O jogo enviará mensagens para uma saída [output] boas-vindas
  36. 36. @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
  37. 37. @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ê
  38. 38. @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
  39. 39. @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
  40. 40. rspec spec -c -f -d @dudumendes
  41. 41. @dudumendes module Senha class Jogo def initialize(output) @output = output end def iniciar end end end
  42. 42. @dudumendes
  43. 43. @dudumendes module Senha class Jogo def initialize(output) @output = output end def iniciar @output.puts 'Bem-vindo ao Senha' end end end
  44. 44. @dudumendes
  45. 45. @dudumendes Resolva a pendência Resposta no próximo slide
  46. 46. @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
  47. 47. @dudumendes
  48. 48. @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
  49. 49. @dudumendes
  50. 50. @dudumendes 02 exemplos falhando Os 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
  51. 51. @dudumendes
  52. 52. @dudumendes “01 expectativa por exemplo”
  53. 53. @dudumendes “01 expectativa por exemplo” Se 02 expectativas falharem, só veremos a 1.ª
  54. 54. @dudumendes 01 expectativa por exemplo 02 expectativas em um 1 exemplo Se ambas expectativas falharem, só veremos a 1.ª 01 expectativa por exemplo Veremos ambas falharem
  55. 55. @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
  56. 56. @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
  57. 57. @dudumendes
  58. 58. @dudumendes O ciclo básico do TDD Escrever um teste unitário que falha Fazer um código passar no teste Refatorar
  59. 59. @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
  60. 60. @dudumendes
  61. 61. @dudumendes Refatorar na fase verde
  62. 62. @dudumendes Refatorar na fase verde Refatorar com confiança
  63. 63. @dudumendes Refatorando Buscar duplicações na implementação e nos exemplos
  64. 64. @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
  65. 65. @dudumendes Crie o before
  66. 66. @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
  67. 67. @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 }
  68. 68. @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
  69. 69. @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 -
  70. 70. @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>”
  71. 71. @dudumendes Cenários sem acertos senha ! 1234 ! contra-senha com 03 dígitos corretos avaliacao 5555 com 01 dígito correto senha ! 1234 ! 1234 avaliacao contra-senha 1555 + 2555 - senha !1234 contra-senha avaliacao 5234 +++ 1234 ! 1234 5134 ++- 5124 +-- !1234 5123 --- com todos corretos senha com 2 dígitos corretos senha ! 1234 contra-senha avaliacao 5254 ++ 1234 5154 +- 1234 2545 -- contra-senha avaliacao 1234 1234 ++++ 1234 1243 ++-- 1234 1423 +--- 1234 4321 ----
  72. 72. @dudumendes Criação da senha Vamos informar a senha na hora da chamada ao início do jogo
  73. 73. @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 !
  74. 74. @dudumendes
  75. 75. @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
  76. 76. @dudumendes Avaliação
  77. 77. @dudumendes 14 cenários identificados Qual deles é o mais importante? Por qual cenário começar?
  78. 78. @dudumendes
  79. 79. @dudumendes “Utilize o cenário mais simples”
  80. 80. @dudumendes “Utilize o cenário mais simples” Que permita progredir facilmente
  81. 81. @dudumendes “Utilize o cenário mais simples” Que permita progredir facilmente Pequenos passos
  82. 82. @dudumendes Cenários sem acertos senha ! 1234 ! contrasenha 5555 com 03 dígitos corretos avaliacao com 01 dígito correto senha ! 1234 ! 1234 avaliacao contra-senha 1555 + 2555 - senha !1234 contra-senha avaliacao 5234 +++ 1234 ! 1234 5134 ++- 5124 +-- !1234 5123 --- com todos corretos senha com 2 dígitos corretos senha ! 1234 contra-senha avaliacao 5254 ++ 1234 5154 +- 1234 2545 -- contra-senha avaliacao 1234 1234 ++++ 1234 1243 ++-- 1234 1423 +--- 1234 4321 ----
  83. 83. @dudumendes describe "#avaliar" do it "envia ‘’ quando receber ‘5555’" do end end
  84. 84. @dudumendes
  85. 85. @dudumendes “Utilize contextos”
  86. 86. @dudumendes “Utilize contextos” organizam seus testes
  87. 87. @dudumendes “Utilize contextos” organizam seus testes tornam-os mais compreensíveis
  88. 88. @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
  89. 89. @dudumendes
  90. 90. @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
  91. 91. @dudumendes
  92. 92. @dudumendes Qual a solução mais simples?
  93. 93. @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
  94. 94. @dudumendes
  95. 95. @dudumendes Próximo cenário? sem acertos senha ! 1234 ! com 03 dígitos corretos contrasenha 5555 avaliacao com 01 dígito correto senha ! 1234 ! 1234 avaliacao contra-senha 1555 + 2555 - senha !1234 contra-senha avaliacao 5234 +++ 1234 ! 1234 5134 ++- 5124 +-- !1234 5123 --- com todos corretos senha com 2 dígitos corretos senha ! 1234 contra-senha avaliacao 5254 ++ 1234 5154 +- 1234 2545 -- contra-senha avaliacao 1234 1234 ++++ 1234 1243 ++-- 1234 1423 +--- 1234 4321 ----
  96. 96. @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
  97. 97. @dudumendes
  98. 98. module 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
  99. 99. @dudumendes
  100. 100. @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
  101. 101. module 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
  102. 102. module 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
  103. 103. @dudumendes Próximo cenário? sem acertos senha ! 1234 ! com 03 dígitos corretos contrasenha 5555 avaliacao com 01 dígito correto senha ! 1234 ! 1234 avaliacao contra-senha 1555 + 2555 - senha !1234 contra-senha avaliacao 5234 +++ 1234 ! 1234 5134 ++- 5124 +-- !1234 5123 --- com todos corretos senha com 2 dígitos corretos senha ! 1234 contra-senha avaliacao 5254 ++ 1234 5154 +- 1234 2545 -- contra-senha avaliacao 1234 1234 ++++ 1234 1243 ++-- 1234 1423 +--- 1234 4321 ----
  104. 104. @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
  105. 105. @dudumendes
  106. 106. @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
  107. 107. @dudumendes
  108. 108. @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
  109. 109. @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
  110. 110. @dudumendes As intenções estão claras? 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
  111. 111. @dudumendes
  112. 112. @dudumendes “Extraia métodos”
  113. 113. @dudumendes “Extraia métodos” elimina duplicação
  114. 114. @dudumendes “Extraia métodos” elimina duplicação introduz abstrações que expressam
 com mais clareza
 a intenção do código
  115. 115. @dudumendes Extrair Método
  116. 116. @dudumendes Extrair Método • Contexto • métodos muito longos • lógicas de complexo entendimento
  117. 117. @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
  118. 118. @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
  119. 119. @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
  120. 120. @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
  121. 121. 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
  122. 122. @dudumendes Extrair Método outro caso Se um trecho de código duplicado diferentes do programa Classe1
  123. 123. @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
  124. 124. @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
  125. 125. @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
  126. 126. @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á
  127. 127. @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
  128. 128. @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
  129. 129. @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
  130. 130. @dudumendes Extração de método no Senha
  131. 131. @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
  132. 132. @dudumendes
  133. 133. @dudumendes
  134. 134. @dudumendes “Adicione complexidade gradativamente”
  135. 135. @dudumendes “Adicione complexidade gradativamente” confiança ao programar
  136. 136. @dudumendes Próximo cenário? sem acertos senha ! 1234 ! com 03 dígitos corretos contrasenha 5555 avaliacao com 01 dígito correto senha ! 1234 ! 1234 avaliacao contra-senha 1555 + 2555 - senha !1234 contra-senha avaliacao 5234 +++ 1234 ! 1234 5134 ++- 5124 +-- !1234 5123 --- com todos corretos senha com 2 dígitos corretos senha ! 1234 contra-senha avaliacao 5254 ++ 1234 5154 +- 1234 2545 -- contra-senha avaliacao 1234 1234 ++++ 1234 1243 ++-- 1234 1423 +--- 1234 4321 ----
  137. 137. @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
  138. 138. @dudumendes
  139. 139. @dudumendes Obtendo resultado Como já foram realizadas algumas refatorações o código já passa a nos ajudar
  140. 140. @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
  141. 141. @dudumendes
  142. 142. @dudumendes Próximo cenário? sem acertos senha ! 1234 ! com 03 dígitos corretos contrasenha 5555 avaliacao com 01 dígito correto senha ! 1234 ! 1234 avaliacao contra-senha 1555 + 2555 - senha !1234 contra-senha avaliacao 5234 +++ 1234 ! 1234 5134 ++- 5124 +-- !1234 5123 --- com todos corretos senha com 2 dígitos corretos senha ! 1234 contra-senha avaliacao 5254 ++ 1234 5154 +- 1234 2545 -- contra-senha avaliacao 1234 1234 ++++ 1234 1243 ++-- 1234 1423 +--- 1234 4321 ----
  143. 143. @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
  144. 144. @dudumendes
  145. 145. @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
  146. 146. @dudumendes
  147. 147. @dudumendes def digito_correto?(contra_senha, index) @senha.include?(contra_senha[index]) && !digito_exato?(contra_senha, index) end
  148. 148. @dudumendes
  149. 149. @dudumendes Em seguida?
  150. 150. @dudumendes Em seguida Remover bad smells Variáveis temporárias Métodos longos estruturados Classes com responsabilidades demais Extrair classe
  151. 151. @dudumendes O que vimos?
  152. 152. @dudumendes O que vimos? Iniciar os testes baseados em cenários previamente
  153. 153. @dudumendes O que vimos? Iniciar os testes baseados em cenários previamente Nunca codifique uma funcionalidade nova sem um teste falhando
  154. 154. @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
  155. 155. @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
  156. 156. @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
  157. 157. @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
  158. 158. @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
  159. 159. @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
  160. 160. @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
  161. 161. @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.

×