Capítulo 12. Gerador de Esqueleto

O Gerador de Esqueleto do PHPUnit é uma ferramenta que pode gerar esqueletos de classes de teste a partir de classes códigos de produção e vice-versa. Pode ser instalado usando-se o seguinte comando:

pear install phpunit/PHPUnit_SkeletonGenerator

Gerando um Esqueleto de Classe de Caso de Teste

Quando você está escrevendo testes para um código existente, você tem que escrever os mesmos fragmentos de código como:

public function testMetodo()
{
}

de novo e de novo. O Gerador de Esqueleto do PHPUnit pode ajudá-lo analisando o código da classe existente e gerando um esqueleto de classe de caso de teste para ele.

Exemplo 12.1: A classe Calculadora

<?php
class Calculadora
{
public function soma($a, $b)
{
return $a + $b;
}
}
?>


O seguinte exemplo mostra como gerar um esqueleto de classe de caso de teste para uma classe chamada Calculadora (veja Exemplo 12.1).

phpunit-skelgen --test Calculadora
PHPUnit Skeleton Generator 1.0.0 by Sebastian Bergmann.

Wrote skeleton for "CalculadoraTest" to "/home/sb/CalculadoraTest.php".

Para cada método na classe original, haverá um caso de teste incompleto (veja Capítulo 7) na classe de caso de teste gerada.

Classes separadas por nome e o Gerador de Esqueleto

Quando você está usando o gerador de esqueleto para gerar código baseado em uma classe que é declarada em um namespace você tem que fornecer o nome qualificado da classe assim como o caminho para o arquivo-fonte em que está declarado.

Por exemplo, para a classe Calculadora que está declarada no namespace project você precisa invocar o gerador de esqueleto desta forma:

phpunit-skelgen --test -- "project\Calculadora" Calculadora.php
PHPUnit Skeleton Generator 1.0.0 by Sebastian Bergmann.

Wrote skeleton for "project\CalculadoraTest" to "/home/sb/CalculadoraTest.php".

Abaixo está a saída da execução da classe de caso de teste gerada.

phpunit --bootstrap Calculadora.php --verbose CalculadoraTest
PHPUnit 3.8.0 by Sebastian Bergmann.

I

Time: 0 seconds, Memory: 3.50Mb

There was 1 incomplete test:

1) CalculadoraTest::testSoma
This test has not been implemented yet.

/home/sb/CalculadoraTest.php:38
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 0, Incomplete: 1.

Você pode usar a anotação @assert no bloco de documentação de um método para gerar automaticamente testes simples, porém significativos, em vez de casos de testes incompletos. Exemplo 12.2 mostra um exemplo.

Exemplo 12.2: A classe Calculadora com anotações @assert

<?php
class Calculadora
{
/**
* @assert (0, 0) == 0
* @assert (0, 1) == 1
* @assert (1, 0) == 1
* @assert (1, 1) == 2
*/
public function soma($a, $b)
{
return $a + $b;
}
}
?>


Cada método na classe original é verificada por anotações @assert. Estas são transformadas em um código de teste como

 /**
     * Generated from @assert (0, 0) == 0.
     */
    public function testSoma() {
        $o = new Calculadora;
        $this->assertEquals(0, $o->soma(0, 0));
    }

Abaixo está a saída da execução da classe de caso de teste gerada.

phpunit --bootstrap Calculadora.php --verbose CalculadoraTest
PHPUnit 3.8.0 by Sebastian Bergmann.

....

Time: 0 seconds, Memory: 3.50Mb

OK (4 tests, 4 assertions)

Tabela 12.1 mostra variantes suportadas para a anotação @assert e como elas podem ser transformadas em código de teste.

Tabela 12.1. Variantes suportadas da anotação @assert

AnotaçãoTransformada para
@assert (...) == XassertEquals(X, method(...))
@assert (...) != XassertNotEquals(X, method(...))
@assert (...) === XassertSame(X, method(...))
@assert (...) !== XassertNotSame(X, method(...))
@assert (...) > XassertGreaterThan(X, method(...))
@assert (...) >= XassertGreaterThanOrEqual(X, method(...))
@assert (...) < XassertLessThan(X, method(...))
@assert (...) <= XassertLessThanOrEqual(X, method(...))
@assert (...) throws X@expectedException X


Gerando uma Classe Esqueleto de uma Classe de Caso de Teste

Quando você está fazendo Desenvolvimento Guiado por Teste (veja ???) e escreve seus testes antes do código que o teste exercita, o PHPUnit pode ajudá-lo a gerar esqueletos de classe das classes de casos de testes.

Seguindo a convenção de que os testes para uma classe Unidade são escritos em uma classe chamada UnidadeTest, a fonte da classe de caso de teste é pesquisada para encontrar variáveis que referenciem objetos da classe Unidade e analisa que métodos são chamados nesses objetos. Por exemplo, dê uma olhada em Exemplo 12.4 que foi gerado baseado na análise de Exemplo 12.3.

Exemplo 12.3: A classe JogoBolicheTest

<?php
class JogoBolicheTest extends PHPUnit_Framework_TestCase
{
protected $jogo;

protected function setUp()
{
$this->jogo = new JogoBoliche;
}

protected function arremessarVarias($n, $pinos)
{
for ($i = 0; $i < $n; $i++) {
$this->jogo->arremessa($pinos);
}
}

public function testPontuacaoPorJogarNaCanaletaEh0()
{
$this->arremessarVarias(20, 0);
$this->assertEquals(0, $this->jogo->pontuacao());
}
}
?>


phpunit-skelgen --class JogoBolicheTest
PHPUnit Skeleton Generator 1.0.0 by Sebastian Bergmann.

Wrote skeleton for "JogoBoliche" to "./JogoBoliche.php".

Exemplo 12.4: O esqueleto gerado da classe JogoBoliche

<?php
/**
* Generated by PHPUnit_SkeletonGenerator on 2012-01-09 at 16:55:58.
*/
class JogoBoliche
{
/**
* @todo Implement arremessa().
*/
public function arremessa()
{
// Remove the following line when you implement this method.
throw new RuntimeException('Not yet implemented.');
}

/**
* @todo Implement pontuacao().
*/
public function pontuacao()
{
// Remove the following line when you implement this method.
throw new RuntimeException('Not yet implemented.');
}
}
?>


Abaixo está a saída da execução dos testes contra a classe gerada.

phpunit --bootstrap JogoBoliche.php JogoBolicheTest
PHPUnit 3.8.0 by Sebastian Bergmann.

E

Time: 0 seconds, Memory: 3.50Mb

There was 1 error:

1) JogoBolicheTest::testPontuacaoPorJogarNaCanaletaEh0
RuntimeException: Not yet implemented.

/home/sb/JogoBoliche.php:13
/home/sb/JogoBolicheTest.php:14
/home/sb/JogoBolicheTest.php:20

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
Please open a ticket on GitHub to suggest improvements to this page. Thanks!