Test-Driven Development with PHP

Download Test-Driven Development with PHP

Post on 11-Jun-2015

818 views

Category:

Technology

1 download

Embed Size (px)

DESCRIPTION

Mini Curso sobre TDD e PHPUnit, bsico, ministrado no PHPSC Conf 2013.

TRANSCRIPT

<ul><li> 1. Test Driven Development with PHPCezar Junior de Souza E-mail: cezar08@unochapeco.edu.br</li></ul><p> 2. Quem sou eu Desenvolvedor PHP h 4 anos; Bacharel em Sistemas de Informao pela Unochapec;Especialista em Engenharia e Qualidade de Software;Programador na Unochapec; 3. Quem sou eu Tem experincia com: Zend Framework 1;Zend Framework 2;Ruby on Rails 3.2;Dojo;ExtJs;Jquery;Doctrine 2;PHPUnit;Gerncia de projetos com SCRUM... 4. O que vamos ver Introduo CicloPor que devemos testar?Por que no testamos?Testes automatizadosTestes automatizados X TDD O que ?ConclusoTeste de unidade Primeiro teste de unidade 5. O que vamos ver PHPUnit O que ?ObjetivosInstalaoAsseres assertEquals assertFalse assertInstanceOf assertCount assertEmpty assertNull assertTrue 6. O que vamos ver PHPUnit Escrevendo Testes com PHPUnit Dependncia de testes Provedores de dados Testando Excees 7. O que vamos ver Exemplos Exemplo 1: Conta BancriaExemplo 2: Carrinho de comprasExemplo 3: Nota fiscalMocks Anlise e cobertura de cdigo Coding Dojo O problema dos nmeros romanosBrainstormingReferncias 8. Introduo O que TDD? uma das prticas de desenvolvimento de software sugeridas por diversas metodologias.Prega a ideia de fazer com que o desenvolvedor escreva testes automatizados de maneira constante ao longo do desenvolvimento.Sugere que o desenvolvedor escreva o teste antes mesmo da implementao. 9. Introduo O que TDD? desenvolvido organicamente, com o feedback do cdigo executvel exibido entre as decises.O desenvolvedor escreve os prprios testes porque no pode esperar 20 vezes por dia por algum para escrev-los.Utilizando a tcnica as baterias de testes tendem a ser maiores, cobrindo mais casos, e garantindo uma maior qualidade externa 10. Introduo O que o TDD? A prtica nos ajuda a escrever um software melhor, com mais qualidade, e um cdigo melhor, mais fcil de ser mantido e evoludo. 11. IntroduoToda prtica que ajuda a aumentar a qualidade do software produzido deve ser estudada.(Aniche, 2012) 12. Ciclo Escrever o teste-&gt;Teste Falha-&gt;Escreve o programa-&gt;Teste passa-&gt;Refatora 13. Por que devemos testar? necessria somente uma resposta para esta pergunta, para ter a certeza que o nosso cdigo faz o que deve fazer. A quantidade de software que no funciona incrvel. 14. Por que devemos testar? Os Estados Unidos estimam que bugs de software lhes custam aproximadamente 60 bilhes de dlares por ano...Fonte: Computer World. Study: Buggy software costs users, vendors nearly 60b annually. http://www.computerworld.com/s/article/72245/Study_Buggy_software_ costs_users_vendors_nearly_60B_annually. 15. Por que devemos testar? Um erro de software pode matar pessoas o foguete Ariane 5 explodiu por um erro de software;um hospital panamenho matou pacientes pois seu software para dosagem de remdios errou. 16. Por que no testamos? No h um desenvolvedor que no saiba que a soluo para o problema testar seus cdigos. No testamos, porque testar sai caro. Testar sai caro porque estamos pagando a pessoa errada para fazer o trabalho. 17. Por que no testamos? interessante a quantidade de tempo que gastamos criando solues tecnolgicas para resolver problemas dos outros. Por que no escrevemos programas que resolvam tambm os nossos problemas? 18. Testes automatizados Uma maneira para conseguir testar o sistema todo de maneira constante e contnua a um preo justo automatizando os testes. O teste automatizado executaria muito rpido; Se ele executa constantemente;rpido,logoorodaramosSe os rodarmos o tempo todo, descobriramos os problemas mais cedo, diminuindo o custo que o bug geraria. 19. Testes automatizados Mas a equipe de desenvolvimento no gastar tempo escrevendo cdigo de teste? Antes ela s gastava tempo com cdigo de produo, essa equipe ficar menos produtiva? 20. Testes automatizados A resposta para essa pergunta :O que produtividade? Se produtividade for medida atravs do nmero de linhas de cdigo de produo escritos por dia, talvez o desenvolvedor seja sim menos produtivo, mas, se produtividade for a quantidade de linhas de cdigo de produo sem defeitos escritos por dia, o desenvolvedor ser mais produtivo ao utilizar testes automatizados. 21. Testes automatizados X TDD Teste automatizadoProblemaPensa em uma soluoCodifica a soluoPensa nos Possveis casos De erroCodifica os testesTestaCodifica a soluoTestaRefatoraTDDProblemaPensa em uma soluoPensa nos Possveis casos De erroCodifica os testesRefatora 22. Concluso Um mdico, ao longo de uma cirurgia, nunca abre mo de qualidade. Se o paciente falar para ele: Doutor, o senhor poderia no lavar a mo e terminar a cirurgia 30 minutos mais cedo?, tenho certeza que o mdico negaria na hora. Ele saberia que chegaria ao resultado final mais rpido, mas a chance de um problema to grande, que simplesmente no valeria a pena. 23. Concluso Em nossa rea, justamente o contrrio. Qual desenvolvedor nunca escreveu um cdigo de m qualidade de maneira consciente? Quem nunca escreveu uma gambiarra"? Quem nunca colocou software em produo sem executar o mnimo suficiente de testes para tal? 24. Concluso No h desculpas para no testar software.A soluo para que seus testes sejam sustentveis automatizando;Testar divertido, aumenta a qualidade do seu produto, e pode ainda ajud-lo a identificar trechos de cdigo que foram mal escritos ou projetados; Te livram vrias vezes da chatice do seu inimigo natural, o testador;Testador ProgramadoresEnfim, muita vantagem. 25. Teste de unidade Desenvolvedores, quando pensam em teste de software, geralmente imaginam um teste que cobre o sistema como um todo. Um teste de unidade no se preocupa com todo o sistema; ele est interessado apenas em saber se uma pequena parte do sistema funciona. Um teste de unidade testa uma nica unidade do nosso sistema. Geralmente, em sistemas orientados a objetos, essa unidade a classe. 26. Teste de unidade A ideia termos baterias de testes de unidade separadas para cada uma das classes do sistema; Cada bateria preocupada apenas com a sua classe. 27. Teste de unidade Desenvolvedores gastam toda sua vida automatizando processos de outras reas de negcio, criando sistemas para RHs, controle de caixa, entre outros, com o intuito de facilitar a vida daqueles profissionais.Por que no criar software que automatize o seu prprio ciclo de trabalho? Testes automatizados so fundamentais para um desenvolvimento de qualidade, sua existncia traz diversos benefcios, como aumento da qualidade e a diminuio de bugs em produo. 28. Primeiro teste de unidade Neste primeiro teste vamos de um simples cdigo baseado em echo e vamos at um teste totalmente automatizado; Imagine que temos que testar um vetor do PHP, uma pequena funcionalidade a se testar a funo count(); Para um vetor recm criado esperamos que a funo count retorne 0; Aps adicionarmos um elemento, count dever retornar 1; 29. Primeiro teste de unidade 30. Primeiro teste de unidade Testando o vetor parte 1: ?&gt; 31. Primeiro teste de unidade Testando o vetor parte 2: Um jeito bem simples te testar que estamos obtendo os resultados que esperamos imprimir o resultado antes e depois de adicionarmos o elemento. Se obtivermos 0 e depois 1, a funo count se comporta como o esperado. ?&gt; 32. Primeiro teste de unidade Testando o vetor parte 3 Vamos mudar de testes que exigem interpretao manual para testes que podem executar automaticamente. Escrevemos a comparao do valor esperado e do real em nosso cdigo de teste e imprimimos ok se os valores forem iguais. Se alguma vez virmos uma mensagem no ok saberemos que algo est errado. ?&gt; 33. Primeiro teste de unidade Testando o vetor parte 4: Agora fatoramos a sada de comparao dos valores esperado e real em uma funo que gera uma Exception onde h uma discrepncia. Isso nos traz dois benefcios: a escrita dos testes se torna mais fcil e s obteremos sada quando algo estiver errado. ?&gt; 41. Asseres assertFalse assertFalse(booleano $condicao)Relata um erro se a $condicao for TRUE. ?&gt; 42. Asseres assertInstanceOf assertInstanceOf($esperado, $real)Relata um erro se $real no for uma instncia de $esperado. ?&gt; 43. Asseres assertCount() assertCount($contaEsperada, $colecao)Relata um erro se o nmero de elementos em $colecao no for $contaEsperada. ?&gt; 44. Asseres assertEmpty() assertEmpty($colecao)Relata um erro se $colecao no estiver vazio. ?&gt; 45. Asseres assertNull assertNull($variavel)Relata um erro se $variavel no for NULL. ?&gt; 46. Asseres assertTrue assertTrue(booleano $condicao)Relata um erro se $condicao FALSE. ?&gt; 47. Asseres Mais asseres: http://phpunit.de/manual/3.7/pt_br/index.html 48. Escrevendo Testes com PHPUnit Testando o vetor com PHPUnit ?&gt; 56. Exemplo 1: Conta Bancaria O teste para a primeira condio do contrato agora passa, mas os testes para a segunda condio do contrato falham, porque ainda temos que implementar os mtodos que esses testes chamam. Para que os testes que asseguram a segunda condio do contrato passem, agora precisamos implementar os mtodos sacarDinheiro(), depositarDinheiro(), e setSaldo().Exemplo conta bancaria 57. Exemplo 1: Conta Bancaria Agora os testes que asseguram a segunda condio do contrato tambm passam. 58. Exemplo 2: Carrinho de compras Neste exemplo vamos discutir como os testes podem efetivamente ajudar desenvolvedores a pensar melhor em relao as classes que esto criando. Vamos supor que o nosso projeto atual seja uma loja on-line. Esta loja possu um carrinho de compras que guarda uma coleo de itens comprados. Um item tem as seguintes propriedades: descrio, quantidade e valor unitrio. O item tambm deve ter um mtodo que retorne o valor total. 59. Exemplo 2: Carrinho de compras As classes Item e Carrinho esto desta maneira: ItemCarrinhoDeCompras 60. Exemplo 2: Carrinho de compras O cliente solicitou uma funcionalidade que devolva o valor do item de maior valor dentro desse carrinho de compras. J pensando nos testes, temos os seguintes cenrios: Um carrinho sem nenhum item deve retornar zero;Se o carrinho s tiver um item, ele mesmo ser o item de maior valor;Se o carrinho tiver muitos itens, o item de maior valor o que deve ser retornado. 61. Exemplo 2: Carrinho de compras Seguindo a tcnica do TDD, vamos comear pelo cenrio mais simples, que nesse caso o carrinho vazio. Vamos criar um teste para a classe MaiorPreco, responsvel por essa tarefa: 62. Exemplo 2: Carrinho de compras 64. Exemplo 2: Carrinho de compras O teste dever passar, agora vamos escrever o teste que o caso do carrinho conter apenas um produto:public function testDeveRetornarValorDoItemSeCarrinhoCom1Elemento(){ $CarrinhoDeCompras = new CarrinhoDeCompras(); $carrinho = $CarrinhoDeCompras-&gt;adiciona(new Item("Kindle", 1, 299.00)); $MaiorPreco = new MaiorPreco(); $valor = $MaiorPreco-&gt;encontra($carrinho); $this-&gt;assertEquals(299.00, $valor); } 65. Exemplo 2: Carrinho de compras Para este teste passar, vamos ter que escrever um pouco mais de cdigo, mas ele continua sendo simples: 77. Exemplo 3: Nota FiscalEmail.php ?&gt;}}$this-&gt;assertEquals(1, $numero); $this-&gt;assertEquals(1, $numero); 101. O problema dos nmeros romanos Implementar a classe ConversorDeNumeroRomano da maneira mais simples para que o primeiro teste passe: ?&gt;public function converte($numeroEmRomano) {{ public function converte($numeroEmRomano) return 1; return 1; }} 102. O problema dos nmeros romanos Adicionando o segundo teste:public function testDeveEntenderOSimboloI() {{ public function testDeveEntenderOSimboloI() $romano = new ConversorDeNumeroRomano(); $romano = new ConversorDeNumeroRomano(); $numero = $romano-&gt;converte("I"); $numero = $romano-&gt;converte("I"); }}$this-&gt;assertEquals(1, $numero); $this-&gt;assertEquals(1, $numero);public function testDeveEntenderOSimboloV() {{ public function testDeveEntenderOSimboloV() $romano = new ConversorDeNumeroRomano(); $romano = new ConversorDeNumeroRomano(); $numero = $romano-&gt;converte("V"); $numero = $romano-&gt;converte("V"); }}$this-&gt;assertEquals(5, $numero); $this-&gt;assertEquals(5, $numero); 103. O problema dos nmeros romanos Implementar a classe ConversorDeNumeroRomano da maneira mais simples para que os dois primeiros testes passem: ?&gt;}} }} 104. O problema dos nmeros romanos Para no precisarmos utilizar vrios ifs encadeados ou um switch case vamos armazenar todos os smbolos com seus valores em um vetor, assim contemplamos a primeira parte, que converter os valores quando o smbolo est sozinho.class ConversorDeNumeroRomano {{ class ConversorDeNumeroRomano protected $converteArray; protected $converteArray; public function __construct() public function __construct() {{ $this-&gt;converteArray = array('I' =&gt; '1', 'V' =&gt; '5', 'X' =&gt; '10', $this-&gt;converteArray = array('I' =&gt; '1', 'V' =&gt; '5', 'X' =&gt; '10', 'L' =&gt; '50', 'C' =&gt; '100', 'D' =&gt; '500', 'L' =&gt; '50', 'C' =&gt; '100', 'D' =&gt; '500', 'M' =&gt; '1000'); 'M' =&gt; '1000');}}}} public function converte($numeroEmRomano) {{ public function converte($numeroEmRomano) return $this-&gt;converteArray[$numeroEmRomano]; return $this-&gt;converteArray[$numeroEmRomano]; }} 105. O problema dos nmeros romanos Adicionando o terceiro e quarto teste :... ... public function testDeveEntenderOSimboloII() {{ public function testDeveEntenderOSimboloII() $romano = new ConversorDeNumeroRomano(); $romano = new ConversorDeNumeroRomano(); $numero = $romano-&gt;converte("II"); $numero = $romano-&gt;converte("II"); }}$this-&gt;assertEquals(2, $numero); $this-&gt;assertEquals(2, $numero);public function testDeveEntenderOSimboloIII() {{ public function testDeveEntenderOSimboloIII() $romano = new ConversorDeNumeroRomano(); $romano = new ConversorDeNumeroRomano(); $numero = $romano-&gt;converte("III"); $numero = $romano-&gt;converte("III"); }}$this-&gt;assertEquals(3, $numero); $this-&gt;assertEquals(3, $numero); 106. O problema dos nmeros romanos Implementando a soluo mais simples para fazer todos os testes passarem:public function converte($numeroEmRomano) {{ public function converte($numeroEmRomano) $acumulador = 0; $acumulador = 0; for($i = 0; $i &lt; strlen($numeroEmRomano); $i++) {{ for($i = 0; $i &lt; strlen($numeroEmRomano); $i++) $acumulador += $this-&gt;converteArray[$numeroEmRomano[$i]]; $acumulador += $this-&gt;converteArray[$numeroEmRomano[$i]]; }} return $acumulador; return $acumulador; }} 107. O problema dos nmeros romanos Adicionando testes com nmeros de menor valor a esquerda e a direita:... ... public function testDeveEntenderOSimboloIV() {{ public function testDeveEntenderOSimboloIV() $romano = new ConversorDeNumeroRomano(); $romano = new ConversorDeNumeroRomano(); $numero = $romano-&gt;converte("IV"); $numero = $romano-&gt;converte("IV"); }}$this-&gt;assertEquals(4, $numero); $this-&gt;assertEquals(4, $numero);public function testDeveEntenderOSimboloXI() {{ public function testDeveEntenderOSimboloXI() $romano = new ConversorDeNumeroRomano(); $romano = new ConversorDeNumeroRomano(); $numero = $romano-&gt;converte("XI"); $numero = $romano-&gt;converte("XI"); }}$this-&gt;assertEquals(11, $numero); $this-&gt;assertEquals(1...</p>