Testes de unidade e TDD SoLiSC 2011
-
Upload
luis-otavio-cobucci-oblonczyk -
Category
Technology
-
view
1.297 -
download
4
description
Transcript of Testes de unidade e TDD SoLiSC 2011
Testes de unidade avançados e TDD
Testes de unidade avançados e TDD
Luís Otávio Cobucci Oblonczyk
21 de Outubro de 20116° SoLiSC
Luís Otávio Cobucci OblonczykLuí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
Normalmente quando desenvolvemos fazemos o teste F5
1) Abre sistema no browser2) Procura o erro3) Muda o código
Normalmente quando desenvolvemos fazemos o teste F5
1) Abre sistema no browser2) Procura o erro3) Muda o código4) F5
Normalmente quando desenvolvemos fazemos o teste F5
1) Abre sistema no browser2) Procura o erro3) Muda o código4) F55) Muda o código
Normalmente quando desenvolvemos fazemos o teste F5
1) Abre sistema no browser2) Procura o erro3) Muda o código4) F55) Muda o código6) F5
Normalmente quando desenvolvemos fazemos o teste F5
1) Abre sistema no browser2) Procura o erro3) Muda o código4) F55) Muda o código6) F5…
Normalmente quando desenvolvemos fazemos o teste F5
1) Abre sistema no browser2) Procura o erro3) Muda o código4) F55) Muda o código6) F5…999) Resolve o
problema
Testes de UnidadeTestes 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
Testes de UnidadeTestes 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
Utilizarei aqui funcionalidadespresentes a partir do PHP 5.3.2!
Se você ainda não usao PHP 5.3 é uma boaoportunidade decomeçar ; )
PHPUnitPHPUnit
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
src/Lcobucci/Examples/Tests/Calculator.php
<?phpnamespace Lcobucci\Examples\Tests;
class Calculator{ public function sum($number1, $number2) { return $number1 + $number2; }}
test/Lcobucci/Examples/Tests/CalculatorTest.php<?phprequire_once 'src/Lcobucci/Examples/Tests/Calculator.php';require_once 'PHPUnit/Framework/TestCase.php';
use \Lcobucci\Examples\Tests\Calculator;
class CalculatorTest extends PHPUnit_Framework_TestCase{ public function testSum() { $calculator = new Calculator(); $this->assertEquals(4, $calculator->sum(2, 2)); }}
TestCase e TestSuiteTestCase 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
tearDown() e setUp()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
tearDown() e setUp()tearDown() e setUp()
● No TestSuite o setUp() é executado ANTES de cada item da suite de testes e o tearDown ao FINAL de cada item
Boas práticasBoas 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);
Boas práticasBoas 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
src/Lcobucci/Examples/Tests/Calculator.php
<?phpnamespace Lcobucci\Examples\Tests;
use \InvalidArgumentException;
class Calculator{ public function div($dividend, $divisor) { if ($divisor == 0) { throw new InvalidArgumentException( 'The divisor cannot be ZERO' ); }
return $dividend / $divisor; }}
test/Lcobucci/Examples/Tests/CalculatorTest.php<?phprequire_once 'src/Lcobucci/Examples/Tests/Calculator.php';require_once 'PHPUnit/Framework/TestCase.php';
use \Lcobucci\Examples\Tests\Calculator;
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)); }}
Test DoublesTest 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
Test DoublesTest 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
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 \Lcobucci\Examples\Tests\Calculator;
class CalculatorTest extends PHPUnit_Framework_TestCase{ public function testLoggerCanBeAttached() { $logger = $this->getMock( '\Lcobucci\Utils\FileLog', array('log') );
$logger->expects($this->any()) ->method('log') ->will($this->returnValue(true));
$calculator = new Calculator($logger); $this->assertEquals(2, $calculator->div(4, 2)); }}
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 \Lcobucci\Examples\Tests\Calculator;
class CalculatorTest extends PHPUnit_Framework_TestCase{ public function testMathOperationsMustBeLogged() { $logger = $this->getMock( '\Lcobucci\Utils\FileLog', 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)); }}
Outras funcionalidadesOutras funcionalidades
● Dependência entre métodos de teste● Acessar atributos privados● Acessar métodos privados
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]); }}
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' ) ); }}
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() ); }}
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) ); }}
Facilitadores dos testes de unidadeFacilitadores dos testes de unidade● Baixo acoplamento● Alta coesão● Injeção de dependências● Métodos pequenos
Complicadores dos testes de unidadeComplicadores dos testes de unidade● Escopo global● Atributos e métodos estáticos● Singleton● Tarefas no construtor da classe
Test Driven DevelopmentTest 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
Benefícios do TDDBenefícios do TDD
● Diminui ou até elimina a otimização prematura● Código simples, eficaz e eficiente● Cenários de testes bem definidos
TDD na correção de bugsTDD na correção de bugs
1. Escreva um cenário de teste que reproduza o erro
2. 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 comprometido
4. Refatore o código corrigido (agora sim pra deixar bonito)
5. Execute os testes novamente e seja feliz =D
Obrigado!Obrigado!
Eu por aí: http://about.me/lcobucci
Slides: http://slideshare.net/lcobucci
Avalie essa palestra: http://joind.in/3938