Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testes Automatizados- Reduzindo os erros de manutenção no código

Testes Automatizados- Reduzindo os erros de manutenção no código

No início do aprendizado de programação utilizamos apenas testes manuais. Por muitas vezes esse procedimento de teste é mantido até o fim do curso e praticado em projetos do dia-a-dia. Projetos reais necessitam de alterações e melhorias constantes, testes manuais são insuficientes para permitir a agilidade e segurança de alteração do código ao programador. Hoje, testes automatizados são um padrão de excelência e profissionalismo com enormes benefícios para a longevidade de um projeto. Nessa palestra, nós vamos aprender sobre testes automatizados, as diferentes categorias existentes, além de ver exemplos práticos e os benefícios que eles trazem.

50e713934ed341675bf1fa73127ec260?s=128

Ulisses Almeida

October 31, 2013
Tweet

Transcript

  1. Boa noite!

  2. Quem sou eu? ulissesalmeida

  3. None
  4. None
  5. http://www.plataformatec.com.br

  6. Testes Automatizados Reduzindo erros de manutenção no código

  7. Hoje iremos estudar como o programador faz seus testes

  8. Na faculdade

  9. Exercício bacana

  10. Codificamos

  11. As ferramentas nos ajudam

  12. Porém na hora de usar o programa

  13. None
  14. None
  15. Minimizando esse risco

  16. Código modular

  17. Nomes significativos int a, b, fCont; float mTeZ(float b)

  18. Testar cedo e frequente

  19. Sucesso na entrega do exercício!

  20. Tá pronto! Valeu professor até semana que vem!

  21. Semana seguinte: novo exercício

  22. Sem evolução e manutenção do código antigo.

  23. Mas no dia-a-dia

  24. É todo dia

  25. Não trabalha sozinho

  26. Requisitos novos

  27. O código fica maior

  28. Dúvidas surgem

  29. Conflitos de requisitos e interesses

  30. Bugs novos e velhos

  31. Difícil adicionar algo novo

  32. Software Engineering Economics, Barry Boehm Só fica pior

  33. A culpa é...

  34. Software Engineering Economics, Barry Boehm Melhorias!

  35. Como o desenvolvedor fez os testes?

  36. Manualmente!

  37. Testes manuais são apagados

  38. Sujam o código fonte

  39. Não existe um padrão

  40. Trabalhoso de se repetir

  41. O desenvolvedor precisa melhorar seus testes!

  42. Como melhorar? • Automatizar os testes manuais • Um espaço

    no código fonte para escrever os testes • Uma forma padrão de escrever • Que seja simples de executar
  43. Automatizar um teste? Escrever código que confirma os resultados previstos

    do software.
  44. Desenvolvimento Ágil

  45. Ferramentas para todas linguagens RSpec Cucumber JUnit MSpec unittest PHPUnit

    SimpleTest Jasmine
  46. Vamos aprender escrever os testes

  47. Passo a passo

  48. Exemplo simples

  49. Quero um sistema de conta bancária

  50. Ferramentas

  51. Ruby • Uma linguagem dinâmica, open source com foco na

    simplicidade e na produtividade. Tem uma sintaxe elegante de leitura natural e fácil escrita. https://www.ruby-lang.org/pt/
  52. puts 'Olá mundo'

  53. TestUnit • Uma ferramenta de testes para ruby. • Segue

    o design xUnit criado por Kent Beck(XP e TDD)
  54. Criando o esboço do programa

  55. Saldo 0 Depósito de R$ 100 Saldo 100

  56. Saldo 100 Saque de R$ 80 Saldo 20

  57. conta_bancaria.rb saldo = 0 deposito = 100 saldo = saldo

    + deposito puts saldo
  58. terminal ruby conta_bancaria.rb 100

  59. conta_bancaria.rb def deposita(saldo, valor) return saldo + valor end def

    saca(saldo, valor) return saldo - valor end
  60. conta_bancaria.rb saldo = 0 saldo = deposita(saldo, 100) puts saldo

    saldo = saca(saldo, 80) puts saldo
  61. terminal ruby conta_bancaria.rb 100 20

  62. conta_bancaria.rb saldo = 0 saldo = deposita(saldo, 100) puts saldo

    saldo = saca(saldo, 50) puts saldo
  63. Ta pronto!

  64. Quero fazer transferência entre contas!

  65. conta_bancaria.rb def deposita(saldo, valor) return saldo + valor end def

    saca(saldo, valor) return saldo - valor end
  66. Not good :(

  67. conta_bancaria.rb class ContaBancaria def initialize(saldo) @saldo = saldo end end

  68. conta_bancaria.rb def saldo return @saldo end

  69. conta_bancaria.rb def deposita(valor) @saldo = @saldo + valor end

  70. conta_bancaria.rb def saca(valor) @saldo = @saldo - valor end

  71. Testar tudo novamente :/

  72. Vamos automatizar :D

  73. conta_bancaria_test.rb require 'test/unit' require 'conta_bancaria' class ContaBancariaTeste < Test::Unit::TestCase end

  74. conta_bancaria_test.rb def test_deposita conta = ContaBancaria.new(0) conta.deposita(100) assert_equal 100, conta.saldo

    end
  75. terminal ruby -I . conta_bancaria_test.rb 1 tests, 1 assertions, 0

    failures, 0 errors, 0 skips
  76. conta_bancaria_test.rb def test_saca conta = ContaBancaria.new(100) conta.saca(100) assert_equal 0, conta.saldo

    end
  77. terminal ruby -I . conta_bancaria_test.rb 2 tests, 2 assertions, 0

    failures, 0 errors, 0 skips
  78. conta_bancaria.rb def deposita(valor) @saldo = @saldo + valor + 1

    end
  79. terminal ruby -I . conta_bancaria_test.rb [1/2] ContaBancariaTeste#test_deposita = 0.00 s

    1) Failure: ContaBancariaTeste#test_deposita [conta_bancaria_test.rb:10]: <100> expected but was <101>. 2 tests, 2 assertions, 1 failures, 0 errors, 0 skips
  80. terminal ContaBancariaTeste#test_deposita: <100> expected but was <101>.

  81. None
  82. Testes unitários Testes de funções do código independente de outras

    partes do sistema
  83. A transferência

  84. Conta de Origem Saldo = 150 Transferência de R$ 50

    Conta de Destino Saldo = 200 Conta de Origem Saldo = 100 Conta de Destino Saldo = 250
  85. transferencia.rb class Transferencia def initialize(conta_origem, conta_destino) @conta_origem = conta_origem @conta_destino

    = conta_destino end end
  86. transferencia.rb def transfere(valor) @conta_destino.deposita(valor) @conta_origem.saca(valor) end

  87. transferencia_test.rb require 'test/unit' require 'conta_bancaria' require 'transferencia' class TransferenciaTest <

    Test::Unit::TestCase end
  88. transferencia_test.rb def test_transferencia conta_origem = ContaBancaria.new(150) conta_destino = ContaBancaria.new(200) transferencia

    = Transferencia.new( conta_origem, conta_destino ) transferencia.transfere(50) assert_equal 100, conta_origem.saldo assert_equal 250, conta_destino.saldo end
  89. transferencia.transfere(50) assert_equal 100, conta_origem.saldo assert_equal 250, conta_destino.saldo

  90. terminal ruby -I . transferencia_test.rb 1 tests, 2 assertions, 0

    failures, 0 errors, 0 skips
  91. Testes de integração Testes da interação entre as funções e

    objetos do sistema
  92. BUG! É possível ter saques maiores que o saldo!

  93. Abordagem diferente

  94. conta_bancaria_test.rb def test_saca_com_saldo_insuficiente conta = ContaBancaria.new(100) assert_raises(Exception) { conta.saca(200) }

    end
  95. terminal ruby -I . conta_bancaria_test.rb ContaBancariaTeste#test_saca_com_saldo_insuficiente Exception expected but nothing

    was raised. 3 tests, 3 assertions, 1 failures, 0 errors, 0 skips
  96. conta_bancaria.rb def saca(valor) if saldo >= valor @saldo = @saldo

    - valor else raise Exception, 'Saldo insuficiente' end end
  97. terminal ruby -I . conta_bancaria_test.rb 3 tests, 3 assertions, 0

    failures, 0 errors, 0 skips
  98. Corrigimos o bug, garantimos que ele não volte

  99. Mas ainda temos a transferência!

  100. transferencia_test.rb def test_transferencia_origem_sem_saldo conta_origem = ContaBancaria.new(150) conta_destino = ContaBancaria.new(200) transferencia

    = Transferencia.new( conta_origem, conta_destino ) assert !transferencia.transfere(200) assert_equal 150, conta_origem.saldo assert_equal 200, conta_destino.saldo end
  101. transferencia_test.rb assert !transferencia.transfere(200) assert_equal 150, conta_origem.saldo assert_equal 200, conta_destino.saldo

  102. terminal ruby -I . transferencia_test.rb TransferenciaTest#test_transferencia_origem_sem_saldo: Exception: Saldo insuficiente 3

    tests, 3 assertions, 0 failures, 1 errors, 0 skips
  103. transferencia.rb def transfere(valor) @conta_destino.deposita(valor) @conta_origem.saca(valor) rescue Exception return false end

  104. terminal ruby -I . transferencia_test.rb TransferenciaTest#test_transferencia_origem_sem_saldo: <200> expected but was

    <400>. 2 tests, 5 assertions, 1 failures, 0 errors, 0 skips
  105. None
  106. transferencia_test.rb assert_equal 200, conta_destino.saldo

  107. transferencia.rb @conta_destino.deposita(valor) @conta_origem.saca(valor)

  108. transferencia.rb @conta_origem.saca(valor) @conta_destino.deposita(valor)

  109. terminal ruby -I . transferencia_test.rb 2 tests, 5 assertions, 0

    failures, 0 errors, 0 skips
  110. Descobrimos um bug e garantimos que não volte

  111. Melhorando o design

  112. The value returned by a Ruby method is the value

    of the last expression evaluated, so we can get rid of the return statement altogether. http://ruby-doc.com/docs/ProgrammingRuby/
  113. def saldo return @saldo end def transfere(valor) @conta_origem.saca(valor) @conta_destino.deposita(valor) rescue

    Exception return false end
  114. Você teria coragem de remover?

  115. Não mexa no que está funcionando

  116. Mas com testes automatizados

  117. É trivial checar se o sistema continua funcionando

  118. def saldo @saldo end def transfere(valor) @conta_origem.saca(valor) @conta_destino.deposita(valor) rescue Exception

    false end
  119. terminal ruby -I . conta_bancaria_test.rb 3 tests, 3 assertions, 0

    failures, 0 errors, 0 skips ruby -I . transferencia_test.rb 2 tests, 5 assertions, 0 failures, 0 errors, 0 skips
  120. Here we've defined three accessor methods to return the values

    of the three instance attributes. Because this is such a common idiom, Ruby provides a convenient shortcut: attr_reader creates these accessor methods for you. http://ruby-doc.com/docs/ProgrammingRuby/
  121. def saldo @saldo end attr_reader :saldo

  122. terminal ruby -I . conta_bancaria_test.rb 3 tests, 3 assertions, 0

    failures, 0 errors, 0 skips ruby -I . transferencia_test.rb 2 tests, 5 assertions, 0 failures, 0 errors, 0 skips
  123. Temos segurança de mudar

  124. Pois é rápido verificar

  125. Sistemas possuem interface

  126. É possível automatizar! visit root_path click_link 'Sign up' within('form') do

    fill_in 'Name', with: 'Billy' fill_in 'Email', with: 'billy@mail.com' fill_in 'Password', with: 'strong_password' fill_in 'Confirm password', with: 'strong_password' click_button('Sign up!') end
  127. Testes de aceitação Testes do ponto de vista do usuário

  128. Você não trabalha sozinho

  129. Servidores de testes Usando os testes como apoio para comunicação

    da equipe
  130. Servidor dedicado a executar os testes

  131. Concluindo...

  132. Os testes automatizados

  133. Descrevem o comportamento do software

  134. São executáveis

  135. Contribuem para

  136. Reduzir o número de bugs

  137. Adição de melhorias

  138. Comunicação

  139. Velocidade de desenvolvimento

  140. Time is money!

  141. Cuidado • Devem ser mantidos com zelo • Não removem

    a necessidade de QA e testes manuais
  142. Exemplos https://github.com/ ulissesalmeida/bank- account-sample

  143. Slides https://speakerdeck.com/ ulissesalmeida

  144. Testes te dão confiança para mudança!

  145. Referências • https://www.ruby-lang.org • http://rubyonrails.org/ • http://www.casadocodigo.com.br/products/livro- cucumber-rspec-tdd-bdd

  146. Referências • http://pragprog.com/book/jvrails2/crafting-rails-4- applications • http://www.amazon.com/Clean-Code-Handbook- Software-Craftsmanship/dp/0132350882 • http://en.wikipedia.org/wiki/Test_automation

  147. Obrigado!