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

Testes automatizados e a prática antes da teoria

5a90a67fa1a92e6a4b605cfd8da5e375?s=47 Lucas Mazza
February 24, 2018

Testes automatizados e a prática antes da teoria

Escrever testes automáticos é uma prática bem estabelecida na comunidade Ruby, mas o quão bons são os testes que escrevemos? Na correria do dia a dia, estamos testando de forma efetiva ou só escrevendo mais código? Nesta palestra vamos ver alguns vícios e más práticas tradicionais de projetos Ruby, como podemos evitá-los e escrever testes melhores, e quais mudanças de pensando e práticas podemos adotar para aprimorar a nossa escrita de testes de software.

5a90a67fa1a92e6a4b605cfd8da5e375?s=128

Lucas Mazza

February 24, 2018
Tweet

Transcript

  1. Testes automatizados & a prática antes da teoria

  2. @lucasmazza http://afterhours.io

  3. https://magnetis.workable.com

  4. !

  5. testes & ruby?

  6. testes & rspec?

  7. None
  8. None
  9. #1 Não temos uma definição do que é um bom

    teste
  10. #2 É muito fácil escrever testes ruins

  11. “Estou testando ou apenas escrevendo código?”

  12. “To fix these issues and end up with tests (and

    a testing process) that actually work for us, we need to reconnect with the underlying needs that originally drove us to write tests.” Sarah Mei - Five Factor Testing https://www.devmynd.com/blog/five-factor-testing/
  13. #1 Não temos uma definição do que é um bom

    teste
  14. DDD Hexagonal REST SOLID CQRS Event Sourcing DRY

  15. ?!?

  16. xUnit

  17. xUnit xUnit Test Patterns http://xunitpatterns.com

  18. Setup Exercise Verify Teardown

  19. Arrange Act Assert Setup Exercise Verify Teardown

  20. Bons testes…

  21. Bons testes… 1. Verificam que o código funciona como esperado

  22. Bons testes… 1. Verificam que o código funciona como esperado

    2. Previnem regressões
  23. Bons testes… 1. Verificam que o código funciona como esperado

    2. Previnem regressões 3. Documentam a implementação atual
  24. Bons testes… 1. Verificam que o código funciona como esperado

    2. Previnem regressões 3. Documentam a implementação atual 4. Servem como guias para o seu design
  25. Bons testes… 1. Verificam que o código funciona como esperado

    2. Previnem regressões 3. Documentam a implementação atual 4. Servem como guias para o seu design 5. Ajudam refatorações
  26. Bons testes… 1. Verificam que o código funciona como esperado

    2. Previnem regressões 3. Documentam a implementação atual 4. Servem como guias para o seu design 5. Ajudam refatorações
  27. Bons testes… 1. Verificam que o código funciona como esperado

    2. Previnem regressões 3. Documentam a implementação atual 4. Servem como guias para o seu design 5. Ajudam refatorações
  28. #2 É muito fácil escrever testes ruins

  29. ué !?

  30. (╯°□°)╯︵ ┻━┻ AAA Frameworks

  31. (╯°□°)╯︵ ┻━┻ AAA Devs

  32. É muito fácil… Abusar de DSLs e DRY e escrever

    testes muito acoplados e complicados de ler.
  33. É muito fácil… Abusar de DSLs e DRY e escrever

    testes muito acoplados e complicados de ler.
  34. Context "Comum" do def faz; objeto.faz; end teste "faz alguma

    coisa" do faz # ... end end Context “Um pouco diferente" do def dep2; end teste "faz alguma coisa um pouco diferente" do objeto.faz # ... end end end
  35. Context "Comum" do def faz; objeto.faz; end teste "faz alguma

    coisa" do faz # ... end end Cenario “Um pouco diferente" do def dep2; end teste "faz alguma coisa um pouco diferente" do objeto.faz # ... end end end
  36. class CasoDeTeste def dep1; end def dep2; end def objeto;

    Coisa.new(dep1, dep2); end Cenario “Um pouco diferente" do def dep2; end teste "faz alguma coisa um pouco diferente" do objeto.faz # ... end end end
  37. Cenario "Comum" do def faz; objeto.faz; end teste "faz alguma

    coisa" do faz # ... end end Cenario “Um pouco diferente" do def dep2; end teste "faz alguma coisa um pouco diferente" do objeto.faz # ... end end end
  38. None
  39. 1. Relação teste/dependências não é explícita

  40. 1. Relação teste/dependências não é explícita 2. Mudanças nas dependências

    impactam vários testes
  41. 1. Relação teste/dependências não é explícita 2. Mudanças nas dependências

    impactam vários testes 3. subject não é um verbo
  42. 1. Relação teste/dependências não é explícita 2. Mudanças nas dependências

    impactam vários testes 3. subject não é um verbo 4. Volume de dependências fica escondido
  43. ➖ ➕ Duplicação Acoplamento

  44. ➕ ➖ Duplicação Acoplamento

  45. ✔ ✔ Duplicação Acoplamento

  46. Cenario "ABC" do teste "faz alguma coisa" do dep1 =

    ??? dep2 = ??? objeto = Coisa.new(dep1, dep2) objeto.faz # ... end end Cenario "DEF" do teste "faz alguma coisa um pouco diferente" do dep1 = ??? dep2 = ??? objeto = Coisa.new(dep1, dep2) objeto.faz # ... end end
  47. Cenario "ABC" do teste "faz alguma coisa" do dep1 =

    ??? dep2 = ??? objeto = Coisa.new(dep1, dep2) objeto.faz # ... end end Cenario "DEF" do teste "faz alguma coisa um pouco diferente" do dep1 = ??? dep2 = ??? objeto = Coisa.new(dep1, dep2) objeto.faz # ... end end def cria_coisa(dep1: dep1padrao, dep2: dep2padrao) Coisa.new(dep1, dep2) end def dep1padrao; end def dep2padrao; end
  48. SETUP System under test Exercise

  49. É muito fácil… Exagerar no uso de mocks e injeção

    de dependências sem identificar problemas no design do seu software
  50. class CasoDeTeste def dep1_1; mock(faz: 'alguma-coisa'); end def dep1_2; mock(faz:

    'outra-coisa'); end def dep1; Dep1.new(dep1_1, dep1_2); end def dep2; mock(pega: dep1_2); end def sistema; Sistema.new(dep1, dep2, dep1_1); end teste "alguma coisa" do # ... end end
  51. Sistema DEP 1 DEP 2 DEP 1-1 DEP 1-2

  52. None
  53. Não simule o que não é seu

  54. 1. Dependências externas

  55. 1. Dependências externas 2. Sistemas externos (oi VCR)

  56. 1. Dependências externas 2. Sistemas externos (oi VCR) 3. Dependências

    de dependências
  57. None
  58. None
  59. Dependência externa Dependência INTERNA

  60. Classe 1 Collab HTTP Mocks

  61. Classe 1 Adapter Mock impl testes execução

  62. Adapter HTTP testes

  63. Classe 2 Adapter Mock impl testes execução

  64. Classe 3 Adapter Mock impl testes execução

  65. Adapter HTTP testes

  66. Não simule o que está sendo testado

  67. Deu trabalho pra simular? Revise a sua API

  68. http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ “Mocks/stubs do not remove the need to define an

    explicit interface between your components (modules, classes, whatever)” José Valim, 2015
  69. É muito fácil… Escrever asserções/verificações que não explicam bem quando

    as coisas falham
  70. # Running: ................................................................................... .........................F........................................................ Finished in 0.012428s, 13276.4725 runs/s, 13276.4725

    assertions/s. 1) Failure: BugTest#test_140 [foo.rb:21]: Expected false to be truthy. 165 runs, 165 assertions, 1 failures, 0 errors, 0 skips
  71. # Running: ................................................................................... .........................F........................................................ Finished in 0.012428s, 13276.4725 runs/s, 13276.4725

    assertions/s. 1) Failure: BugTest#test_140 [foo.rb:21]: Expected false to be truthy. 165 runs, 165 assertions, 1 failures, 0 errors, 0 skips ಠ_ಠ
  72. “Expected X be included in Y” “Expected to found X

    but found Y instead” “Expected X to be visible in 500ms” “Expected X to change Y from Z to W”
  73. Use (ou crie) asserções que condizem Com o nível de

    abstração que o seu teste cuida
  74. within('#overall-ranking') do expect(find(:xpath, './/li[1]').to have_text('Player 1') expect(find(:xpath, './/li[2]').to have_text('Player 2')

    end within('#last-week-ranking') do expect(find(:xpath, './/li[1]').to have_text('Player 4') expect(find(:xpath, './/li[2]').to have_text('New Player') end
  75. within('#overall-ranking') do expect(find(:xpath, './/li[1]').to have_text('Player 1') expect(find(:xpath, './/li[2]').to have_text('Player 2')

    end within('#last-week-ranking') do expect(find(:xpath, './/li[1]').to have_text('Player 4') expect(find(:xpath, './/li[2]').to have_text('New Player') end wtf xpath e se o elemento não existir?
  76. within(ranking_panel(:overall)) do expect(find(:li, 1)).to have_text('Player 1') expect(find(:li, 2)).to have_text('Player 2')

    end within(ranking_panel(:last_week)) do expect(find(:li, 1)).to have_text('Player 4') expect(find(:li, 2)).to have_text('New Player') end
  77. within(ranking_panel(:overall)) do expect(find(:li, 1)).to have_text('Player 1') expect(find(:li, 2)).to have_text('Player 2')

    end within(ranking_panel(:last_week)) do expect(find(:li, 1)).to have_text('Player 4') expect(find(:li, 2)).to have_text('New Player') end Capybara custom selector método seu
  78. https://relishapp.com/rspec/rspec-expectations/docs http://docs.seattlerb.org/minitest/Minitest/Assertions.html http://www.rubydoc.info/github/teamcapybara/capybara/master/ Capybara/Node/Matchers …

  79. Testes não é um “PROBLEMA resolvido”

  80. expanda o seu toolkit

  81. Estude mais & analise os seus projetos

  82. Five Factor Testing https://www.devmynd.com/blog/five-factor-testing/ testdouble/test-smells https://github.com/testdouble/test-smells testdouble/contributing-tests https://github.com/testdouble/contributing-tests

  83. Rails 5 Test Prescriptions https://pragprog.com/book/nrtest3/rails-5-test-prescriptions xUnit Patterns http://xunitpatterns.com Cucumber e

    RSpec https://www.casadocodigo.com.br/products/livro-cucumber-rspec-tdd-bdd
  84. Obrigado :) @lucasmazza https://speakerdeck.com/lucas