TDD com Python

13,035 views
13,446 views

Published on

Published in: Technology
2 Comments
21 Likes
Statistics
Notes
No Downloads
Views
Total views
13,035
On SlideShare
0
From Embeds
0
Number of Embeds
5,964
Actions
Shares
0
Downloads
0
Comments
2
Likes
21
Embeds 0
No embeds

No notes for slide

TDD com Python

  1. 1. Testes Versão Python Osvaldo Santana Neto osantana@triveos.com Sunday, October 24, 2010
  2. 2. Osvaldo Santana Neto Programador amador desde 1988 Programador profissional desde 1991 Programador Python desde 2000 Programador Django desde 2008 Sunday, October 24, 2010
  3. 3. Teste automatizado ... é o uso de software para controlar a execução dos testes. Sunday, October 24, 2010
  4. 4. Testes automatizados Unitários Integração Funcionais Aceitação Regressão Outros: performance, estático, performance, segurança, ... Sunday, October 24, 2010
  5. 5. Unitário Inventory Sunday, October 24, 2010
  6. 6. Unitário Unitário Inventory Order Integração DB Sunday, October 24, 2010
  7. 7. Funcionais Unitário Unitário Inventory Order Integração DB Sunday, October 24, 2010
  8. 8. Testes automatizados Prós Asseguram uma qualidade maior no código Garante que os sistemas continuem funcionando após mudanças Contras Não garatem que o código é "bug free" Tempo de desenvolvimento e manutenção de aplicação tem um pequeno aumento Sunday, October 24, 2010
  9. 9. Testes automatizados No longo prazo sempre trazem benefícios Quando usar? para testar código que já existe antes de iniciar uma refatoração durante o processo de bugfix antes de implementar o código (usado para guiar a implementação) — Test-Driven Development Sunday, October 24, 2010
  10. 10. Cobertura de código Desejável 100% Não existe ferramenta capaz de medir com 100% de certeza a cobertura Código 100% coberto != código sem bugs Ferramenta: coverage.py Sunday, October 24, 2010
  11. 11. Test-Driven Development Desenvolvimento guiado por testes Sunday, October 24, 2010
  12. 12. Test-Driven Development Abreviação: TDD Kent Beck: prática de XP e depois em seu livro Test-Driven Development by Examples Utilização de testes unitários na condução do desenvolvimento traduzido Sunday, October 24, 2010
  13. 13. Test-Driven Development TDD não é "ensinado". TDD é "praticado" Na fase de treinamento é importante seguir as regras. Depois podemos quebrá-las. Baby Steps Sunday, October 24, 2010
  14. 14. Test-Driven Development Uma linha de código só existe se tiver um teste a avaliando Altos índices de cobertura: >90% Sunday, October 24, 2010
  15. 15. Red. Green. Refactor. Escrever um teste que falha Fazer o teste passar Refatorar Sunday, October 24, 2010
  16. 16. Red. Escrever um teste que inevitavelmente falhe Se o teste não falhar? A nova funcionalidade já existe e, consequentemente, já deve ter sido testada. Mantê-lo é opcional mas se não tivermos segurança para removê-lo é melhor mantê-lo. Teste com problema Sunday, October 24, 2010
  17. 17. Green. Escrever o mínimo de código que faça o teste passar "Fake It ('Til you make it)" — valores 'hard coded' ou objetos "fakes" no lugar de dependências ainda não implementadas Triangulate — implementação real quando você tem dois ou mais exemplos "Obvious Implementation ('Til you get red bars)" — implementações óbvias podem ser feitas Sunday, October 24, 2010
  18. 18. Refactor. Refatoração: Aperfeiçoar o código sem alterar o seu comportamento Remover duplicação de código entre o código implementado e o teste traduzido Sunday, October 24, 2010
  19. 19. Testes unitários Teste de uma unidade de código Sunday, October 24, 2010
  20. 20. Testes unitários Unidades de código: funções, métodos, classes, ... System Under Test (SUT) — código que está sendo testado Framework xUnit: unittest, nose e py.test Criado por Kent Beck para Smalltalk e posteriormente para Java (jUnit) Doctests — documentação "executável" Sunday, October 24, 2010
  21. 21. Testes unitários Ferramentas Python — http://j.mp/ptRk Unit Test e Runners: unittest, doctest, nose, py.test, ... Mockery: mocker, pyMock, pMock, Mock, mox, ... Functional/Acceptance: selenium, windmill, pyccuracy, twirl, django-client, ... Static: pylint, pyflakes, pychecker, ... Coverage: coverage Sunday, October 24, 2010
  22. 22. Testes unitários Usaremos: Ambiente virtual isolado: virtualenv Unit Test e Runners: unittest e nose Mockery: mocker Functional/Acceptance: selenium Coverage: coverage Sunday, October 24, 2010
  23. 23. Testes unitários Existe a possibilidade de usar outras ferramentas para os casos: Unittest e Runners: py.test Mockery: Mock Neste caso os exemplos precisarão ser feitos "na mão" Sunday, October 24, 2010
  24. 24. Testes unitários Etapas: Setup (setUp) — preapara o ambiente onde o teste será executado (fixtures) Exercise (test*) — executa o procedimento a ser testado Assert (assert*/verify) — verifica os resultados Teardown (tearDown) — limpa o ambiente Sunday, October 24, 2010
  25. 25. Testes unitários Dicas O melhor "primeiro teste" é o teste que verifica o caso de uso mais comum. O teste mais básico. Comece a escrever pelas "assertions" Sunday, October 24, 2010
  26. 26. Testes unitários Características Isolamento — testes são independentes Legibilidade — devem privilegiar legibilidade Velocidade — devem executar rapidamente Manutenabilidade — manutenção deve ser fácil Não intrusivos — código de teste deve ficar somente no teste e não no SUT Sunday, October 24, 2010
  27. 27. Testes unitários Isolamento Um teste devem funcionar de forma independente de outros testes e assumir um ambiente "limpo" para execução Todas as dependências do código testado devem ser subtituídas por "doubles" (fakes/stubs ou mocks) Mocks aren't Stubs - Martin Fowler http://bit.ly/mockrnstubs Sunday, October 24, 2010
  28. 28. Testes unitários Legibilidade O código do teste não precisa ser elegante, precisa ser legível. Testes são para "consumo" humano Resultados esperados em primeiro lugar: Pior Melhor banco = Banco() banco.indice("USD", "BRL", TAXA_PADRAO) banco.comissao(COMISSAO_PADRAO) res = banco.converte( Nota(100, "USD"), "BRL) assert res == Nota(49.25, "BRL") banco = Banco() banco.indice("USD", "BRL", TAXA_PADRAO) banco.comissao(COMISSAO_PADRAO) res = banco.converte( Nota(100, "USD"), "BRL) assert Nota(49.25, "BRL") == res Sunday, October 24, 2010
  29. 29. Testes unitários Legibilidade Dados evidentes: deixe a relação entre as entradas e os resultados aparente: Pior Melhor banco = Banco() banco.indice("USD", "BRL", TAXA_PADRAO) banco.comissao(COMISSAO_PADRAO) res = banco.converte( Nota(100, "USD"), "BRL) assert Nota(49.25, "BRL") == res banco = Banco() banco.indice("USD", "BRL", 2.00) banco.comissao(0.015) res = banco.converte( Nota(100, "USD"), "BRL) assert Nota(100 / 2 * (1 - 0.015), "BRL") == res Sunday, October 24, 2010
  30. 30. Testes unitários Legibilidade Nome de teste: test_(pass|fail)_descricao_(invalid| with_x|without_y|basic) Apenas 1 ciclo setup/exercise/verify/teardown por teste A legibilidade sempre é subjetiva mas é importante estabelecer padrões em projetos desenvolvidos por equipes com vários desenvolvedores Sunday, October 24, 2010
  31. 31. Testes unitários Dicas O ciclo completo de red/green/refactor deve ser curto para privilegiar o ritmo. Se o teste está ficando grande: quebre-o em testes menores Sunday, October 24, 2010
  32. 32. Testes unitários Dicas Programando sozinho? Deixe o último teste "quebrado" no fim de uma sessão de programação para saber de onde retomar o desenvolvimento Programando em equipe? Faça 'commit' somente se todos os testes estiverem passando Usa um sistema de controle de versão distribuído? Deixe 'quebrado' localmente Sunday, October 24, 2010
  33. 33. Testes unitários Testabilidade Fácil testar: código bem desenhado, código criado com TDD, funções determinísticas, etc Difícil testar: GUI, código assíncrono, esquemas em banco de dados, componentes de aplicações distribuídas, funções não-determinísticas, etc Existem práticas e padrões que tornam alguns tipos de testes mais fáceis de serem feitos Sunday, October 24, 2010
  34. 34. Padrões com objetos falsos Test Double Patterns Sunday, October 24, 2010
  35. 35. Exemplo de código Sunday, October 24, 2010
  36. 36. Exemplo de código Dependência Sunday, October 24, 2010
  37. 37. Testes falham Sunday, October 24, 2010
  38. 38. Testes falham FALHAM! Sunday, October 24, 2010
  39. 39. Test Double Substituir uma ou mais dependências do SUT por um equivalente específico para o teste: Test Double Dummy Object Test Stub Test Spy Mock Object Fake Object Sunday, October 24, 2010
  40. 40. Dummy Geralmente são valores que não são usados no teste. Algumas vezes são apenas passados como parâmetros para atender ao número de parâmetros de um método. Sunday, October 24, 2010
  41. 41. Fake Uma implementação funcional do objeto original Sunday, October 24, 2010
  42. 42. Stubs Similares aos objetos Fake Não tem uma implementação funcional, apenas retorna valores pré-estabelecidos Podem gerar uma exceção para testar comportamento do SUT nessa situação Ex: Simular um erro de timeout na conexão com um banco de dados Sunday, October 24, 2010
  43. 43. Spy Similares aos objetos Stub Registram chamadas para seus métodos para que seja possível fazer uma verificação indireta posteriormente Ex. Servidor de e-mail que registra e-mails "enviados" Sunday, October 24, 2010
  44. 44. Mock Tipo especial de objeto que pode ser programado com as expectativas de chamadas e retornos Sunday, October 24, 2010
  45. 45. Mock Rede de objetos Fonte: Growing Object-Oriented Software, Guided by Tests Sunday, October 24, 2010
  46. 46. Mock Testando objeto isoladamente Fonte: Growing Object-Oriented Software, Guided by Tests Sunday, October 24, 2010
  47. 47. Mock Testando com um objeto mock Fonte: Growing Object-Oriented Software, Guided by Tests Sunday, October 24, 2010
  48. 48. Mock Testando com um objeto mock Fonte: Growing Object-Oriented Software, Guided by Tests Sunday, October 24, 2010
  49. 49. Mocker http://labix.org/mocker Desenvolvida pelo brasileiro Gustavo Niemeyer Usa a estratégia Record (para especificar as expectativas e retornos) & Play (para verificar os resultados) Sunday, October 24, 2010
  50. 50. Mock Mocker Sunday, October 24, 2010
  51. 51. Padrões para banco de dados Database Patterns Sunday, October 24, 2010
  52. 52. Padrões de banco de dados Database Sandbox — cada desenvolvedor tem um banco de dados à sua disposição (ex. Django SQLite in memory) Table Truncate Teardown — truncar as tabelas na fase do teardown Transaction Rollback Teardown — iniciar uma transação na fase de setup e efetuar um rollback na fase de teardown. Deve-se cuidar para que não tenha nenhum commit no SUT Sunday, October 24, 2010
  53. 53. Padrões de desenho para testabilidade Design-for-Testability Patterns Sunday, October 24, 2010
  54. 54. Padrões para testabilidade Dependency Injection — permite substituir dependências do SUT por Test Doubles. A dependência pode ser passada na construção ou como parâmetro do método. Ex. O objeto TimeDisplay depende de TimeProvider que, nos testes, é substituído por stub/mock Dependency Lookup — o objeto busca suas dependências em um local específico. Ex. registro, dict Sunday, October 24, 2010
  55. 55. Padrões para testabilidade Humble object — extrair a lógica num componente separado e mais fácil de testar. Ex. extrair a parte síncrona de um objeto com operações assíncronas Pode-se usar um método no lugar de um objeto Test Hook — não use: adicionar lógica condicional no SUT para se comportar de modo específico com os testes Exemplo! pag. 764 do xunit Sunday, October 24, 2010
  56. 56. Desenvolvendo aplicações Desenvolvendo aplicações completas usando Test-Driven Development Sunday, October 24, 2010
  57. 57. Desenvolvendo aplicações Testes de aceitação Validar requisitos dos clientes Selenium2, Pyccuracy, Windmill, Django Client, etc. Inicia ciclo red/green/ refactor Sunday, October 24, 2010
  58. 58. Desenvolvendo aplicações Escrever um teste que falha Fazer o teste passar Refatorar Escrever um teste de aceitação que falha Sunday, October 24, 2010
  59. 59. Desenvolvendo aplicações Escrever um teste que falha Fazer o teste passar Refatorar Escrever um teste de aceitação que falha Se surgir alguma idéia nova para outro teste: anote no papel Sunday, October 24, 2010
  60. 60. Resumo Sumário dos tópicos abordados Sunday, October 24, 2010
  61. 61. Resumo Testes são isolados A ordem dos testes não é garantida Não se deve adicionar lógica de teste no código de produção Testes devem assumir um ambiente limpo quando começam e limpar o ambiente quando terminam Sunday, October 24, 2010
  62. 62. Resumo red / green / refactor setup, exercise, verify, teardown Sunday, October 24, 2010
  63. 63. F.A.Q. Quando sei que os testes são suficientes? Quando você tiver certeza que seu software está completo e sem bugs: nunca serão. Quando eu preciso fazer testes: Resposta curta: sempre. Resposta longa: quando você não tiver segurança total daquilo que precisa ser feito Sunday, October 24, 2010
  64. 64. F.A.Q. Qual o tamanho ideal de um baby-step? Resposta curta: do tamanho que te dê segurança. Resposta longa: TDD é uma prática e como tal requer treino. O ideal é que no início se use passos pequenos e posteriormente aumentá-los. Existe uma relação direta entre a cobertura de testes e a quantidade de bugs num código? Existe essa relação mas ela não é linear. Sunday, October 24, 2010
  65. 65. Mensagens Teste é algo desejável num software. Melhor se forem automatizados e ótimos se o código foi feito depois do teste Falácia: "Código não testado é código bugado" Não existe bala de prata, logo, teste automatizado não é uma delas Atenção para os "radicais do teste". Radicalismo nunca é bom para um programador Sunday, October 24, 2010
  66. 66. Leitura complementar Não terminamos por aqui... Sunday, October 24, 2010
  67. 67. Leitura Complementar Internet TDD @ Wikipedia — http://j.mp/zBGgt Mocks aren't Stubs — http://j.mp/7MdzF Inversion of Control and Dependency Injection — http://j.mp/I0YAA Sunday, October 24, 2010
  68. 68. Leitura Complementar Sunday, October 24, 2010

×