Testes e o TDD estão se tornando uma parte muito importante do nosso dia a dia como desenvolvedores. Veja como os testes se aplicam ao seu trabalho e como seus sistemas e equipe podem se beneficiar com isso. Aprenda também o que é o TDD e quais melhorias ele traz ao processo de desenvolvimento.
A Journey into your Lizard Brain - PHP Conference Brasil 2015
TDC 2011 - E no sétimo dia ele escreveu testes
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
Saturday, July 9, 2011
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.
Saturday, July 9, 2011
3. A CRIAÇÃO DO MUNDO
do ponto de vista do desenvolvimento de software
Saturday, July 9, 2011
13. @OCriador
* Adão has joined #earth
Adão
* Eva has joined #earth
Eva
Saturday, July 9, 2011
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çã!
Saturday, July 9, 2011
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!
Saturday, July 9, 2011
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
Saturday, July 9, 2011
17. Rafael Dohms
photo credit: Eli White
Evangelista PHP, membro ativo da Comunidade
PHP e certificado ZCE. Ele ajudou na fundação de
dois Grupos de Usuários de PHP ao longo do tempo
e hoje compartilha a coordenação do PHPSP.
Desenvolvedor, gamer e apaixonado por código ele
também é host do primeiro podcast de PHP do
Brasil: PHPSPCast.
Atualmente ele trabalha na equipe SWAT do
grupo MIH, uma equipe de experts que fornecem
conhecimento técnico para o grupo além de trabalhar
com P&D buscando novos nichos da internet e
tecnologia. Seu papel como Desenvolvedor
Sênior é codar, treinar e auxiliar outras empresas e
se divertir enquanto faz isso.
Saturday, July 9, 2011
18. Sebastian
Bergmann
TESTES
porque você precisa deles, mas ainda não sabe
Saturday, July 9, 2011
19. TESTES?
• Descrever programaticamente um caso de uso válido e
garantir sua funcionalidade
• Forçar a execução de seu código em diversos cenários
• Objetivos
• Garantir funcionamento
• Agilizar a refatoração
• Testes automatizados
Saturday, July 9, 2011
20. 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
Saturday, July 9, 2011
21. 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
Saturday, July 9, 2011
22. 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
Saturday, July 9, 2011
23. CADA SITUAÇÃO, UMA FERRAMENTA
Frontend Backend PHP
Selenium
+ PHPUnit PHPT
PHPUnit
Saturday, July 9, 2011
24. skoop @flickr
ESCREVENDO TESTES
quando você começar, nunca mais vai parar
Saturday, July 9, 2011
25. MANOWARS!
• Sistema de Batalhas
• Garantindo o elemento aleatório
• Ataque: Fixo + Random
• Defesa: Fixo + Random
• Damage: Atk/Def * Random
Saturday, July 9, 2011
26. 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!
Saturday, July 9, 2011
27. MW_MANO
Vamos ver de perto o código
Saturday, July 9, 2011
28. 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
Saturday, July 9, 2011
29. RAIO-X DE UMA SUITE DE TESTES
PHPUnit_Framework_TestSuite
AllTests
Saturday, July 9, 2011
30. RAIO-X DE UMA SUITE DE TESTES
PHPUnit_Framework_TestSuite
AllTests
PHPUnit_Framework_TestCase
ClassXTest
PHPUnit_Framework_TestCase
ClassXTest
PHPUnit_Framework_TestCase
ClassXTest
Saturday, July 9, 2011
31. 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
Saturday, July 9, 2011
32. 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
Saturday, July 9, 2011
33. EXECUÇÃO DA SUITE
SetUp
SetUp
Para cada teste
TearDown
SetUp
Para cada teste
TearDown
SetUp
Para cada teste
TearDown
TearDown
Saturday, July 9, 2011
34. 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
Saturday, July 9, 2011
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()
{
unlink($this->file);
parent::tearDown();
}
public function testFile()
{
file_put_contents($this->file);
}
Saturday, July 9, 2011
36. 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);
}
Saturday, July 9, 2011
37. 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);
}
Saturday, July 9, 2011
38. QUANDO LIMPAR?
class CleanUpTest extends PHPUnit_Framework_TestCase
{
private $file = "/tmp/file";
protected function setUp()
{
parent::setUp();
}
protected function tearDown()
{
parent::tearDown();
}
public function testFile()
{
file_put_contents($this->file);
$this->assertSomething(...);
unlink($this->file);
}
Saturday, July 9, 2011
39. QUANDO LIMPAR?
class CleanUpTest extends PHPUnit_Framework_TestCase
{
private $file = "/tmp/file";
protected function setUp()
{
parent::setUp();
}
protected function tearDown()
{
parent::tearDown();
}
public function testFile()
{
file_put_contents($this->file);
$this->assertSomething(...);
Interrompe o
unlink($this->file); teste se falhar
}
Saturday, July 9, 2011
40. TESTANDO OS BÁSICOS
• Estrutura da Suite
• AllTests.php
• MW_Mano
• Testes do 1 ao 6
Saturday, July 9, 2011
41. 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
Saturday, July 9, 2011
42. CÓDIGO DEINTESTÁVEL
• Singletons
• MyClass::getInstance();
• Dependências
• SO: exec(‘ls -la’);
• Recursos externos: APIs, File System
• Métodos Privados
• private method fazTudo(){...}
Saturday, July 9, 2011
43. 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'));
}
Saturday, July 9, 2011
44. 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'));
}
Saturday, July 9, 2011
45. CENAS ARRISCADAS
• Porque, às vezes, os testes precisam de dublês
• Removem dependências em código externo
• Oferecem controle sobre resultados
• Estratégias comuns:
• Dummy, Fake, Stub, Spy, Mock
Saturday, July 9, 2011
46. MOCK OBJECT
• Em português: falso, imitação (Objeto falso)
• Significa: copiar, imitar ou falsificar
• Objetivo: trocar algo que não temos controle por
outro do qual podemos garantir o resultado, forçando
diferentes cenários.
Saturday, July 9, 2011
47. 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());
}
Saturday, July 9, 2011
48. DATA PROVIDERS
• Um teste, muitos dados
• Análise completa de diferentes cenários
Saturday, July 9, 2011
51. Test Driven Development
TDD
Não é sobre testes, é sobre especificações
Saturday, July 9, 2011
52. “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
Saturday, July 9, 2011
53. 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
Saturday, July 9, 2011
54. Especificação Análise Codificação
Manutenção Deploy Testes
CICLO DE DESENVOLVIMENTO
sem TDD
Saturday, July 9, 2011
63. Especificação Análise Codificação
Manutenção Deploy Testes
CICLO DE DESENVOLVIMENTO
sem TDD
Saturday, July 9, 2011
64. Especificação Análise Testes
Manutenção Deploy Codificação
CICLO DE DESENVOLVIMENTO
sem TDD
Saturday, July 9, 2011
65. Especificação Análise Testes
Manutenção Deploy Codificação
CICLO DE DESENVOLVIMENTO
sem TDD
Saturday, July 9, 2011
66. Testes
O que desejamos que <método> faça?
Quais são os cenários que ele precisa estar preparado
para lidar?
Codificação
Como <método> fará o que precisa?
Sem formulários, teste direto o backend com os dados
Saturday, July 9, 2011
67. Especificação Análise Testes
Manutenção Deploy Codificação
CICLO DE DESENVOLVIMENTO
sem com TDD
Saturday, July 9, 2011
68. 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
Saturday, July 9, 2011
69. RINSE AND REPEAT
Automatize seus testes e garanta qualidade da equipe
Saturday, July 9, 2011
70. CONTINUOS INTEGRATION
• “Integração contínua”
• Processo automatizado
• Executado após cada commit
• Identifica falhas
• Identifica culpados
• Controla qualidade
Saturday, July 9, 2011