Successfully reported this slideshow.
Your SlideShare is downloading. ×

Ganhando tempo com casos de testes

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 36 Ad

Ganhando tempo com casos de testes

Download to read offline

Como usar a biblioteca SimpleTest do PHP para ganhar tempo resolvendo os problemas mas simples do dia-a-dia. Essa apresentação foi elaborada para o PHPConference2008 que aconteceu em Osasco, SP Brasil.

Como usar a biblioteca SimpleTest do PHP para ganhar tempo resolvendo os problemas mas simples do dia-a-dia. Essa apresentação foi elaborada para o PHPConference2008 que aconteceu em Osasco, SP Brasil.

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to Ganhando tempo com casos de testes (20)

Advertisement

Recently uploaded (20)

Advertisement

Ganhando tempo com casos de testes

  1. 1. Ganhando tempo com Casos de Testes Michael Castillo Granados [email_address] http://dgmike.com.br
  2. 2. Já se sentiu sem saber onde está o erro de sua aplicação? Calma! Isso é mais normal do que parece!
  3. 3. Tenho uma solução para seus problemas! Test-Driven Development
  4. 4. Por que usar? <ul><li>O sistema é percorrido por testes do começo ao fim </li></ul><ul><li>O código do projeto se torna mais confiável </li></ul><ul><li>Ganho de tempo nos projetos </li></ul><ul><li>A equipe pode efetuar testes locais e ao final de um período, executar testes globais verificando se alguém quebrou a programação de outro </li></ul>
  5. 5. O que você precisa? Suite de testes estável: Php_Unit SimpleTest Coragem Bom Senso
  6. 6. Escrevendo os primeiros testes <ul><li><?php </li></ul><ul><li>include ( 'simpletest/autorun.php' ); </li></ul><ul><li>include ( 'calculadora.php' ); </li></ul><ul><li>class CalculadoraTest extends UnitTestCase { </li></ul><ul><li>function testSoma() { </li></ul><ul><li>$ resultado = soma( 5 , 6 ); </li></ul><ul><li>$ this ->assertEqual ($ resultado , 11 ); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  7. 7. Escrevendo os primeiros testes <ul><li><?php </li></ul><ul><li>include ( 'simpletest/autorun.php' ); </li></ul><ul><li>include ( 'calculadora.php' ); </li></ul><ul><li>class CalculadoraTest extends UnitTestCase { </li></ul><ul><li>function testSoma() { </li></ul><ul><li>$resultado = soma(5, 6); </li></ul><ul><li>$this->assertEqual ($resultado, 11); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  8. 8. Escrevendo os primeiros testes <ul><li><?php </li></ul><ul><li>include ('simpletest/autorun.php'); </li></ul><ul><li>include ('calculadora.php'); </li></ul><ul><li>class CalculadoraTest extends UnitTestCase { </li></ul><ul><li>function testSoma() { </li></ul><ul><li>$resultado = soma(5, 6); </li></ul><ul><li>$this->assertEqual ($resultado, 11); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>O módulo de testes deve extender uma classe especial da SimpleTest , neste caso: UnitTestCase
  9. 9. Escrevendo os primeiros testes <ul><li><?php </li></ul><ul><li>include ('simpletest/autorun.php'); </li></ul><ul><li>include ('calculadora.php'); </li></ul><ul><li>class CalculadoraTest extends UnitTestCase { </li></ul><ul><li>function test Soma() { </li></ul><ul><li>$resultado = soma(5, 6); </li></ul><ul><li>$this->assertEqual ($resultado, 11); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>O método deve começar com test
  10. 10. Escrevendo os primeiros testes <ul><li><?php </li></ul><ul><li>include ('simpletest/autorun.php'); </li></ul><ul><li>include ('calculadora.php'); </li></ul><ul><li>class CalculadoraTest extends UnitTestCase { </li></ul><ul><li>function testSoma() { </li></ul><ul><li>$resultado = soma (5, 6); </li></ul><ul><li>$this-> assertEqual ($resultado, 11); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>assertEqual verifica se o resultado é igual ao esperado: 11
  11. 11. O primeiro resultado Fatal error: Call to undefined function soma() in calculadora_test.php on line 6 Isto acontece porque a função soma ainda não existe
  12. 12. Resolvendo o problema <ul><li><?php </li></ul><ul><li>function soma ($ a , $ b ) { </li></ul><ul><li>return $ a +$ b ; </li></ul><ul><li>} </li></ul>Uma forma simples de resolver, nada de resolver coisas a mais
  13. 13. Resultado <ul><li>OK </li></ul><ul><li>Test cases run: 1/1, Passes: 1, Failures: 0, Exceptions: 0 </li></ul>
  14. 14. Você ainda pode rodar os testes no seu navegador Falha Sucesso
  15. 15. Vamos complicar um pouco? <ul><li>class CalculadoraTest extends UnitTestCase { </li></ul><ul><li>function testSoma() { </li></ul><ul><li>$ this ->assertEqual ( soma ( 5 , 6 ), 11 ); </li></ul><ul><li>} </li></ul><ul><li>function testMultiSoma() { </li></ul><ul><li>$ this ->assertEqual ( soma ( 5 , 6 , 4 , 6 , 8 , 9 ), 38 ); </li></ul><ul><li>} </li></ul><ul><li>function testSomaVazio() { </li></ul><ul><li>$ this ->assertEqual( soma (), 0 ); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  16. 16. E o resultado dos testes muda um pouquinho... <ul><li>calculadora_test.php </li></ul><ul><li>1) Equal expectation fails because [ Integer: 11 ] differs from [ Integer: 38 ] by 27 at [F:wwhpconferencexemplosalculadora_test.php line 11] </li></ul><ul><li>in testMultiSoma </li></ul><ul><li>in CalculadoraTest </li></ul><ul><li>Exception 1! </li></ul><ul><li>Unexpected PHP error [ Missing argument 1 for soma() , called in F:wwhpconferencexemplosalculadora_test.php on line 14 and defined] severity [E_WARNING] in [F:wwhpconferencexemplosalculadora.php line 2] </li></ul><ul><li>in testSomaVazio </li></ul><ul><li>in CalculadoraTest </li></ul><ul><li>Exception 2! </li></ul><ul><li>Unexpected PHP error [ Missing argument 2 for soma() , called in F:wwhpconferencexemplosalculadora_test.php on line 14 and defined] severity [E_WARNING] in [F:wwhpconferencexemplosalculadora.php line 2] </li></ul><ul><li>in testSomaVazio </li></ul><ul><li>in CalculadoraTest </li></ul><ul><li>FAILURES!!! </li></ul><ul><li>Test cases run: 1/1, Passes: 2, Failures: 1, Exceptions: 2 </li></ul>
  17. 17. Métodos que podemos verificar <ul><li>assertTrue($x) </li></ul><ul><li>assertFalse($x) </li></ul><ul><li>assertNull($x) </li></ul><ul><li>assertNotNull($x) </li></ul><ul><li>assertIsA($x, $t) </li></ul><ul><li>assertNotA($x, $t) </li></ul><ul><li>assertEqual($x, $y) </li></ul><ul><li>assertNotEqual($x, $y) </li></ul><ul><li>assertWithinMargin($x, $y, $m) </li></ul><ul><li>assertOutsideMargin($x, $y, $m) </li></ul><ul><li>assertIdentical($x, $y) </li></ul><ul><li>assertNotIdentical($x, $y) </li></ul><ul><li>assertReference($x, $y) </li></ul><ul><li>assertClone($x, $y) </li></ul><ul><li>assertPattern($p, $x) </li></ul><ul><li>assertNoPattern($p, $x) </li></ul><ul><li>expectError($x) </li></ul><ul><li>assert($e) </li></ul>Ao todo, temos 18 métodos de verificação unitária no SimpleTest
  18. 18. Verificando um erro <ul><li><?php </li></ul><ul><li>include_once ('simpletest/autorun.php'); </li></ul><ul><li>class CometendoErros extends UnitTestCase { </li></ul><ul><li>function testEsperandoUmErro() { </li></ul><ul><li>$this-> expectError ( 'Nao foi possivel somar' ); </li></ul><ul><li>soma_impossivel (); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>function soma_impossivel () { </li></ul><ul><li>trigger_error ( 'Nao foi possivel somar' ); </li></ul><ul><li>} </li></ul>
  19. 19. Antes e depois de executar testes <ul><li>Métodos especiais setUp e tearDown </li></ul><ul><li>class LoggerTest extends UnitTestCase { </li></ul><ul><li>function setUp() { @ unlink ( 'registro.log' ); } </li></ul><ul><li>function tearDown() { @ unlink ( 'registro.log' ); } </li></ul><ul><li>function testLogger() { </li></ul><ul><li>$ this ->assert False ( file_exists ( 'registro.log' )); </li></ul><ul><li>logger( 'Mensagem que vai para o log' ); </li></ul><ul><li>$ this ->assert True ( file_exists ( 'registro.log' )); </li></ul><ul><li>$this->assert Equal ( file_get_contents ( 'registro.log' ), “Mensagem que vai para o log.” ); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  20. 20. Brincando com o banco de dados <ul><li><?php </li></ul><ul><li>class Db { </li></ul><ul><li>var $ con, $ res ; </li></ul><ul><li>function __construct () { </li></ul><ul><li>$ this ->con = new PDO( 'mysql:host=localhost;dbname=phpconference' , </li></ul><ul><li>'phpconference' , 'phpconference' ); </li></ul><ul><li>} </li></ul><ul><li>function query ( $ query ) { </li></ul><ul><li>$ this ->res = $ this ->con->query( $ query ); </li></ul><ul><li>} </li></ul><ul><li>function total( $ table ) { </li></ul><ul><li>$ res = $ this ->con->query( &quot;SELECT COUNT(*) AS t FROM $ table &quot; ); </li></ul><ul><li>return $ res ->fetchObject()->t; </li></ul><ul><li>} </li></ul><ul><li>function clear ( $ table ) { </li></ul><ul><li>$ this ->con->query( &quot;DELETE FROM $ table &quot; ); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>Tomando como base a seguinte classe de manipulação de Banco de dados
  21. 21. E a seguinte tabela do banco Tabela usuario com primary_key em id
  22. 22. Escrevemos o seguinte teste include_once ( 'simpletest/autorun.php' ); include_once ( 'db.php' ); include_once ( 'usuario.php' ); class UsuarioTest extends UnitTestCase { var $ db ; function setUp() { $ this ->db = new Db; $ this ->db->clear( 'usuarios' ); } function testNovoUsuario() { $ usuario = new Usuario(array ( 'nome' => 'Michael' , 'idade' => 24 , 'sexo' => 'masculino' , 'site' => 'http://dgmike.com.br' , )); $ this ->assertEqual( $ this ->db->total( 'usuarios' ), 1 ); } }
  23. 23. Escrevemos o seguinte teste include_once ( 'simpletest/autorun.php' ); include_once ( 'db.php' ); include_once ( 'usuario.php' ); class UsuarioTest extends UnitTestCase { var $db; function setUp() { $this->db = new Db; $this->db->clear('usuarios'); } function testNovoUsuario() { $usuario = new Usuario(array ( 'nome' => 'Michael', 'idade' => 24, 'sexo' => 'masculino', 'site' => 'http://dgmike.com.br', )); $this->assertEqual($this->db->total('usuarios'), 1); } } Incluimos os arquivos: - autorun da simpletest - classe de banco de dados - classe Usuário (que iremos testar)
  24. 24. Escrevemos o seguinte teste include_once ('simpletest/autorun.php'); include_once ('db.php'); include_once ('usuario.php'); class UsuarioTest extends UnitTestCase { var $db; function setUp() { $ this ->db = new Db; $ this ->db->clear( 'usuarios' ); } function testNovoUsuario() { $usuario = new Usuario(array ( 'nome' => 'Michael', 'idade' => 24, 'sexo' => 'masculino', 'site' => 'http://dgmike.com.br', )); $this->assertEqual($this->db->total('usuarios'), 1); } } Ao inicializar, o banco de dados (de testes) é limpo. Podemos inserir também dados de teste caso necessário.
  25. 25. Escrevemos o seguinte teste include_once ('simpletest/autorun.php'); include_once ('db.php'); include_once ('usuario.php'); class UsuarioTest extends UnitTestCase { var $db; function setUp() { $this->db = new Db; $this->db->clear('usuarios'); } function testNovoUsuario() { $ usuario = new Usuario(array ( 'nome' => 'Michael' , 'idade' => 24 , 'sexo' => 'masculino' , 'site' => 'http://dgmike.com.br' , )); $ this ->assertEqual( $ this ->db->total( 'usuarios' ), 1 ); } } Ao usar a classe Usuario nosso banco de dados deve adicionar um registro, logo o total de usuários deve ser 1 .
  26. 26. Banco de dados sempre é uma dor de cabeça! <ul><li>Alterar registros, verificar se foram alterados em funções que obviamente adicionam ao banco de dados, reescrever os testes sobre áreas já testadas. </li></ul><ul><li>Sim, concordo! Trabalhar com banco de dados é uma dor-de-cabeça! Mas nem sempre você precisa se conectar ao banco de dados de verdade </li></ul>
  27. 27. Duck typing: usando mockups <ul><li>Se quacheia como um pato e anda como um pato, então é um pato </li></ul>class BancoPato { function query() {} function numRows() {} } // Gerando o pato Mock :: generate ('BancoPato'); $ banco = new MockBancoPato (); // Setando o retorno do método query do meu // objeto de manipulação de banco de dados Pato $ banco ->setReturnValue( 'query' , true );
  28. 28. Testes diferentes para retornos diferentes da função query class PatoTest extends UnitTestCase { function setUp() { global $banco, $pato; $banco = new MockBancoPato(); $pato = new Pato(); } function testPato() { global $banco, $pato; $banco->setReturnValue( 'query' , true ); $this->assertEqual( 'Voce inseriu um pato com sussesso!' , $pato->insert( array ( 'Rodrigo' ))); } function testPatoInvalido() { global $banco, $pato; $banco->setReturnValue( 'query' , false ); $this->assertEqual( 'Ops! Ocorreram falhas ao tentar adicionar um pato' , $pato->insert( array ( 'Rodrigo' ))); } }
  29. 29. Testando a Web <ul><li>Sim! É possível testar seus formulários. </li></ul><ul><li>Que tal economizar seus dedos ao preencher aquele formulário enorme? </li></ul><ul><li>Verificar resultados de busca </li></ul><ul><li>Verificar se os links o levam para a página correta </li></ul><ul><li>Verificar se o usuário está logado ou não na conta do sistema </li></ul>
  30. 30. Um exemplo clássico
  31. 31. WebTestCase <?php include_once ( 'simpletest/web_tester.php' ); class LoginTest extends WebTestCase { function setUp() { $ db = new Db; $ db ->clear( 'usuarios' ); $ usuario = new Usuario( array ( 'nome' => 'Michael' , 'idade' => 24, 'sexo' => 'masculino' , 'site' => 'http://dgmike.com.br' , )); } function testLoginErrado () { $ this ->get( 'http://localhost/phpconference/exemplos/login.php' ); $ this ->assertTrue($ this ->setField( 'nome' , 'Augusto' )); $ this ->clickSubmit( 'Login' ); // Clicamos no botão submit $ this ->assertText( 'Login Invalido' ); // Verificamos se o texto existe } }
  32. 32. WebTestCase <?php include_once ('simpletest/web_tester.php'); class LoginTest extends WebTestCase { function setUp() { $db = new Db; $db->clear('usuarios'); $usuario = new Usuario(array ( 'nome' => 'Michael', 'idade' => 24, 'sexo' => 'masculino', 'site' => 'http://dgmike.com.br', )); } function testLoginErrado () { $ this ->get( 'http://localhost/phpconference/exemplos/login.php' ); $ this ->assertTrue($ this ->setField( 'nome' , 'Augusto' )); $ this ->clickSubmit( 'Login' ); // Clicamos no botão submit $ this ->assertText( 'Login Invalido' ); // Verificamos se o texto existe } } É aqui que acontece a mágica. Fazemos o script navegar como se fosse o usuário. E nada mais de testar na mão para ver se o formuário está correto.
  33. 33. Tem que rodar os testes separados? <ul><li><?php </li></ul><ul><li>require_once ( 'simpletest/autorun.php' ); </li></ul><ul><li>class FileTestSuite extends TestSuite { </li></ul><ul><li>function FileTestSuite() { </li></ul><ul><li>$this->TestSuite( 'All file tests' ); </li></ul><ul><li>foreach ( glob ( '*.test.php' ) as $file) { </li></ul><ul><li>$this->addTestFile($file); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  34. 34. Mas Mike, não é mais lento escrever tanto teste? NÃO!
  35. 35. Então... onde ganho? <ul><li>Na hora de descobrir onde aquela função de alteração de última hora afeta seu código </li></ul><ul><li>A longo prazo são menos falhas a corrigir </li></ul><ul><li>Tem a certeza que está escrevendo certo </li></ul><ul><li>Passa a escrever menos código desnecessário </li></ul><ul><li>Os testes são automatizados, então não precisam de sua interferência para fazer os testes, mesmo do projeto inteiro </li></ul>
  36. 36. Onde encontrar?

×