105 votes

PHPUnit: Comment créer une fonction à appeler une fois pour tous les tests d'une classe?

J'ai une classe de cas de test PHPUnit (consistant en quelques fonctions de test). Je voudrais écrire une fonction oneTimeSetUp() qui sera appelée une seule fois pour tous mes tests dans la classe (contrairement à la fonction standard setUp() qui est appelée une fois pour chaque test dans la classe). En d'autres termes, je recherche l'équivalent de PHPUnit à l'annotation @BeforeClass de JUnit.

Même question avec une fonction oneTimeTearDown().

Est-il possible de le faire avec PHPUnit?

138voto

borrible Points 7069

Jetez un œil à setUpBeforeClass() de la section 6 de la documentation de PHPUnit.

Pour le tearDown unique, vous devriez utiliser tearDownAfterClass();.

Les deux méthodes doivent être définies dans votre classe en tant que méthodes statiques.

30voto

Dane Powell Points 146

setUpBeforeClass() est la manière de le faire si tous vos tests sont littéralement contenus dans une seule classe.

Cependant, votre question semble indiquer que vous pourriez utiliser votre classe de test comme une classe de base pour plusieurs classes de test. Dans ce cas, setUpBeforeClass sera exécuté avant chacune d'entre elles. Si vous voulez le lancer une seule fois, vous pouvez le protéger avec une variable statique :

abstract class TestBase extends TestCase {

  protected static $initialized = FALSE;

  public function setUp() {

    parent::setUp();

    if (!self::$initialized) {
      // Faire quelque chose une fois ici pour toutes les sous-classes de test.
      self::$initialized = TRUE;
    }
  }

}

Une option finale pourrait être un auditeur de test.

14voto

Iannazzi Points 576

Je suis arrivé sur cette page avec la même question, cependant la réponse acceptée s'applique à toutes les classes, et pour moi ce n'était pas la bonne réponse.

Si vous êtes comme moi, votre premier "test d'intégration" consiste à vider la base de données et exécuter les migrations. Cela vous permet d'avoir une base de données de référence pour tous les tests. Je change constamment les fichiers de migration à ce stade, donc la configuration de la base de référence fait réellement partie de tous les tests.

La migration prend du temps, donc je ne veux pas qu'elle soit exécutée pour tous les tests.

Ensuite, j'ai dû construire la base de données en testant chaque élément. Je dois écrire un test sur les commandes, mais d'abord je dois créer quelques produits et les tester, puis je dois tester une fonction d'import.

Donc, ce que j'ai fait est SUPER facile, mais ce n'est pas expliqué de manière très claire sur internet. J'ai créé un simple test pour configurer la base de données. Ensuite, dans votre fichier phpspec.xml, ajoutez un testsuite....

    tests/in/SystemSetupTest.php
    tests/in/ProductTest.php
    tests/in/ProductImportTest.php

Et dans le fichier SystemSetupTest.php ....

class SystemSetupTest extends ApiTester
{

    /** @test */
    function system_init()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        self::createEM(); //this has all the code to init the system...
    }
}

Ensuite, exécutez-le comme :

phpunit --testsuite Products

En fin de compte, c'est beaucoup plus simple. Cela me permettra de construire mon système correctement.

De plus, j'utilise laravel 5. Lorsque j'utilise setUpBeforeClass(), je rencontre des problèmes de démarrage, que je suis sûr de pouvoir résoudre, mais la méthode que j'utilise ci-dessus fonctionne parfaitement.

9voto

Gus Costa Points 533

La option bootstrap peut être utilisée dans ces cas.

Vous pouvez l'appeler depuis la ligne de commande

phpunit --bootstrap myBootstrap.php

Ou le mettre dans le fichier XML, comme ceci:

...

5voto

cprn Points 267

Élargir sur la réponse acceptée:

Aucun des setUpBeforeClass(), tearDownAfterClass(), @beforeClass, @afterClass ne s'exécute dans le contexte de l'objet (méthodes statiques). Vous pouvez contourner cette restriction en protégeant tout code @before avec une propriété statique, comme ceci:

class MyTest extends PHPUnit\Framework\TestCase
{
    private static $ready = false;

    /**
     * @before
     */
    protected function firstSetUp()
    {
        if (static::$ready))
            return;

        /* votre setUp unique ici */

        static::$ready = true;
    }
}

Cela ne peut pas être utilisé pour @after, cependant, car il n'y a pas moyen de dire quand le dernier test a été appelé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X