tutorial - test unitaire php symfony




Comment configurer des tests unitaires de base de données dans Symfony2 en utilisant PHPUnit? (2)

Je n'ai jamais utilisé PHPUnit_Extensions_Database_TestCase , principalement parce que pour ces deux raisons:

  • Ça ne va pas bien. Si vous configurez et supprimez la base de données pour chaque test et que vous disposez d'une application qui dépend fortement de la base de données, vous créez et supprimez le même schéma encore et encore.
  • J'aime avoir mes montages non seulement dans mes tests mais aussi dans ma base de données de développement et certains appareils sont même nécessaires pour la production (utilisateur admin initial ou catégories de produits ou autre). Les avoir à l'intérieur d'un xml qui ne peut être utilisé que pour phpunit ne me semble pas correct.

Mon chemin en théorie ...

J'utilise le doctrine/doctrine-fixtures-bundle pour les appareils (peu importe le but) et configure la base de données entière avec tous les appareils. J'exécute alors tous les tests contre cette base de données et m'assure de recréer la base de données si un test l'a changé.

Les avantages sont que je n'ai pas besoin de configurer une base de données si un test ne lit que mais ne change rien. Pour les changements que je dois faire, déposez-le et créez-le à nouveau ou assurez-vous de rétablir les changements.

J'utilise sqlite pour tester car je peux configurer la base de données, puis copier le fichier sqlite et le remplacer par un fichier propre pour ramener la base de données d'origine. De cette façon, je n'ai pas besoin de déposer la base de données, de la créer et de charger à nouveau tous les appareils pour une base de données propre.

... et dans le code

J'ai écrit un article sur comment je fais des tests de base de données avec symfony2 et phpunit .

Bien qu'il utilise sqlite je pense que l'on peut facilement faire les changements pour utiliser MySQL ou Postgres ou autre.

Penser plus loin

Voici quelques autres idées qui pourraient fonctionner:

  • J'ai lu une fois sur une installation de test où avant d'utiliser la base de données, vous démarrez une transaction (dans la méthode setUp), puis utilisez le tearDown pour restaurer. De cette façon, vous n'avez plus besoin de configurer la base de données et vous avez juste besoin de l'initialiser une fois.
  • Ma configuration décrite ci-dessus présente l'inconvénient que la base de données est configurée chaque fois que phpunit est exécuté, même si vous exécutez uniquement des tests unitaires sans interaction avec la base de données. J'expérimente avec une configuration où j'utilise une variable globale qui indique si la base de données a été installée et puis dans les tests appelle une méthode qui vérifie cette variable et initialise la base de données si elle ne s'est pas encore produite. De cette façon seulement quand un test a besoin de la base de données, la configuration se produira.
  • Un problème avec sqlite est qu'il ne fonctionne pas comme MySQL dans de rares cas. J'ai eu un problème une fois où quelque chose se comportait différemment dans MySQL et sqlite provoquant l'échec d'un test quand MySQL fonctionnait. Je ne me souviens pas de ce que c'était exactement.

Je suis assez nouveau dans le monde des tests et je veux m'assurer que je suis sur la bonne voie.

J'essaie de mettre en place des tests unitaires dans un projet symfony2 en utilisant phpunit .

PHPUnit fonctionne et les tests simples du contrôleur par défaut fonctionnent bien. (Pourtant, il ne s'agit pas de tests fonctionnels mais de tests unitaires de mon application.)

Mon projet repose cependant fortement sur des interactions de base de données, et si je comprends bien de la documentation de phpunit , je devrais mettre en place une classe basée sur \PHPUnit_Extensions_Database_TestCase , puis créer des fixtures pour ma base de données et travailler à partir de là.

Cependant, symfony2 ne propose qu'une classe WebTestCase qui ne s'étend que depuis \PHPUnit_Framework_TestCase .

Donc ai-je raison de supposer que je devrais créer mon propre DataBaseTestCase qui copie principalement WebTestCase , la seule différence étant qu'il s'étend de \PHPUnit_Extensions_Database_TestCase et implémente toutes ses méthodes abstraites?

Ou y a-t-il un autre workflow "intégré" recommandé pour symfony2 concernant les tests centrés sur la base de données?

Comme je veux m'assurer que mes modèles stockent et récupèrent les bonnes données, je ne veux pas finir par tester les détails de la doctrine par accident.


Vous pouvez utiliser cette classe:

<?php

namespace Project\Bundle\Tests;

require_once dirname(__DIR__).'/../../../app/AppKernel.php';

use Doctrine\ORM\Tools\SchemaTool;

abstract class TestCase extends \PHPUnit_Framework_TestCase
{
/**
* @var Symfony\Component\HttpKernel\AppKernel
*/
protected $kernel;

/**
 * @var Doctrine\ORM\EntityManager
 */
protected $entityManager;

/**
 * @var Symfony\Component\DependencyInjection\Container
 */
protected $container;


public function setUp()
{
    // Boot the AppKernel in the test environment and with the debug.
    $this->kernel = new \AppKernel('test', true);
    $this->kernel->boot();

    // Store the container and the entity manager in test case properties
    $this->container = $this->kernel->getContainer();
    $this->entityManager = $this->container->get('doctrine')->getEntityManager();

    // Build the schema for sqlite
    $this->generateSchema();


    parent::setUp();
}

public function tearDown()
{
    // Shutdown the kernel.
    $this->kernel->shutdown();

    parent::tearDown();
}

protected function generateSchema()
{
    // Get the metadatas of the application to create the schema.
    $metadatas = $this->getMetadatas();

    if ( ! empty($metadatas)) {
        // Create SchemaTool
        $tool = new SchemaTool($this->entityManager);
        $tool->createSchema($metadatas);
    } else {
        throw new Doctrine\DBAL\Schema\SchemaException('No Metadata Classes to process.');
    }
}

/**
 * Overwrite this method to get specific metadatas.
 *
 * @return Array
 */
protected function getMetadatas()
{
    return $this->entityManager->getMetadataFactory()->getAllMetadata();
}
}

Et puis vous pouvez tester votre entité. Quelque chose comme ceci (en supposant que vous avez une entité Utilisateur)

//Entity Test
class EntityTest extends TestCase {

    protected $user;

    public function setUp()
    {
         parent::setUp();
         $this->user = new User();
         $this->user->setUsername('username');
         $this->user->setPassword('p4ssw0rd');


         $this->entityManager->persist($this->user);
         $this->entityManager->flush();

    }

    public function testUser(){

         $this->assertEquals($this->user->getUserName(), "username");
         ...

    }

}

J'espère que cette aide.

Source: theodo.fr/blog/2011/09/symfony2-unit-database-tests





phpunit