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

Testes automatizados e a prática antes da teoria

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.

Lucas Mazza

February 24, 2018
Tweet

More Decks by Lucas Mazza

Other Decks in Technology

Transcript

  1. !

  2. “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/
  3. ?!?

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

    2. Previnem regressões 3. Documentam a implementação atual
  5. 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
  6. 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
  7. 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
  8. 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
  9. É muito fácil… Abusar de DSLs e DRY e escrever

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

    testes muito acoplados e complicados de ler.
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. É muito fácil… Exagerar no uso de mocks e injeção

    de dependências sem identificar problemas no design do seu software
  19. 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
  20. 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
  21. “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”
  22. Use (ou crie) asserções que condizem Com o nível de

    abstração que o seu teste cuida
  23. 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
  24. 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?
  25. 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
  26. 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