TDD com Python (Completo)

5.423 visualizações

Publicada em

Todos os slides do Curso de TDD com Python

Tudo sobre Python, Django, carreira e empreendedorismo na minha newsletter quinzenal "O Melhor da Internet". ASSINE:

https://osantana.me/o-melhor-da-internet-newsletter/

Publicada em: Tecnologia
1 comentário
19 gostaram
Estatísticas
Notas
Sem downloads
Visualizações
Visualizações totais
5.423
No SlideShare
0
A partir de incorporações
0
Número de incorporações
2.353
Ações
Compartilhamentos
0
Downloads
120
Comentários
1
Gostaram
19
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

TDD com Python (Completo)

  1. 1. TestesVersão Python Osvaldo Santana Neto osantana@triveos.com
  2. 2. Osvaldo Santana NetoProgramador amadordesde 1988Programador profissionaldesde 1991Programador Pythondesde 2000Programador Djangodesde 2008
  3. 3. Eu e os testes... Objective Solutions Triveos Tecnologia XP Testes unitários Pair Programming Testes de aceitação Smalltalk TODO Testes de aceitação/ Continuous integração Integration Klaus Wustefeld Testes de integração
  4. 4. O CursoTest-Driven DevelopmentTestes unitários, integração e funcionaisFoco nos fundamentos de testes automatizadosUso de ferramentas apenas como suporte naexecução das atividades
  5. 5. O CursoA prática do uso de testes automatizadosDemonstrações das vantagens da abordagem TDD nocurto prazo e dos testes automatizados no longo prazoEsclarecimento de dúvidas comuns na implementaçãode testes automatizados
  6. 6. Teste automatizado... é o uso de software para controlar aexecução dos testes.
  7. 7. Testes automatizadosUnitáriosIntegraçãoFuncionaisAceitaçãoRegressãoOutros: performance, estático, performance,segurança, ...
  8. 8. InventoryUnitário
  9. 9. Integração Order DB InventoryUnitário Unitário
  10. 10. Funcionais Integração DB Order Inventory Unitário Unitário
  11. 11. Testes automatizadosPrós Contras Asseguram uma Não garatem que o qualidade maior no código é "bug free" código Tempo de Garante que os desenvolvimento e sistemas continuem manutenção de funcionando após aplicação tem um mudanças pequeno aumento
  12. 12. Testes automatizadosNo longo prazo sempre trazem benefíciosQuando 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
  13. 13. Cobertura de códigoDesejável 100%Não existe ferramenta capaz de medir com 100% decerteza a coberturaCódigo 100% coberto != código sem bugsFerramenta: coverage.py
  14. 14. Test-Driven DevelopmentDesenvolvimento guiado por testes
  15. 15. Test-Driven DevelopmentAbreviação: TDDKent Beck: prática de tr adXP e depois em seu uz id olivro Test-DrivenDevelopment byExamplesUtilização de testesunitários na conduçãodo desenvolvimento
  16. 16. Test-Driven DevelopmentTDD não é "ensinado".TDD é "praticado"Na fase de treinamentoé importante seguir asregras. Depoispodemos quebrá-las. Baby Steps
  17. 17. Test-Driven DevelopmentUma linha de código só existe se tiver um teste aavaliandoAltos índices de cobertura: >90%
  18. 18. Red. Green. Refactor. Escrever um Fazer o teste que falha teste passar Refatorar
  19. 19. Red.Escrever um teste que inevitavelmente falheSe 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
  20. 20. Green.Escrever o mínimo de código que faça o teste passar"Fake It (Til you make it)" — valores hard coded ouobjetos "fakes" no lugar de dependências ainda nãoimplementadasTriangulate — implementação real quando você temdois ou mais exemplos"Obvious Implementation (Til you get red bars)" —implementações óbvias podem ser feitas
  21. 21. Refactor. tr ad Refatoração: uz id 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
  22. 22. Testes unitáriosTeste de uma unidade de código
  23. 23. 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"
  24. 24. 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
  25. 25. Testes unitários Usaremos: Ambiente virtual isolado: virtualenv Unit Test e Runners: unittest e nose Mockery: mocker Functional/Acceptance: selenium Coverage: coverage
  26. 26. 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"
  27. 27. Primeira atividadeHello World do mundo dos testes:Converter um número para algarismos romanos
  28. 28. Primeira atividade Não existe zero C = 100 Algarísmos: D = 500 I=1 M = 1000 V=5 Exemplo: X = 10 MCMLXXXIII = 1983 L = 50 Casos especiais: 4, 9, 40, 90, 400, 900, ...
  29. 29. Preparando o ambiente$ sudo easy_install virtualenvou$ sudo pip install virtualenv$ virtualenv tddNew python executable in tdd/bin/pythonInstalling setuptools............done.$ cd tddtdd/$ source bin/activate(tdd)tdd/$ pip install nose coverage mockerDownloading/unpacking nose:Downloading/unpacking coverage:Downloading/unpacking mocker:Installing collected packages: coverage, nose, mocker:Successfully installed coverage nose mockerCleaning up...
  30. 30. Nosehttp://somethingaboutorange.com/mrl/projects/noseTest Runner com discovery de testes: Se parece com um teste então é um teste :D Arquivos com test no nome. Objetos TestCase, TestSuite e funções com test no nome Funções avulsas com test no nome
  31. 31. NoseOpcionalmente executa doctests: --with-doctest --doctest-extension=txtSistema de plugins e vários plugins third-parties: Usaremos: coverage (requer coverage.py), rednose Opcional: tdaemon + nose-growlConfiguração em ~/.nose.cfg ou em <proj>/setup.cfg
  32. 32. tdaemon + nose-growlPara usuários de Mac: hg clone http://bitbucket.org/osantana/nosegrowl/ hg clone http://bitbucket.org/osantana/tdaemon/Instalar: (cd nosegrowl/nose-growl && python setup.py install) (cd tdaemon && python setup.py install)
  33. 33. Nosenosetests package.module:TestCase.test_methodConfiguração ~/.noserc
  34. 34. 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
  35. 35. 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"
  36. 36. 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
  37. 37. 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 arent Stubs - Martin Fowler http://bit.ly/mockrnstubs
  38. 38. 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 Melhorbanco = Banco() banco = Banco()banco.indice("USD", "BRL", TAXA_PADRAO) banco.indice("USD", "BRL", TAXA_PADRAO)banco.comissao(COMISSAO_PADRAO) banco.comissao(COMISSAO_PADRAO)res = banco.converte( res = banco.converte( Nota(100, "USD"), "BRL) Nota(100, "USD"), "BRL)assert res == Nota(49.25, "BRL") assert Nota(49.25, "BRL") == res
  39. 39. Testes unitários Legibilidade Dados evidentes: deixe a relação entre as entradas e os resultados aparente: Pior Melhor banco = Banco()banco = Banco() banco.indice("USD", "BRL", 2.00)banco.indice("USD", "BRL", TAXA_PADRAO) banco.comissao(0.015)banco.comissao(COMISSAO_PADRAO) res = banco.converte(res = banco.converte( Nota(100, "USD"), "BRL) Nota(100, "USD"), "BRL) assert Nota(100 / 2 * (1 - 0.015), "BRL")assert Nota(49.25, "BRL") == res == res
  40. 40. 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
  41. 41. 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
  42. 42. 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
  43. 43. 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
  44. 44. Testes problemáticosTest Smells
  45. 45. Testes problemáticosTipos de problemas: Code Smells — problemas relacionados com o código dos testes Behaviour Smells — problemas relacionados ao comportamento dos testesTécnicas e padrões podem ser usados para resolveresse tipo de problema
  46. 46. Problemas comcódigo dos testesCode Smells
  47. 47. Teste obscuroDificuldade em entender o código do teste Causas Possíveis SoluçõesTeste verifica muitas informações ao Reduzir número de verificaçõesmesmo tempoO número de objetos construídos no Construir somente as fixtures necessáriassetup é maior que o necessário para aquele testeInteração com o SUT não se dá de forma Remover a indireção e testar o SUTdireta e sim através de um intermediário diretamenteNão é possível identificar o que está Simplificar o processo de setupsendo testadoExcesso de informações irrelevantes no Partir da verificação e remover todos osteste objetos e informações desnecessárias
  48. 48. Lógica condicionalCódigo que pode ou não ser executado no teste Causas Possíveis SoluçõesTeste verifica coisas diferentes Desacoplar o SUT de suas dependênciasdependendo de como executado e/ou dividir o testeModificar o valor esperado numa Criar testes individuais dedicados apenasverificação dependendo de um caso para os casos especiais e excluí-los doespecial teste genéricoRestauração do ambiente é muito Fazer a restauração do ambiente nocomplexa e cheia de verificações método tearDown no lugar de deixá-lo dentro do testeMúltiplos testes condicionais no mesmo Separando os testes para privilegiar ateste percorrento uma collection (input, localização de um problema eventualoutput)
  49. 49. Código difícil de testarCódigo é muito difícil de testar Causas Possíveis SoluçõesCódigo extremamente acoplado Desacoplar o código e parametrizar as dependências para substituí-las por objetos fakeCódigo assíncrono Separar partes síncronas do código assíncrono e testar somente esse código
  50. 50. Duplicação de códigoO mesmo código de teste repetido muitas vezes Causas Possíveis SoluçõesReproveitamento de código no estilo Aplicar padrões de refatoração ao códigoCopy & Paste do teste (ex. Extract Method)"Reinvenção da Roda" - Escrita de Aplicar padrões de refatoração ao códigotrechos de testes já escrito por outra do teste (ex. Extract Method)pessoa
  51. 51. Lógica de teste no códigoCódigo de teste no código sendo testado Causas Possíveis Soluções"Ganchos" para teste: Substituir o teste lógico por umaif testing: ... else: ... dependência que pode ser substituída por um objeto Fake.Variações: dependências específicas Refatorar o código para eliminar essepara teste, reimplementações de tipo de lógica por uma dependência quemétodos específicos para testes, etc. pode ser substituída por um objeto Fake.
  52. 52. Problemas comcomportamento dos testesBehaviour Smells
  53. 53. Roleta de verificaçõesDifícil saber qual verificação falhou Causas Possíveis SoluçõesTeste "fominha": um único teste verifica Dividir o teste em em váriosmuitas funcionalidadesNão é possível identificar o problema Acrescentar mensagens nos casos ondecom a mensagem da verificação quando a verificação não usa valores constantes/ela falha. referência como parâmetro. (ex. assert p1.x == p2.x, "coordenada x deveria ser igual")
  54. 54. Testes erráticos (I)Testes se comportam erraticamente Causas Possíveis SoluçõesTeste depende de outro e falha quando a Remover a dependência copiando-aordem de execução muda ou o teste para o teste em questão ou fazendo osquando é executado sozinho dois compartilharem as mesmas fixturesMais de um teste roda simultaneamente Cada teste deve rodar em seu própriocompartilhando o mesmo ambiente ambiente.Testes vão ficando mais lentos ou Se o problema estiver no SUT o certo éocupando mais recursos da máquina corrigir o bug. Se estiver no teste o bug está no processo de tearDownTestes dependem de recursos externos Criar uma cópia deste recursoque podem estar indisponíveis localmente ou substituí-lo por um stub.
  55. 55. Testes erráticos (II)Testes se comportam erraticamente Causas Possíveis SoluçõesTeste passa na primeira execução e O teste não está restaurando o ambientedepois falha sucessivamente inicial corretamente.Teste falha aleatoriamente quando várias Criar ambientes de teste individuaispessoas executam testessimultaneamente.Teste falha aleatoriamente mesmo com Tentar eliminar, dentro do possível, osuma pessoa executando ele por estar elementos determinísticos do teste.testando código não-determinístico
  56. 56. Depuração manualDepuração manual para localizar problemas Causas Possíveis SoluçõesExistência de código sem cobertura de Providenciar a cobertura do código emteste questão
  57. 57. Intervenção ManualIntervenção manual na execução dos testes Causas Possíveis SoluçõesO teste foi construído sem ter em mente Automatizar todo o processoque "teste automatizado" implica quenão deve existir "intervenção manual"
  58. 58. Testes lentosTestes demoram para executar Causas Possíveis SoluçõesO teste depende de recursos externos Tentar substituir esse recurso por umque têm uma latência muito alta objeto fakeTestes executam fixtures muito extensas A solução ideal é simplificar a construçãopara cada um dos cenários dessas fixtures. Não sendo possível fazer isso permita que os testes compartilhem as fixturesTeste acrescenta explicitamente um Extrair a parte síncrona do código eintervalo para lidar com código testar somente elaassíncronoMuitos testes Não é necessário executar todos os testes o tempo todo
  59. 59. Padrões detestePráticas e padrõespara uso em testes
  60. 60. Padrões…… de estratégia … para banco de dados… básicos xUnit … de desenho para testabilidade… para setup de fixtures… de verificação… para teardown… com objetos falsos
  61. 61. Padrões de estratégiaTest Strategy Patterns
  62. 62. Estratégia de AutomaçãoRecorded Test — usam a estratégia grava & reproduz.ex. Selenium IDE, Sikuli, etcData-Driven Test — úteis para testar parsers,conversores de formatos, etc. ex. teste de um crawlerScripted Test — cria-se um programa especificamentepara testar outroTest Automation Framework — é um tipo de programade testes mas usa um framework para isso. ex. xUnit
  63. 63. Estratégia para fixtures Minimal Fixture — todo teste precisa de fixtures, com essa estratégia cria-se o mínimo necessário para executar apenas o teste em questão Standard Fixture — testes compartilham um método que cria as fixtures usadas por eles Fresh Fixture — teste constrói as suas próprias fixtures Shared Fixture — testes compartilham as mesmas fixtures
  64. 64. Estratégia de Interação Back Door Manipulation (ui!) — nos casos onde não é possível avaliar o funcionamento do SUT diretamente as verificações são feitas com os dados das fixtures. Ex. verificar se o SUT manipulou os dados do banco de dados corretamente. Layer Test — escrever testes para cada uma das camadas de uma aplicação com várias camadas. Ex. testar o driver do DB, o ORM, os objetos model, etc
  65. 65. Padrões básicos xUnitxUnit Basics Patterns
  66. 66. Definição dos testesTest Method — um cenário de teste por método Four-Phase Test — setup, exercise, assert, teardownAssertion Method — métodos de verificação (.assert*()) Assertion Message — exibida quando a verificação falhaTestcase Class — agrupamento de testes relacionados
  67. 67. Execução dos testesTest Runner — aplicação que executa os testes emostra os resultadosTestcase object — instância contendo um conjunto detestes relacionadosTest Suite object — objeto com a mesma interface deTestcase que agrupa um ou mais objetos TestcaseTest Discovery — mecanismo pelo qual o Test Runnerencontra os testes
  68. 68. Padrões para setup defixturesFixture Setup Patterns
  69. 69. Setup de Fresh Fixtures In-Line Setup — cada teste constrói suas fixtures por conta própria Delegated Setup — testes constroem suas fixtures chamando um método auxiliar Implicit Setup — a construção das fixtures é implicita e executada dentro do método .setUp()
  70. 70. Criação compartilhadaPrebuilt Fixture — as fixtures são compartilhadas pelostestes e são construídas por outro componente. Ex. ./manage.py loaddata data.json do DjangoSuite Fixture Setup — fixtures construídas no .setUp()da suíte e não no Testcase
  71. 71. Padrões de verificação deresultadosResult Verification Patterns
  72. 72. Estratégia de verificação State Verification — verificamos o estado do SUT após o exercício. Ex. sut.set(1); assert sut.get() == 1 Behaviour Verification — verificamos os resultados indiretos após o exercício do SUT. Ex. web.open ("http://j.mp", mock); mocker.verify()
  73. 73. Estilos de verificação Custom Assertion — criamos uma verificação personalizada. Ex. chk(d, r) { assert r == roman(d) } Delta Assertion — verificamos a diferença do objeto antes do exercício e depois de exercitá-lo Guard Assertion — verifica o resultado com if. No caso de erro executa uma falha explicitamente. Unfinished Test Assertion — força falha pra indicar que o teste não está pronto
  74. 74. Padrões para teardownFixture Teardown Patterns
  75. 75. Estratégia para teardownGarbage-Collected Teardown — deixar o garbagecollector da linguagem fazer a limpeza do ambienteAutomated Teardown — registramos a criação detodos os objetos no setup para removê-los na fase deteardown
  76. 76. Organização do códigoIn-line Teardown — a limpeza do ambiente é feita nopróprio testeImplicit Teardown — a limpeza do ambiente fica porconta do método .tearDown()
  77. 77. Padrões com objetos falsosTest Double Patterns
  78. 78. Exemplo de código
  79. 79. Exemplo de código Dependência
  80. 80. Testes falham
  81. 81. Testes falham AM ! FA L H
  82. 82. Test DoubleSubstituir uma ou mais dependências do SUT por umequivalente específico para o teste: Test Double Dummy Test Mock Fake Test Spy Object Stub Object Object
  83. 83. DummyGeralmente são valores que não são usados no teste.Algumas vezes são apenas passados comoparâmetros para atender ao número de parâmetros deum método.
  84. 84. FakeUma implementação funcional do objeto original
  85. 85. StubsSimilares aos objetos FakeNão tem uma implementação funcional, apenasretorna valores pré-estabelecidosPodem gerar uma exceção para testar comportamentodo SUT nessa situaçãoEx: Simular um erro de timeout na conexão com umbanco de dados
  86. 86. SpySimilares aos objetos StubRegistram chamadas para seus métodos para que sejapossível fazer uma verificação indireta posteriormenteEx. Servidor de e-mail que registra e-mails "enviados"
  87. 87. MockTipo especial de objeto que pode ser programado comas expectativas de chamadas e retornos
  88. 88. Fonte: Growing Object-Oriented Software, Guided by TestsMockRede de objetos
  89. 89. Fonte: Growing Object-Oriented Software, Guided by TestsMockTestando objetoisoladamente
  90. 90. Fonte: Growing Object-Oriented Software, Guided by TestsMockTestando com umobjeto mock
  91. 91. Fonte: Growing Object-Oriented Software, Guided by TestsMockTestando com umobjeto mock
  92. 92. Mockerhttp://labix.org/mockerDesenvolvida pelo brasileiro Gustavo NiemeyerUsa a estratégia Record (para especificar asexpectativas e retornos) & Play (para verificar osresultados)
  93. 93. MockMocker
  94. 94. Padrões para banco dedadosDatabase Patterns
  95. 95. Padrões de banco de dadosDatabase Sandbox — cada desenvolvedor tem umbanco de dados à sua disposição (ex. Django SQLite inmemory)Table Truncate Teardown — truncar as tabelas na fasedo teardownTransaction Rollback Teardown — iniciar umatransação na fase de setup e efetuar um rollback nafase de teardown. Deve-se cuidar para que não tenhanenhum commit no SUT
  96. 96. Padrões de desenho paratestabilidadeDesign-for-Testability Patterns
  97. 97. 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
  98. 98. Padrões para testabilidade Exemplo! pag. 764 do xunit 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
  99. 99. Desenvolvendo aplicaçõesDesenvolvendo aplicações completas usandoTest-Driven Development
  100. 100. Desenvolvendo aplicaçõesTestes de aceitação Validar requisitos dos clientes Selenium2, Pyccuracy, Windmill, Django Client, etc.Inicia ciclo red/green/refactor
  101. 101. Desenvolvendo aplicações Escrever umteste de aceitação Escrever um Fazer o teste que falha teste passar que falha Refatorar
  102. 102. Desenvolvendo aplicações Se surgir alguma idéia nova para outro teste: anote no papel Escrever umteste de aceitação Escrever um Fazer o teste que falha teste passar que falha Refatorar
  103. 103. AtividadePastebin-like
  104. 104. Codb.inUsuário submete o código e a linguagemUma URL curta é geradaO usuário é encaminhado para o Twitter: http://twitter.com/home?status=???Usaremos a biblioteca PygmentsGoogle App Engine
  105. 105. ResumoSumário dos tópicos abordados
  106. 106. ResumoTestes são isoladosA ordem dos testes não é garantidaNão se deve adicionar lógica de teste no código deproduçãoTestes devem assumir um ambiente limpo quandocomeçam e limpar o ambiente quando terminam
  107. 107. Resumored / green / refactorsetup, exercise, verify, teardown
  108. 108. 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
  109. 109. 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.
  110. 110. MensagensTeste é algo desejável num software. Melhor se foremautomatizados e ótimos se o código foi feito depois dotesteFalá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
  111. 111. Leitura complementarNão terminamos por aqui...
  112. 112. Leitura ComplementarInternet TDD @ Wikipedia — http://j.mp/zBGgt Mocks arent Stubs — http://j.mp/7MdzF Inversion of Control and Dependency Injection — http://j.mp/I0YAA
  113. 113. Leitura Complementar
  114. 114. Atividade opcionalCoding-Dojo
  115. 115. Coding-DojoO melhor modo de aprender um jogo é jogando
  116. 116. Coding-DojoEscolha do desafio Todos participamPair programming em Solução construidas nauma máquina hora (não vale usar bibliotecas dedicadas)Piloto codifica a soluçãousando TDD Design reviews em intervalosCo-piloto troca compiloto em intervalos de 5 Piloto deve descrever ominutos que está fazendo
  117. 117. Coding-DojoO piloto pode pedir Análise de pontosajuda para o co-piloto ou positivos e negativospara a platéia após a sessãoA experiência é mais No Brasil criou-se oimportante que a #horaextra: uma "happysolução do problema hour" após o DojoSessões com tempo fixo Mais informações: http://codingdojo.org/
  118. 118. Sugestões de problemasMão de pokerMostrador LCDValor por extensoCaixa empilhadas

×