Tableless

Busca Menu

PHPUnit – persistência e configurações avançadas

Seja o primeiro a comentar por

Neste artigo você verá como utilizar o PHPUnit para realizar testes com persistência de dados utilizando o Doctrine um ORM open-source e como definir configurações avançadas para personalizar sua suíte de testes e gerar relatórios de testes executados bem como cobertura do código de produção.

 Começando

Para começar o projeto crie um arquivo chamado composer.json. Nele listaremos todos os pacotes/bibliotecas de terceiros que utilizaremos. Para este post utilizaremos o Doctrine e vários elementos do Zend Framework 2 além de é claro o próprio PHPUnit. Abaixo segue a lista de todas as bibliotecas que serão utilizadas.

 "require" : {
    "doctrine/common" : "*",
    "doctrine/dbal": "*",
    "doctrine/orm" : "*",
    "phpunit/phpunit": "3.7.*",
    "zendframework/zend-stdlib": "2.3.*@dev",
    "zendframework/zend-filter": "2.3.*@dev",
    "zendframework/zend-servicemanager": "2.3.*@dev",
    "zendframework/zend-crypt": "2.3.*@dev",
    "zendframework/zend-math": "2.3.*@dev"
 }

Seguindo as recomendações da FIG, utilizaremos a PSR-0 que trata sobre a forma de carregarmento de classes na aplicação que estamos desenvolvendo. Com isso trabalharemos com namespaces e não precisaremos utilizar require ou include nas classes que utilizaremos. Para que o projeto tenha suas classes carregadas conforme a PSR-0 podemos informar isso no arquivo composer.json.

 "autoload" : {
    "psr-0": {
        "Tableless\\": "src/"
    }
 }

Isto nos diz que o namespace “Tableless” estará presente na pasta src e para isto se faz necessária a criação da pasta src e dentro da mesma a pasta Tableless. Há outra maneira de registrar o namespace através do boostrap.php que seria algo como:

 $load = require __DIR__ . '/vendor/autoload.php';
 $load->add('Tableless', __DIR__ . '/src');

O arquivo bootstrap.php é comumente utilizado para realizar as configurações iniciais em vários frameworks. Basicamente ele inclui o autoload.php gerado pelo composer e podem ser definidas as mais diversas configurações globais de sua aplicação no mesmo.

Feito isso baixamos o composer utilizando o comando curl -sS https://getcomposer.org/installer | php e em seguida instalamos as dependências através do comando php composer.phar install.

Instalando composer e dependências

Com a instalação das dependências agora temos a nova estrutura contendo uma pasta vendor contendo todas as bibliotecas de terceiros, um novo arquivo composer.lock e composer.phar os quais já foram descritos em outro artigo sobre PHPUnit com composer e que pode ser acessado aqui.

Nova Estrutura

Próximo passo

Agora temos de criar um arquivo que será o pontapé inicial da aplicação, arquivo este comumente nomeado de bootstrap conforme já mencionado anteriormente. Nele são configurados onde se encontram as entidades – que serão explicadas mais a frente deste tutorial, configuração do banco de dados entre outras configurações. Como neste exemplo será utilizado o Doctrine, precisamos configurar o mesmo.

Crie um arquivo chamado bootstrap.php na raiz de seu projeto, o fonte do bootstrap.php está comentado para melhor entendimento.

<?php
// Carregando o autoload que o composer gerou
require __DIR__ . '/vendor/autoload.php';
// indicando tudo que usaremos no bootstrap
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
/**
* Definindo se é modo desenvolvimento
* 
* Caso true: o cache do Doctrine é realizado em formato de array
* Caso false: o cache é conforme configuração (memcache, APC..)
* 
* Somente trabalharemos aqui com o modo TRUE, cache em array
*/
$config = Setup::createConfiguration( true );
// pasta onde encontram-se nossas entidades
$entitypath = array( __DIR__ . '/src/Tableless/Entity' );
// registrando as entidades
$driver = new AnnotationDriver(new AnnotationReader(), $entitypath);
$config->setMetadataDriverImpl($driver);
/**
* indicando que trabalharemos com o modo annotations para
* as entidades. Pode ser também via arquivo yaml e xml
* 
*/
AnnotationRegistry::registerFile(__DIR__ 
. '/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
// configurando a conexão com o banco de dados
$conn = array(
    'driver' => 'pdo_mysql',    
    'user' => 'root',
    'password' => 'root',
    'dbname' => 'tableless_tdd',
);
// E finalmente criando o manipulador de entidades
$entityManager = EntityManager::create($conn, $config);

Até agora você viu várias vezes a palavra “Entidade” mas o que ela significa? Entidade é um objeto que tem um significado conceitual dentro de um domínio. Em outras palavras, cada entidade no Doctrine é a representação de uma tabela no banco de dados e cada registro é uma instância desta entidade. A entidade não manipula o banco de dados, apenas representa-o.

Pronto, a nível de produção já temos a configuração, agora criaremos a estrutura e configurações para testes.

Na raiz de seu projeto crie uma pasta chamada tests, dentro dela uma pasta chamada src e dentro da src uma pasta chamada Tableless. Perceba que o namespace ficará na mesma estrutura do código de produção, desta forma para utilizarmos uma entidade chamada User por exemplo, usaremos a seguinte declaração: use Tableless\Entity\User;. Para a classe de testes de User se for necessária declarar em algum lugar será desta forma: use Tableless\Entity\UserTest;.

Estrutura inicial testes

Após a criação das pastas necessárias falta a criação do bootstrap de testes e de um arquivo de configurações de execução do PHPUnit.

Começando com o bootstrap, o código novamente está comentado explicando porque determinadas coisas estão sendo feitas. Crie o arquivo bootstrap.php dentro da pasta de testes (tests).

 'pdo_sqlite',
    'dbname' => ':memory:',
);
return $entityManager = EntityManager::create($conn, $config);

O bootstrap de testes se faz necessário para sobrescrever a conexão com o banco de dados, caso contrário, todos os testes realizariam alterações no banco de dados de produção e isto jamais deve acontecer.

Feito isto agora é o momento de criar o arquivo xml de configurações do PHPUnit. Crie um arquivo chamado phpunit.xml dentro de sua pasta tests e adicione o conteúdo abaixo.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="bootstrap.php">

<!-- Indicando qual é o diretório onde as classes de teste se encontram -->
    <testsuites>
        <testsuite name="Tableless TDD Test Suite">
            <directory suffix=".php">src/</directory>
        </testsuite>
    </testsuites>

<!-- Adicionando filtros, basicamente whitelist (diretórios que serão executados), 
dentro temos o exclude (diretórios que não serão executados pelos testes) -->

<filter>
    <whitelist>
        <directory suffix=".php">../src/</directory>
        <exclude>
            <directory suffix=".php">./vendor/</directory>
        </exclude>
    </whitelist>
</filter>
</phpunit>

Quase pronto, se rodarmos o comando ./vendor/bin/phpunit -c tests/phpunit.xml dentro da raiz do projeto teremos a mensagem de que nenhum teste foi executado como na imagem abaixo.

Nenhum Teste

 Como estamos trabalhando com um arquivo de configurações, para rodarmos o phpunit seguindo as definições do arquivo precisamos utilizar o parâmetro -c seguido do nome do arquivo.

Obviamente que nenhum teste ainda foi executado porque não temos nenhuma classe de testes. Vamos começar então. Crie uma pasta Entity dentro de tests/src. Dentro desta pasta crie um arquivo chamado UsertTest.php. A nova estrutura de testes deve estar como na imagem abaixo.

Nova estrutura de testes

No arquivo UserTest.php adicione o namespace do mesmo que é Tableless\Entity.

namespace Tableless\Entity;

Agora definimos quais classes utilizaremos para este teste. Como estamos testando a entidade User precisaremos utilizar o Tableless\Entity\User.

use Tableless\Entity\User;

No entanto aí tem um detalhe. A entidade User ainda não existe, mas a criaremos dentro de instantes pois ainda temos uma classe que devemos criar antes mesmo da User. Ela se chama TestCase e deve estar no namespace Tableless\Test. Crie em src/Tableless (não em tests/src/Tableless) uma pasta chamada Test e dentro dela um arquivo chamado TestCase.php.

Criando o TestCase

Neste arquivo copie e cole o código abaixo que está comentado para melhor entendimento.

<?php
namespace Tableless\Test;

use Doctrine\ORM\Tools\SchemaTool;
use PHPUnit_Framework_TestCase as PHPUnit;

abstract class TestCase extends PHPUnit
{
    protected $entityManager = null;

    /**
    * Executado antes de cada teste unitário
    */
    public function setup() 
    {
        $entityManager = $this->getEntityManager(); 
        $tool = new SchemaTool($entityManager);

        //Obtem informações das entidades que encontrar em Tableless\Entity
        $classes = $entityManager->getMetadataFactory()->getAllMetadata();

        // Cria a base de dados necessária com suas determinadas tabelas
        $tool->createSchema($classes);

        parent::setup();
    } 

    /**
    * Executado após a execução de cada um dos testes unitários
    */
    public function tearDown() 
    {
        $entityManager = $this->getEntityManager(); 
        $tool = new SchemaTool($entityManager);

        //Obtem informações das entidades que encontrar em Tableless\Entity
        $classes = $entityManager->getMetadataFactory()->getAllMetadata();

        // Desfaz o banco criado no setUp
        $tool->dropSchema($classes);

        parent::tearDown();
    }

    /**
    * 
    * @return \Doctrine\ORM\EntityManager
    */
    public function getEntityManager() 
    {
        if (! $this->entityManager) {
            $this->entityManager = require __DIR__ . '/../../../tests/bootstrap.php';
        } 
        return $this->entityManager; 
    } 
}

Pronto, já estamos com tudo o que precisamos para começar escrever os testes. Detalhe que esta configuração foi criada para que fosse possível utilizar e testar a persistência de dados utilizando o Doctrine. Para demais testes em controllers, services, views, forms ou o que mais você desejar esta configuração realizada até o momento permanece podendo ser acrescida de novos elementos, tudo depende da necessidade.

Criando o primeiro teste

No arquivo tests/src/Tableless/Entity/UserTest.php começaremos a definir nossos testes. Lembre-se que a ideia do TDD é que o teste seja criado antes do código de produção, e assim faremos.

Pra início de conversa utilizaremos a classe TestCase previamente criada e a entidade User.

use Tableless\Entity\User;
use Tableless\Test\TestCase;

A classe de testes atual (UserTest) extende de TestCase e adicionaremos o atributo protegido $entity.

class UserTest extends TestCase
{
    protected $entity;
}

Assim como a classe TestCase, nossa classe UserTest também possuirá um métdo setUp e um tearDown que servirão para as configurações da mesma. De momento apenas setaremos o valor default do atributo entity no setUp.

public function setUp()
{
    $this->entity = 'Tableless\Entity\User';
};

Agora segue o nosso primeiro teste: Novamente há comentários explicando cada ação.

public function testIfIsSavingAsExpected()
{
    // Criando os dados necessários para salvar o usuário
    $userData = array(
        'id' => 1,
        'name' => 'Nome do usuário',
        'email' => 'usuario@dominio.com',
        'password' => 'xpto',
        'profilePic' => 'image.png'
    );
    /* o Id é gerado automaticamente pelo Doctrine, neste caso estou forçando
    * um Id desejado, mas somente para o teste, para o código de produção
    * isto não se faz necessário
    */

    // Instanciando a entidade usuário definindo todos os atributos à ela
    $user = new User( $userData );

    // salvando o usuário no banco de dados
    $this->getEntityManager()->persist( $user );
    $this->getEntityManager()->flush();

    // Obtendo o usuário salvo
    $registeredUser = $this->getEntityManager()
            ->getRepository($this->entity)
            ->findOneBy(array('email' => 'usuario@dominio.com'));

    // Garantindo que tudo funcionou conforme o esperado
    $this->assertInstanceOf($this->entity, $registeredUser);
    $this->assertEquals($userData['name'], $registeredUser->getName());
}

Se rodarmos o comando ./vendor/bin/phpunit -c tests/phpunit.xml da raiz de nosso projeto deveremos ver o seguinte erro: “PHP Fatal error: Class ‘Tableless\Entity\User …’” isto porque ainda não existe a entidade User pois realizamos o primeiro passo do TDD, o “Red”. Em seguida realizaremos o passo “Green” que consiste em criarmos o código que faça o teste passar e por último o passo “Refactor” que é onde faremos algumas melhorias no código. No código exemplo não existirá duplicidade e/ou partes inconsistentes com isso o Refactor realizará apenas algumas pequenas melhorias, nada mais.

Crie na pasta src (não em tests/src) uma pasta chamada Entity e dentro dela um arquivo chamado User.php. Eis a estrutura da entidade User. Por ser um arquivo muito extenso, colocarei apenas o link do mesmo que encontra-se no github. Tableless\Entity\User

Perceba que existem comentários acima de cada um dos atributos da classe. Isto se dá por estarmos utilizando o Annotations do Doctrine para que os mesmos sejam lidos e mapeados no banco de dados. Em outras palavras, o Doctrine lê a anotação e cria a estrutura da tabela conforme as definições nos comentários. Há a possibilidade de realizar tais definições via xml e também via yaml o que não veremos neste tutorial.

Agora se rodarmos nosso teste novamente o mesmo passará. Ou seja, já temos um código minimamente testado com um início de noção de persistência de dados, veremos uma pequena melhora no código agora e em seguida algumas configurações para a execução dos testes.

./vendor/bin/phpunit -c tests/phpunit.xml

Primeiro teste passando

Definindo hash para senha

Primeiramente no teste adicionaremos uma asserção de que a senha do usuário registrado não é igual a senha que definimos, em string pura. Adicione o trecho de código abaixo em seu teste logo após $this->assertEquals($userData[‘name’], $registeredUser->getName());

// verificando se hash de senha funcionou
$this->assertNotEquals($userData['password'], $registeredUser->getPassword());

Ao rodarmos o teste o mesmo deve quebrar pois ainda não criamos um hash para a senha, desta forma a senha fornecida está em string pura no banco de dados.

 ./vendor/bin/phpunit -c tests/phpunit.xml

Teste falhando hash

Agora, na classe Tableless\Entity\User usaremos as seguintes classes do Zend:

use Zend\Math\Rand;
use Zend\Crypt\Key\Derivation\Pbkdf2;

em setPassword deixaremos adicionaremos a chamada ao método encryptPassword

public function setPassword( $password )
{
    $this->password = $this->encryptPassword($password);
    return $this;
}

E criaremos o método encryptPassword.

public function encryptPassword( $password )
{
   return base64_encode(
    Pbkdf2::calc('sha256', $password, $this->salt, 
            10000, strlen($password*2)));
}

Agora rodando ./vendor/bin/phpunit -c tests/phpunit.xml o teste passa novamente.

teste passando hash

Assim finalizamos o básico da realização de testes utilizando persitência de dados. A partir de agora veremos algumas configurações avançadas que lhe ajudarão muito no feedback dos testes.

Algumas configurações avançadas

Através do arquivo phpunit.xml podemos definir algumas configurações avançadas para a execução dos testes. Começando pela declaração <phpunit>. Atualmente encontra-se desta forma:

<phpunit colors="true" bootstrap="bootstrap.php">

Isto quer dizer que utilizaremos um arquivo de bootstrap e dizemos qual arquivo é e também que queremos coloração no output. Caso colors=”true” não estivesse presente nossa visão ficaria desta forma.

Colors

Podemos definir erros e avisos sendo tratados como exceções.

<phpunit 
    convertErrorsToExceptions="true" 
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    colors="true"
    bootstrap="bootstrap.php"
>

E muitas outras opções. Para conhecer todas as opções de configurações acesse este link.

Certamente que a configuração a seguir é uma que empolga muitos desenvolvedores, logs e coverage. Com logs e coverage você identifica quais testes passaram, quais tiveram exceções, quais não passaram e o mais legal de tudo, o percentual de cobertura de testes que há em seu código de produção. Basicamente ao rodar um teste unitário, ele cobre uma pequena parte de seu código de produção, habilitando coverage você pode verificar quais linhas estão realmente garantidas por testes e quais você ainda tem de trabalhar mais tempo para garantir um mínimo de cobertura necessário para perfeito funcionamento mas principalmente para garantia de evolução de seu software.

Para criar logs utilizamos a tag logging no arquivo phpunit.xml logo após o fechamento da tag </filter>.

<logging>
    <log type="testdox-text" target="data/testdox.txt" />
</logging>

O log acima está gravando em formato de texto um checklist dos testes que existem em todas as classes de teste dentro da suite de testes marcando com x os que foram executados.

Rodando ./vendor/bin/phpunit -c tests/phpunit.xml será criada a pasta tests/data contento o arquivo testdox.txt O nome do arquivo é de sua escolha.

Testdox

Também é possível gerar o testdox em formato html, basta alterar testdox-text para testdox-html e testdox.txt para testdox.html mas o mais comum é ser utilizado em formato txt mesmo.

Existe também a possibilidade de habilitar o testdox em tempo de execução. Basta apenas adicionar o parâmetro –testdox ao rodar os testes. O resultado será como abaixo.

$ ./vendor/bin/phpunit -c tests/phpunit.xml --testdox
PHPUnit 3.7.35 by Sebastian Bergmann.
Configuration read from /home/andre/Documents/Posts/tableless/phpunit-persistencia-de-dados-e-configuracoes-avancadas/sources/tests/phpunit.xml
Tableless\Entity\User
  [x] If is saving as expected
Generating code coverage report in HTML format ... done

Agrupamento de testes

Por certas vezes necessitamos agrupar testes para que rodemos somente determinada sequência sem que os demais sejam executados. Isto é útil para quando temos de realizar uma pequena alteração e não se faça necessário a execução de todos os testes já criados tornando o feedback mais rápido. Comumente isto é utilizado quando se deseja realizar um ajuste pontual e ao ser finalizado todos os testes são executados novamente.

O PHPUnit nos permite trabalhar com grupos os quais veremos sua definição a seguir.

Crie uma pasta chamada Filter em tests/src/Tableless e dentro dela um arquivo chamado CurrencyTest.php. O conteúdo deste arquivo está abaixo.

<?php
namespace Tableless\Filter;
use Tableless\Test\TestCase;
/**
* @group Filter
*/
class CurrencyTest extends TestCase 
{
    public function testIfClassExists()
    {
        $this->assertTrue(class_exists('Tableless\Filter\Currency'));
    }
}

Perceba que antes de ser declarado o nome da classe existe uma anotação @group Filter. É isto que define o grupo ao qual este teste pertence. Faça o mesmo para o teste já existente (tests/src/Tableless/Entity/UserTest.php) anotando-o como @group Entity.

...
/**
* @group Entity
*/
class UserTest extends TestCase
...

Agora que temos a definição dos grupos podemos rodar nossos testes somente de 1 grupo, de um conjunto de grupos ou de todos os grupos sem distinção. Existem duas formas de rodar os testes por grupos, através de parâmetro informado no momento da execução dos testes ou através do arquivo xml de configurações do PHPUnit, veremos ambas.

Via parâmetro

Somente um grupo

$ ./vendor/bin/phpunit -c tests/phpunit.xml --group Entity

Mais de um grupo

$ ./vendor/bin/phpunit -c tests/phpunit.xml --group Entity,Filter

Para que todos os grupos de testes sejam executados basta que não seja informado o parâmetro –group.

Via arquivo de configuração

No arquivo tests/phpunit.xml adicione uma tag <groups> e dentro dela liste os grupos desejados.

<groups>
    <include>
        <group>Entity</group>
    </include>
</groups>

Você deve estar imaginando, se existe uma tag include deve existir uma tag exclude também. Imaginou certo! Dentro de include você adiciona todos os grupos que deseja que sejam executados nos testes já em exclude, todos que NÃO devem ser executados. O excclude é ideal para testes que foram marcados como incompletos ou pulados (skipped).

Após adicionar as tags referentes aos grupos de testes no arquivo xml de configurações não se faz mais necessário informar o parâmetro  –group, basta rodar normalmente.

$ ./vendor/bin/phpunit -c tests/phpunit.xml

Agora sim, o mais legal de todos, Coverage em Html!

Dentro de <logging> adicione uma nova tag chamada <log> conforme o exemplo abaixo.

<log 
    type="coverage-html" 
    target="data/coverage" 
    charset="UTF-8" 
    yui="true" 
    highlight="true"
    lowUpperBound="35"
    highUpperBound="70" />

Basicamente estamos definindo que o coverage será em formato html, que o considerado baixo coverage será de 35% e um bom coverage se dará a partir de 70%. O highlight serve para destacar as linhas que foram cobertas com verde, não cobertas com vermelho e ignoradas permanecem com a cor padrão. Rode o teste novamente.

Agora no browser entre em seu localhost na pasta do projeto em que está trabalhando. Em seguida entre na pasta tests, após isto em data e por último em coverage. Surpreenda-se!

Coverage

Navegando pelos arquivos você identificará o que já está bom e o que precisa ser mais testado. Neste nosso caso chegar a 100% é muito fácil, basta lermos todos os dados do usuário.

No arquivo tests/src/Tableless/Entity/UserTest.php, dentro do único teste que temos adicione os seguintes asserts:

$this->assertEquals(1, $registeredUser->getId());
$this->assertEquals('usuario@dominio.com', $registeredUser->getEmail());
$this->assertNotNull($registeredUser->getSalt());
$this->assertEquals('image.png', $registeredUser->getProfilePic());

Rode os testes novamente e corra pro abraço!

Coverage 100%

Lembrando novamente que para entendimento deste tutorial se faz necessário a leitura dos conteúdos anteriores sobre o tema, sendo eles TDD, por que usar?  e PHPUnit, como iniciar sem dores.

Bonus.

O que fizemos até o momento foi preparar o ambiente de testes e executá-los mas este ambiente ainda não está totalmente pronto para o código de produção pois precisamos de conexão com um banco de dados além de mais uma configuração do Doctrine para que possamos criar o banco de dados a partir de nossas entidades. Ou seja, lembra daquele processo de criar o banco de dados, definir as tabelas e relacionamentos todos antes do código? Com o Doctrine isto não se faz mais necessário, pode ser feito da forma descrita (e tradicional) mas há outra forma bem legal que é uma mão na roda e que mostrarei agora.

Primeiramente precisamos criar um arquivo de configuração para o cli (Command Line Interface) do Doctrine. Na pasta raiz de sua aplicação crie um arquivo chamado cli-config.php e cole o seguinte conteúdo:

//cli-config.php
require 'bootstrap.php';

return \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($entityManager);
Após a criação deste arquivo podemos rodar o seguinte comando ./vendor/bin/doctrine

Aparecerão várias opções de uso que vão desde checagem de status de conexão, validação das entidades, além de outras funcionalidades. Uma coisa que o doctrine não faz realmente é criar a base de dados pois isto depende de cada base pois Mysql é de um jeito, Postgres é de outro, SQL Server é de outro ainda, então esta tarefa ainda é manual.

Para fins didáticos criei uma base chamada tableless_tdd no mysql como definido no arquivo bootstrap.php da raiz do projeto. Você pode alterar o nome se quiser, bem como o próprio banco, experimente o Sqlite se quiser.

Com a base criada rode o comando ./vendor/bin/doctrine orm:validate-schema. Se estiver tudo ok aparecerá algo como a imagem abaixo. Nela informa que o mapeamento das entidades está correto mas o banco ainda não está sincronizado, para sincronizar rode o comando ./vendor/bin/doctrine orm:schema-tool:create. Isto lerá todas as entidades contidas em src/Tableless/Entity e criará a estrutura de tabelas a partir delas.

./vendor/bin/doctrine orm:validate-schema

Doctrine Validate Schema

./vendor/bin/doctrine orm:schema-tool:create

Doctrine create validate

Atualmente possuímos somente a entidade User que indica que uma tabela users será criada no banco de dados. Após a finalização da execução do comando anterior seu banco de dados já estará com a nova estrutura. Ao realizar qualquer alteração na entidade User ou mesmo criar novas entidades você precisará rodar o comando ./vendor/bin/doctrine orm:schema-tool:update com isso aparecerá uma mensagem informando que já há uma estrutura no banco de dados e lhe pede confirmação sobre o que fazer. Você pode ignorar, ver as alterações ou forçar se tiver certeza do que está fazendo ou mesmo se já visualizou as alterações que serão realizadas e está ciente de que está tudo certo. Basta ler as intruções que o próprio Doctrine fornece que você saberá o que fazer, é muito intuitivo.

Finalizando

Agora que você já configurou o Doctrine, já conhece como criar testes unitários resta apenas aperfeiçoar a cada dia. Não existe uma receita, tudo requer empenho e dedicação mas que no final quando você ver aquelas barrinhas verdes mostrando 100% de cobertura se sentirá cada vez mais empolgado e com um código mais estável mas o principal, com um código que pode facilmente evoluir.

Para baixar o código-fonte gerado neste artigo acesse este link do Github.

Publicado no dia