O TDD (Test Driven Development) se torna mais comum a cada dia, mas porque você deve ligar para testes na sua aplicação. Vamos nos aprofundar num mundo de testes cobrindo desde testar o próprio PHP até os testes de sua aplicação. Descubra os benefícios e aprenda a lidar como choque cultural.
“Writing code that lasts” … or writing code you won’t hate tomorrow.
Testes e desenvolvimento de aplicações
1. E NO SÉTIMO DIA ELE
CRIOU TESTES
TDD e o papel de testes no desenvolvimento de aplicações
Rafael Dohms
rafael@rafaeldohms.com.br
Friday, November 27, 2009
2. Aviso
As referências e opiniões religiosas apresentadas
nesta palestra não refletem a opinião do autor, e
são apresentadas puramente com intuito de
ilustrar pontos-chave de forma descontraída e
humorística.
Friday, November 27, 2009
3. A CRIAÇÃO DO MUNDO
do ponto de vista do desenvolvimento de software
Friday, November 27, 2009
13. @OCriador
* Adão has joined #earth
Adão
* Eva has joined #earth
Eva
Friday, November 27, 2009
14. @OCriador
* Adão has joined #earth
Adão
* Eva has joined #earth
Eva
Adão: Agora vou apavorar!
Eva: Primeiro post!
Eva: ah droga!
Eva: Olha! uma maçã!
Friday, November 27, 2009
15. @OCriador
* Adão has joined #earth
Adão
* Eva has joined #earth
Eva
Adão: Agora vou apavorar!
Eva: Primeiro post!
Eva: ah droga!
Eva: Olha! uma maçã!
> Eva morde a maçã
OCriador: eu avisei!
Friday, November 27, 2009
16. @OCriador
* Adão has joined #earth
Adão
* Eva has joined #earth
Eva
Adão: Agora vou apavorar!
Eva: Primeiro post!
Eva: ah droga!
Eva: Olha! uma maçã!
> Eva morde a maçã
OCriador: eu avisei!
OCriador kicks Eva
OCriador kicks Adão
OCriador adds ban on *@earth on #earth
Friday, November 27, 2009
17. QUEM É RAFAEL DOHMS?
Rafael Dohms é graduado Engenheiro da Computação pelo
UniCEUB. Tem 9 anos de experiência no mercado PHP e atualmente
ocupa o cargo de Desenvolvedor Sênior e Especialista em
PHP na empresa sul-africana SWAT/MIH. É certificado ZCE PHP5.
Grande agitador da comunidade PHP é co-fundador do PHPDF e
atual coordenador do PHPSP. Contribui ativamente na área de
testes do PHP e é Host do PHPSPCast, o primeiro podcast
sobre PHP do Brazil.
Friday, November 27, 2009
18. Sebastian
Bergmann
TESTES
porque você precisa deles, mas ainda não sabe
Friday, November 27, 2009
19. PRÓS
• “Simulação”
• Facilidade de testar funções sem precisar preencher
formulários, criar usuários
• Tudo fica centralizado no teste e é feito apenas uma vez
• “Certeza”
• Testes podem simular todas situações possíveis e garantir
que seu código funciona como esperado
• “Garantia”
• Com um sistema coberto de testes você tem certeza que
sua alteração não vai quebrar outra área do sistema
Friday, November 27, 2009
20. CONS
• Tempo
• Embora você gaste mais tempo criando testes, você ganha
tempo durante as simulações e na manutenção
• Gerência
• Convencer os responsáveis pelo projeto de que testes irão
trazer lucro é geralmente complicado
Friday, November 27, 2009
21. CADA SITUAÇÃO, UMA FERRAMENTA
Frontend Backend PHP
Selenium
+ PHPUnit PHPT
PHPUnit
Friday, November 27, 2009
22. skoop @flickr
ESCREVENDO TESTES
quando você começar, nunca mais vai parar
Friday, November 27, 2009
23. MANOWARS!
• Sistema de Batalhas
• Garantindo o elemento aleatório
• Ataque: Fixo + Random
• Defesa: Fixo + Random
• Damage: Atk/Def * Random
Friday, November 27, 2009
24. Mano Gil pronto para combater.
> Atk: 10 / Def: 8
Mano Brown pronto para combater.
> Atk: 11 / Def: 9
UMA BATALHA!
Round 1
Fight!
Gil took 3 damage from Brown
Gil did 13 damage on Brown
Gil did 10 damage on Brown
Gil did 1 damage on Brown
Gil took 12 damage from Brown
Gil did 13 damage on Brown
Gil did 2 damage on Brown
Gil did 0 damage on Brown
Gil took 7 damage from Brown
Gil did 13 damage on Brown
Gil did 10 damage on Brown
Gil did 0 damage on Brown
Gil took 13 damage from Brown
Gil took 1 damage from Brown
Gil took 10 damage from Brown
Gil took 10 damage from Brown
Gil did 14 damage on Brown
Gil took 9 damage from Brown
Gil took 7 damage from Brown
Gil did 6 damage on Brown
Gil did 8 damage on Brown
Gil did 2 damage on Brown
Gil did 12 damage on Brown
Gil won!
Friday, November 27, 2009
25. MW_MANO
Vamos ver de perto o código
Friday, November 27, 2009
26. O QUE TESTAR?
1.O construtor esta definindo as variáveis?
2.O health (saúde) está em 100 quando damos reset?
3.Quando ele se machuca, o health diminui?
4.Quando vivo, ele diz “tô vivo”?
5.Quando morto, ele morre?
6.Ele se defende com o valor de defesa esperado?
7.Ele ganha bonus de defesa?
8.Qual o resultado de um ataque (sem bônus), quando:
8.1.Atk > Def
8.2.Def > Atk
8.3.Atk = Def
Friday, November 27, 2009
27. RAIO-X DE UMA SUITE DE TESTES
PHPUnit_Framework_TestSuite
AllTests
Friday, November 27, 2009
28. RAIO-X DE UMA SUITE DE TESTES
PHPUnit_Framework_TestSuite
AllTests
PHPUnit_Framework_TestCase
ClassXTest
PHPUnit_Framework_TestCase
ClassXTest
PHPUnit_Framework_TestCase
ClassXTest
Friday, November 27, 2009
29. RAIO-X DE UMA SUITE DE TESTES
PHPUnit_Framework_TestSuite
AllTests
PHPUnit_Framework_TestCase
testX
ClassXTest
...
testY
PHPUnit_Framework_TestCase
testX
ClassXTest
...
testY
PHPUnit_Framework_TestCase
testX
ClassXTest
...
testY
Friday, November 27, 2009
30. RAIO-X DE UMA SUITE DE TESTES
PHPUnit_Framework_TestSuite
SetUp
AllTests TearDown
PHPUnit_Framework_TestCase
SetUp testX
ClassXTest
...
TearDown testY
PHPUnit_Framework_TestCase
SetUp testX
ClassXTest
...
TearDown testY
PHPUnit_Framework_TestCase
SetUp testX
ClassXTest
...
TearDown testY
Friday, November 27, 2009
31. EXECUÇÃO DA SUITE
SetUp
SetUp
Para cada teste
TearDown
SetUp
Para cada teste
TearDown
SetUp
Para cada teste
TearDown
TearDown
Friday, November 27, 2009
32. ISOLAMENTO
• Mantenha seus testes isolados
• Nunca rode testes no servidor de produção!
• Soluções
• Crie uma base separada
• Use pastas separadas para arquivos
• Sempre destrua tudo que seu teste construiu
Friday, November 27, 2009
33. ESQUADRÃO LIMPEZA
Limpe tudo o que seu teste criar!
class CleanUpTest extends PHPUnit_Framework_TestCase
{
private $file = "/tmp/file";
protected function setUp()
{
parent::setUp();
}
protected function tearDown()
{
unlink($this->file);
parent::tearDown();
}
public function testFile()
{
file_put_contents($this->file);
}
Friday, November 27, 2009
34. ESQUADRÃO LIMPEZA
Limpe tudo o que seu teste criar!
class CleanUpTest extends PHPUnit_Framework_TestCase
{
private $file = "/tmp/file";
protected function setUp()
{
parent::setUp();
}
protected function tearDown()
{
unlink($this->file);
parent::tearDown();
}
public function testFile() Everything
{ must be clean!
file_put_contents($this->file);
}
Friday, November 27, 2009
35. ESQUADRÃO LIMPEZA
Limpe tudo o que seu teste criar!
class CleanUpTest extends PHPUnit_Framework_TestCase
{
private $file = "/tmp/file";
protected function setUp()
{
parent::setUp();
}
protected function tearDown()
{ Arquivos, Banco de
unlink($this->file); Dados, etc...
parent::tearDown();
}
public function testFile() Everything
{ must be clean!
file_put_contents($this->file);
}
Friday, November 27, 2009
36. TIPOS
• Teste Unitário
• Pequeno e pontual
• Geralmente testa a entrada/saída de uma função
• Teste Funcional
• Verifica a funcionalidade de interfaces
• End-to-End
• Verifica o processo do início ao fim
• Analisa o fluxo de sua aplicação
Friday, November 27, 2009
37. TESTANDO OS BÁSICOS
• Estrutura da Suite
• AllTests.php
• MW_Mano
• Testes do 1 ao 6
Friday, November 27, 2009
38. public function attack(MW_Mano $victim)
{
$atk = $this->getAtk() + trim(file_get_contents('URL'));
$def = $victim->defend();
$dmgMultiplier = (trim(file_get_contents('URL')))/100;
if ($atk > $def){
$dmg = round($atk * $dmgMultiplier);
$victim->hurt( $dmg );
$action = "%s did %d damage on %s";
}else{
$dmg = round($def * $dmgMultiplier);
$this->hurt( $dmg );
$action = "%s took %d damage from %s";
}
return sprintf($action, $this->getName(), $dmg, $victim->getName());
}
Para Facilitar leitura:
[URL] => http://www.random.org/integers/?num=1&min=0&max=100&col=1&base=10&format=plain&rnd=new
Friday, November 27, 2009
39. CÓDIGO DEINTESTÁVEL
• Singletons
• MyClass::getInstance();
• Dependências
• SO: exec(‘ls -la’);
• Recursos externos: APIs, File System
• Métodos Privados
• private method fazTudo(){...}
Friday, November 27, 2009
40. public function attack(MW_Mano $victim)
{
$atk = $this->getAtk() + $this->getRandom();
$def = $victim->defend();
$dmgMultiplier = $this->getRandom(1,100)/100;
if ($atk > $def){
$dmg = round($atk * $dmgMultiplier);
$victim->hurt( $dmg );
$action = "%s did %d damage on %s";
}else{
$dmg = round($def * $dmgMultiplier);
$this->hurt( $dmg );
$action = "%s took %d damage from %s";
}
return sprintf($action, $this->getName(), $dmg, $victim->getName());
}
public function getRandom($min = 1, $max = 10)
{
return trim(file_get_contents('http://www.random.org/integers/?num=1&min='.
$min.'&max='.$max.'&col=1&base=10&format=plain&rnd=new'));
}
Friday, November 27, 2009
41. NINJA TESTING
• Porque, às vezes, os testes precisam de dublês
• Dummy
• Fake
• Stub
• Spy
• Mock
Friday, November 27, 2009
42. RANDOM SEM O RANDOM
public function testDefendWithoutLuck()
{
//Obter Mock
$manoMock = $this->getMock('MW_Mano',array('getRandom'),
array('John'));
//Definir que o objeto retorne zero.
$manoMock->expects($this->any())
->method('getRandom')
->will($this->returnValue(0));
//Definir defesa
$manoMock->setDef(5);
//Verificar que defesa nao se altera
$this->assertEquals(5, $manoMock->defend());
}
Friday, November 27, 2009
43. DATA PROVIDERS
•1 teste, muitos dados
• Análise completa de diferentes quadros
Friday, November 27, 2009
46. Test Driven Development
TDD
Não é sobre testes, é sobre especificações
Friday, November 27, 2009
47. “TDD é uma forma de projetar software,
não apenas uma forma de testar software.”
Sebastian Bergmann - criador do PHPUnit
“It's about figuring out what you are trying
to do before you run off half-cocked to try
to do it.”
Dave Astels - autor de livros sobre TDD
Friday, November 27, 2009
48. TDD
• Escrever testes que definem o comportamento de sua
aplicação antes de escrever código.
• Testar comportamento, não apenas funcionamento
• Especificar e não apenas validar
Friday, November 27, 2009
49. Especificação Análise Codificação
Manutenção Deploy Testes
CICLO DE DESENVOLVIMENTO
sem TDD
Friday, November 27, 2009
58. Especificação Análise Codificação
Manutenção Deploy Testes
CICLO DE DESENVOLVIMENTO
sem TDD
Friday, November 27, 2009
59. Especificação Análise Testes
Manutenção Deploy Codificação
CICLO DE DESENVOLVIMENTO
sem TDD
Friday, November 27, 2009
60. Especificação Análise Testes
Manutenção Deploy Codificação
CICLO DE DESENVOLVIMENTO
sem TDD
Friday, November 27, 2009
61. Testes
O que desejamos que <método> faça?
Massa de dados para Teste
Codificação
Como <método> fará o que precisa?
Sem formulários, teste direto o backend com os dados
Friday, November 27, 2009
62. Especificação Análise Testes
Manutenção Deploy Codificação
CICLO DE DESENVOLVIMENTO
sem com TDD
Friday, November 27, 2009
63. Manutenção
• Processo de correção de bugs
• Identificar erro
• Escrever teste que cause falha
• Corrigir código
• Rodar teste novamente
• Verificar que o teste passou
Friday, November 27, 2009
64. RINSE AND REPEAT
Automatize seus testes e garanta qualidade da equipe
Friday, November 27, 2009
65. CONTINUOS INTEGRATION
• “Integração contínua”
• Processo automatizado
• Executado após cada commit
• Identifica falhas
• Identifica culpados
• Controla qualidade
Friday, November 27, 2009
67. FERRAMENTAS
• phpUnderControl
• baseado no CruiseControl
• Versão atual já formata:
• Resultados de Testes
• PHP Code Sniffer
• Code Coverage
• phpDoc
Friday, November 27, 2009