Testes de unidade e TDD SoLiSC 2011

1.058 visualizações

Publicada em

Aqui buscamos ir um pouco além do uso básico do PHPUnit para que com o uso do TDD garantirmos o funcionamento correto de suas regras de negócio.

Publicada em: Tecnologia
0 comentários
4 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
1.058
No SlideShare
0
A partir de incorporações
0
Número de incorporações
56
Ações
Compartilhamentos
0
Downloads
19
Comentários
0
Gostaram
4
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Testes de unidade e TDD SoLiSC 2011

  1. 1. Testes de unidade avançados e TDD Luís Otávio Cobucci Oblonczyk21 de Outubro de 2011 6° SoLiSC
  2. 2. Luís Otávio Cobucci Oblonczyk● Desenvolvedor PHP na Softnex Tecnologia● Orientador no Senac TI● Doido por PHP desde 2003● Perfeccionista ao extremo =P @lcobucci http://about.me/lcobucci
  3. 3. Normalmente quando desenvolvemos fazemos o teste F5
  4. 4. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser
  5. 5. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro
  6. 6. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro 3) Muda o código
  7. 7. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro 3) Muda o código 4) F5
  8. 8. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro 3) Muda o código 4) F5 5) Muda o código
  9. 9. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro 3) Muda o código 4) F5 5) Muda o código 6) F5
  10. 10. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro 3) Muda o código 4) F5 5) Muda o código 6) F5 …
  11. 11. Normalmente quando desenvolvemos fazemos o teste F5 1) Abre sistema no browser 2) Procura o erro 3) Muda o código 4) F5 5) Muda o código 6) F5 … 999) Resolve o problema
  12. 12. Quanto tempo PERDEMOS nesta brincadeira?
  13. 13. Quanto dinheiro PERDEMOS nesta brincadeira?
  14. 14. E a pergunta que não quer calar...
  15. 15. Quando isso acontece num ambiente “separado”não tem GRANDES problemas
  16. 16. E quando acontece na “vida real”?
  17. 17. Tá, e o que eu posso fazer?
  18. 18. Tá, e o que eu posso fazer? Automatizar alguns testes! (pra começar)
  19. 19. Testes de Unidade “Teste de unidade é toda a aplicação de teste nas assinaturas de entradas e saídas de um sistema, consiste em validar dados válidos e inválidos via I/O (entrada/saída) sendo aplicado por desenvolvedores ou analistas de teste. Uma unidade é a menor parte testável de um programa de computador.” http://pt.wikipedia.org/wiki/Teste_de_unidade
  20. 20. Testes de Unidade● Te dá uma visão rápida do teu código: ou funciona ou não funciona● Facilita o desenvolvimento, pois caso alguma alteração estrague uma funcionalidade já existente, você fica sabendo antes mesmo de ser enviado para os sistemas de controle de versão● Servem também como parte da documentação● Ajuda a manter a sanidade mental da equipe
  21. 21. Utilizarei aqui funcionalidadespresentes a partir do PHP 5.3.2!
  22. 22. Utilizarei aqui funcionalidadespresentes a partir do PHP 5.3.2! Se você ainda não usa o PHP 5.3 é uma boa oportunidade de começar ; )
  23. 23. PHPUnit O que é: Framework p/ criação e execução de testes de unidade. Faz parte da família xUnit. Criador: Sebastian Bergmann Instalação: pear config-set auto_discover 1 pear install pear.phpunit.de/PHPUnit http://www.phpunit.de
  24. 24. Bora pro código!
  25. 25. src/Lcobucci/Examples/Tests/Calculator.php<?phpnamespace LcobucciExamplesTests;class Calculator{ public function sum($number1, $number2) { return $number1 + $number2; }}
  26. 26. test/Lcobucci/Examples/Tests/CalculatorTest.php<?phprequire_once src/Lcobucci/Examples/Tests/Calculator.php;require_once PHPUnit/Framework/TestCase.php;use LcobucciExamplesTestsCalculator;class CalculatorTest extends PHPUnit_Framework_TestCase{ public function testSum() { $calculator = new Calculator(); $this->assertEquals(4, $calculator->sum(2, 2)); }}
  27. 27. TestCase e TestSuite● O TestCase possui métodos de testes para um recurso (normalmente uma classe)● TestSuites formam grupos de testes, ou seja dentro de um TestSuite podem ter vários TestCases ou até vários TestSuites
  28. 28. tearDown() e setUp()● São métodos protegidos (com visibilidade protected) disponíveis tanto no TestCase quanto no TestSuite● Podem ser sobrecarregados caso NECESSÁRIO, e são utilizados para preparar e limpar o ambiente de teste● No TestCase o setUp() é executado ANTES de cada método de teste e o tearDown ao FINAL de cada método
  29. 29. tearDown() e setUp()● No TestSuite o setUp() é executado ANTES de cada item da suite de testes e o tearDown ao FINAL de cada item
  30. 30. Boas práticas● Não crie métodos de teste que não teste absolutamente nada● Não queira testar várias situações em um método só● Use os métodos corretos para comparações ● $this->assertEmpty($var); vs $this->assertTrue(empty($var)); ● $this->assertInstanceOf(Exception, $e); vs $this->assertTrue($e instanceof Exception);
  31. 31. Boas práticas● Crie um método de teste para cada condição de teste de um método usando nomes significativos● Mantenha os diretórios de teste similares aos diretórios das classes● Use arquivo de configuração com um arquivo de bootstrap
  32. 32. src/Lcobucci/Examples/Tests/Calculator.php<?phpnamespace LcobucciExamplesTests;use InvalidArgumentException;class Calculator{ public function div($dividend, $divisor) { if ($divisor == 0) { throw new InvalidArgumentException( The divisor cannot be ZERO ); } return $dividend / $divisor; }}
  33. 33. test/Lcobucci/Examples/Tests/CalculatorTest.php<?phprequire_once src/Lcobucci/Examples/Tests/Calculator.php;require_once PHPUnit/Framework/TestCase.php;use LcobucciExamplesTestsCalculator;class CalculatorTest extends PHPUnit_Framework_TestCase{ /** * @expectedException InvalidArgumentException */ public function testDivisorCannotBeZero() { $calculator = new Calculator(); $calculator->div(2, 0); } public function testDivMustReturnTheRightDivision() { $calculator = new Calculator(); $this->assertEquals(2, $calculator->div(4, 2)); }}
  34. 34. Test Doubles● São objetos “falsos” que utilizamos para isolar elementos que podem impedir a execução dos testes de unidade a qualquer momento e em qualquer ambiente, como: ● File system ● Database connections ● Socket connections ● HTTP requests
  35. 35. Test Doubles● Dummy: são objetos que nunca são utilizados, são criados apenas para completar a lista de parâmetros exigidos● Fake: objetos que implementados APENAS para testes, e que NÃO DEVEM ser utilizados em produção (ex: conexão com DB em memória)● Stubs: objetos que retornam dados falsos● Mocks: parecido com stubs, porém além de retornar verifica número de chamadas e parâmetros utilizados
  36. 36. test/Lcobucci/Examples/Tests/CalculatorTest.php (EXEMPLO stub)<?phprequire_once src/Lcobucci/Examples/Tests/Calculator.php;require_once src/Lcobucci/Utils/FileLog.php;require_once PHPUnit/Framework/TestCase.php;use LcobucciExamplesTestsCalculator;class CalculatorTest extends PHPUnit_Framework_TestCase{ public function testLoggerCanBeAttached() { $logger = $this->getMock( LcobucciUtilsFileLog, array(log) ); $logger->expects($this->any()) ->method(log) ->will($this->returnValue(true)); $calculator = new Calculator($logger); $this->assertEquals(2, $calculator->div(4, 2)); }}
  37. 37. test/Lcobucci/Examples/Tests/CalculatorTest.php (EXEMPLO mock)<?phprequire_once src/Lcobucci/Examples/Tests/Calculator.php;require_once src/Lcobucci/Utils/FileLog.php;require_once PHPUnit/Framework/TestCase.php;use LcobucciExamplesTestsCalculator;class CalculatorTest extends PHPUnit_Framework_TestCase{ public function testMathOperationsMustBeLogged() { $logger = $this->getMock( LcobucciUtilsFileLog, array(log) ); $logger->expects($this->one()) ->method(log) ->with(div, array(4, 2), 2) ->will($this->returnValue(true)); $calculator = new Calculator($logger); $this->assertEquals(2, $calculator->div(4, 2)); }}
  38. 38. Outras funcionalidades● Dependência entre métodos de teste● Acessar atributos privados● Acessar métodos privados
  39. 39. test/Lcobucci/Examples/Tests/StackTest.php<?phprequire_once PHPUnit/Framework/TestCase.php;class StackTest extends PHPUnit_Framework_TestCase{ public function testStackIsInitiallyEmpty() { $stack = array(); $this->assertEmpty($stack); return $stack; } /** * @depends testStackIsInitiallyEmpty */ public function testAddingAnElementWorks(array $stack) { array_push($stack, test); $this->assertEquals(test, $stack[count($stack) - 1]); }}
  40. 40. test/Lcobucci/Examples/Tests/PrivateAttributeTest.phpNão é uma boa prática, mas de vez em quando é necessário...<?phprequire_once PHPUnit/Framework/TestCase.php;class PrivateAttributeTest extends PHPUnit_Framework_TestCase{ public function testPrivateAttribute() { $this->assertEquals( teste, $this->readAttribute( new MyClass(), myPrivateAttribute ) ); }}
  41. 41. test/Lcobucci/Examples/Tests/PrivateAttributeTest.phpNão é uma boa prática, mas de vez em quando é necessário...<?phprequire_once PHPUnit/Framework/TestCase.php;class PrivateAttributeTest extends PHPUnit_Framework_TestCase{ public function testPrivateAttribute() { $this->assertAttributeEquals( teste, myPrivateAttribute, new MyClass() ); }}
  42. 42. test/Lcobucci/Examples/Tests/PrivateMethodTest.phpNão é uma boa prática, mas de vez em quando é necessário...<?phprequire_once PHPUnit/Framework/TestCase.php;class PrivateMethodTest extends PHPUnit_Framework_TestCase{ public function testPrivateMethod() { $obj = new MyClass(); $method = new ReflectionMethod( $obj, myPrivateMethod ); $method->setAccessible(true); $this->assertEquals( 2, $method->invoke($obj, 4, 2) ); }}
  43. 43. Facilitadores dos testes deunidade● Baixo acoplamento● Alta coesão● Injeção de dependências● Métodos pequenos
  44. 44. Complicadores dos testes deunidade● Escopo global● Atributos e métodos estáticos● Singleton● Tarefas no construtor da classe
  45. 45. Test Driven Development “Test Driven Development (TDD) ou em português Desenvolvimento dirigido por testes é uma técnica de desenvolvimento de software que baseia em um ciclo curto de repetições: Primeiramente o desenvolvedor escreve um caso de teste automatizado que define uma melhoria desejada ou uma nova funcionalidade. Então, é produzido código que possa ser validado pelo teste para posteriormente o código ser refatorado para um código sob padrões aceitáveis.” http://pt.wikipedia.org/wiki/Test_Driven_Development
  46. 46. Só isso??
  47. 47. Benefícios do TDD● Diminui ou até elimina a otimização prematura● Código simples, eficaz e eficiente● Cenários de testes bem definidos
  48. 48. Hora do exemplo!
  49. 49. E pra enfrentar bugs, como fica?
  50. 50. TDD na correção de bugs1. Escreva um cenário de teste que reproduza o erro2. Resolva o problema no código fonte (não pensa em deixar bonito, resolva o problema)3. Execute os testes para garantir que nada foi comprometido4. Refatore o código corrigido (agora sim pra deixar bonito)5. Execute os testes novamente e seja feliz =D
  51. 51. Dúvidas???
  52. 52. Obrigado!Eu por aí: http://about.me/lcobucciSlides: http://slideshare.net/lcobucciAvalie essa palestra: http://joind.in/3938

×