web-dev-qa-db-fra.com

PHPUnit: Comment créer une fonction à appeler une fois pour tous mes tests?

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

Même question avec une fonction oneTimeTearDown().

Est-il possible de le faire dans PHPUnit?

57
snakile

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

Pour le déchirement unique, vous devez utiliser tearDownAfterClass();.

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

87
borrible

Je suis venu sur cette page avec la même question, mais la réponse acceptée est exécutée sur 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. Vous obtenez ainsi une base de données de base pour tous les tests. Je modifie constamment les fichiers de migration à ce stade, donc la configuration de la ligne de base fait vraiment partie de tous les tests.

La migration prend un certain temps, donc je ne veux pas qu'elle s'exécute sur tous les tests.

Ensuite, j'avais besoin de construire la base de données en testant chaque pièce. Je dois écrire un test de commande, mais je dois d'abord créer des produits et le tester, puis je dois tester une fonction d'importation.

Donc, ce que j'ai fait est SUPER facile, mais pas très bien expliqué sur Internet. J'ai créé un test simple pour configurer la base de données. Ensuite, dans votre fichier phpspec.xml, ajoutez une suite de tests ....

<testsuite name="Products">
    <file>tests/in/SystemSetupTest.php</file>
    <file>tests/in/ProductTest.php</file>
    <file>tests/in/ProductImportTest.php</file>
</testsuite>

Et dans le 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:

produits phpunit --testsuite

En fin de compte, c'est une tonne plus facile. Cela me permettra de construire correctement mon système.

De plus, j'utilise laravel 5. Lorsque j'utilise setUpBeforeClass() je me retrouve avec bootstrap problèmes, que je suis sûr que je peux résoudre, mais la méthode que j'utilise ci-dessus fonctionne parfaitement.

7
Iannazzi

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

Cependant, votre question implique que vous utilisez peut-être votre classe de test comme classe de base pour plusieurs classes de test. Dans ce cas, setUpBeforeClass sera exécuté avant chacun. Si vous ne voulez l'exécuter qu'une fois que vous pouvez le protéger avec une variable statique:

abstract class TestBase extends TestCase {

  protected static $initialized = FALSE;

  public function setUp() {
    if (!self::$initialized) {
      // Do something once here for _all_ test subclasses.
      self::$initialized = TRUE;
    }
  }

}

Une dernière option pourrait être un auditeur de test .

4
Dane Powell

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

Vous pouvez l'appeler depuis la ligne de commande

phpunit --bootstrap myBootstrap.php

Ou mettez-le dans le fichier XML, comme ceci:

<phpunit bootstrap="myBootstrap.php">
...
</phpunit>
1
Gustavo Alves

Extension de la réponse acceptée:

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

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

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

        /* your one time setUp here */

        self::$ready = true;
    }
}

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

0
cprn