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

Testando código em Python

Testando código em Python

Slides de apresentação no encontro da Python Floripa.

Dfd7b9492f5c5e49dca373bfdd7a3b1a?s=128

Elias Dorneles

December 10, 2015
Tweet

Transcript

  1. Testando código em Python Elias Dorneles @eliasdorneles

  2. Ouvi falar de TDD pela 1a vez em 2009

  3. Mas levei anos para ver vantagem.

  4. YMMV Sua experiência pode ser diferente!

  5. Com dez anos de experiência, a gente ainda é adolescente

    =)
  6. Complexidade pode te deixar de coração partido

  7. • Consigo ir mais longe • Reduz a quantidade de

    adivinhação • Por conseguinte, reduz minha ansiedade :) PORÉM: não ajuda se falta feedback para coisas mais amplas (tipo: estou criando o produto certo?) Por que é legal escrever testes?
  8. TDD is cool. Porém, é mais comum me encontrar escrevendo

    testes para código legado.
  9. Bugs tendem a reaparecer... Ói nóis qui traveiz...

  10. Regra de ouro: quando encontrar bug, adicione um caso para

    pegá-lo.
  11. Cheap trick $ ./meu_script.py <in.txt >out.txt $ diff <(./meu_script.py <in.txt)

    out.txt
  12. Cheap trick $ ./meu_script.py <in.txt >out.txt $ diff <(./meu_script.py <in.txt)

    out.txt Prós: 1. de graça! 2. se sentir Unıx hacker :D Contras: 1. cobre apenas o caminho feliz 2. não aponta o problema exato
  13. Para cobrir mais casos, basta usar outros arquivos.

  14. Suíte de testes $ cat run_tests.sh #!/bin/bash set -e diff

    <(python meu_script.py < in1.txt) out1.txt diff <(python meu_script.py < in2.txt) out2.txt diff <(python meu_script.py < in3.txt) out3.txt $ ./run_tests.sh
  15. Suíte de testes $ cat run_tests.sh #!/bin/bash set -e diff

    <(python meu_script.py < in1.txt) out1.txt diff <(python meu_script.py < in2.txt) out2.txt diff <(python meu_script.py < in3.txt) out3.txt $ ./run_tests.sh Fixtures
  16. Suíte de testes $ cat run_tests.sh #!/bin/bash set -e diff

    <(python meu_script.py < in1.txt) out1.txt diff <(python meu_script.py < in2.txt) out2.txt diff <(python meu_script.py < in3.txt) out3.txt $ ./run_tests.sh Fixtures Expectativas
  17. Suíte de testes $ cat run_tests.sh #!/bin/bash set -e diff

    <(python meu_script.py < in1.txt) out1.txt diff <(python meu_script.py < in2.txt) out2.txt diff <(python meu_script.py < in3.txt) out3.txt $ ./run_tests.sh Fixtures Expectativas Caso
  18. Suíte de testes $ cat run_tests.sh #!/bin/bash set -e diff

    <(python meu_script.py < in1.txt) out1.txt diff <(python meu_script.py < in2.txt) out2.txt diff <(python meu_script.py < in3.txt) out3.txt $ ./run_tests.sh Fixtures Expectativas Suíte Caso
  19. Having a test suite is sweet!

  20. Estrutura de um teste ➔ Dado: ◆ fixtures, inicializando código

    a ser testado ➔ Quando: ◆ exercitar código a ser testado ➔ Então: ◆ verifica se resultado é o esperado
  21. “Show me some code!” import unittest class ExampleCase(unittest.TestCase): def test_something(self):

    # given: fixture = self.build_fixture(...) # when: resultado = codigo_a_testar(fixture) # then: self.assertEqual(esperado, resultado)
  22. Estrutura de um teste ➔ Dado: ◆ fixtures, inicializando código

    a ser testado ➔ Quando: ◆ exercitar código a ser testado ➔ Então: ◆ verifica se resultado é o esperado Parte mais chata
  23. Estrutura de um teste ➔ Dado: ◆ fixtures, inicializando código

    a ser testado ➔ Quando: ◆ exercitar código a ser testado ➔ Então: ◆ verifica se resultado é o esperado Parte mais importante e mais fácil de errar
  24. Verificar a coisa errada atrapalha mais do que ajuda

  25. Exemplo com bug na verificação def test_device_should_be_connected(self): # when: report

    = get_status_report(self.device) # then: self.assertTrue('connected' in report)
  26. Para ter certeza que está checando a coisa certa, faça

    o teste falhar
  27. Fazendo o teste falhar def test_device_should_be_connected(self): # when: report =

    get_status_report(self.offline_device) # then: self.assertTrue('connected' in report) OOOPS! Teste continua passando!
  28. Corrigindo... def test_device_should_be_connected(self): # when: report = get_status_report(self.offline_device) # then:

    self.assertRegexpMatches(report, r'\bconnected') Agora o teste falha, como esperado
  29. Agora, sim! def test_device_should_be_connected(self): # when: report = get_status_report(self.device) #

    then: self.assertRegexpMatches(report, r'\bconnected')
  30. Dublês de teste (test doubles) Para quando você quiser poupar

    o oficial
  31. Tipos de dublês de teste ➔ Dummy ◆ só para

    preencher argumentos (geralmente vazios, tipo None, [], {}, etc) ➔ Fakes ◆ implementação leve duma dependência (exemplo: DB em memória) ➔ Stubs ◆ simulam respostas prontas para chamadas feitas pelo código sendo testado ➔ Mocks ◆ especificam contrato com código sendo testado (possuem asserções)
  32. Biblioteca mock: use para stubs ou para mocks

  33. (demo rápida da classe mock.Mock)

  34. Python context managers rock!

  35. Context managers ajudam com captura/cleanup @contextmanager def script_args(argv): old_argv =

    sys.argv try: sys.argv = ['fake_script.py'] + argv yield sys.argv finally: sys.argv = old_argv
  36. Context managers ajudam com captura/cleanup # USANDO: with script_args(['--opcao1', '--opcao2']):

    print(sys.argv) # vai mostrar: # ['fake_script.py', '--opcao1', '--opcao2']
  37. Mais ferramentas legais • VCR.py https://pypi.python.org/pypi/vcrpy • Tox: https://tox.readthedocs.org •

    py.test http://pytest.org/ • Nose: https://nose.readthedocs.org Wishlist: RSpec para Python (http://rspec.info)
  38. Últimos pensamentos... • Testar a coisa certa, na camada correta,

    às vezes é difícil de descobrir. Idéia: pensar o que é mais provável mudar. • “Bom design recebe bem as mudanças” - José Ricardo ◦ Isto vale para o código dos testes também, mas os tipos de coisas que causam mudanças são diferentes. ◦ Geralmente, código de teste é melhor bem direto (mínima indireção, sem muita herança e/ou OO)
  39. FIM Thanks! Algumas referências: • http://blog.solidcraft. eu/2012/09/test-driven-traps- part-1.html • http://martinfowler.

    com/articles/mocksArentStubs. html • https://www.destroyallsoftware. com/screencasts/catalog • https://www.facebook. com/notes/kent-beck/when-tdd- doesnt- matter/797644973601702 • Livro do Michael Feathers Elias Dorneles @eliasdorneles