web-dev-qa-db-fra.com

Chargement automatique des classes dans PHPUnit avec Composer et autoload.php

Je viens d'installer PHPUnit version 3.7.19 de Sebastian Bergmann via Composer et j'ai écrit une classe que j'aimerais tester à l'unité.

J'aimerais que toutes mes classes soient automatiquement chargées dans chaque test unitaire sans avoir à utiliser include ou require au début de mon test, mais cela s'avère difficile!

Voici à quoi ressemble ma structure de répertoire (une barre oblique/fin indique un répertoire, pas un fichier):

  • composer.json
  • composer.lock
  • composer.phar
  • lib /
    • rentrant.php
  • tests /
    • returnTest.php
  • vendeur/
    • poubelle/
      • phpunit
    • compositeur/
    • phpunit /
    • symfony /
    • autoload.php

Mon fichier composer.json comprend les éléments suivants:

"require": {
    "phpunit/phpunit": "3.7.*",
    "phpunit/phpunit-Selenium": ">=1.2"
}

Mon fichier de classe return.php comprend les éléments suivants:

<?php
class Returning {
    public $var;
    function __construct(){
        $this->var = 1;
    }
}
?>

Mon fichier de test returnTest.php comprend les éléments suivants:

<?php
class ReturningTest extends PHPUnit_Framework_TestCase
{
    protected $obj = null;

    protected function setUp()
    {
        $this->obj = new Returning;
    }

    public function testExample()
    {   
        $this->assertEquals(1, $this->obj->var);
    }

    protected function tearDown()
    {

    }
}
?>

Cependant, lorsque j'exécute ./vendor/bin/phpunit tests à partir de la ligne de commande, l'erreur suivante apparaît:

Erreur PHP irrécupérable: La classe 'Retourner' ne se trouve pas dans /files/code/php/db/tests/returningTest.php à la ligne 8

J'ai remarqué que composer produisait un fichier autoload.php dans vendor/autoload.php mais je ne savais pas si cela était pertinent pour mon problème.

De plus, dans d'autres réponses sur Stack Overflow, des personnes ont mentionné l'utilisation de PSR-0 dans composer et la commande namespace en PHP, mais je n'ai réussi à utiliser ni l'un ni l'autre.

S'il vous plaît aider! Je veux juste charger automatiquement mes classes dans PHPUnit afin de pouvoir les utiliser pour créer des objets sans me soucier de include ou require.


Mise à jour: 14 août 2013

J'ai maintenant créé un projet Open Source appelé PHPUnit Skeleton pour vous aider à vous familiariser facilement avec les tests PHPUnit pour votre projet.

55
Jasdeep Khalsa

Eh bien, au début. Vous devez dire à l'autochargeur où trouver le fichier php pour une classe. Cela se fait en suivant la norme PSR-0.

Le meilleur moyen consiste à utiliser des espaces de noms. L'autoloader recherche un fichier Acme/Tests/ReturningTest.php lorsque vous avez demandé une classe Acme\Tests\ReturningTest. Il existe de très bons tutoriels sur les espaces de noms, il suffit de chercher et de lire. Veuillez noter que le namespacing est not quelque chose qui est entré dans PHP pour le chargement automatique, il peut être utilisé pour le chargement automatique.

Composer est livré avec un autochargeur standard PSR-0 (celui dans vendor/autoload.php). Dans votre cas, vous souhaitez demander à l'autochargeur de rechercher des fichiers dans le répertoire lib. Ensuite, lorsque vous utilisez ReturningTest, il cherchera /lib/ReturningTest.php

Ajoutez ceci à votre composer.json:

{
    ...
    "autoload": {
        "psr-0": { "": "lib/" }
    }
}

Plus d'informations dans la documentation .

Maintenant, l'autochargeur peut trouver vos classes et vous devez informer PHPunit qu'il doit exécuter un fichier avant d'exécuter les tests: un fichier d'amorçage. Vous pouvez utiliser l'option --bootstrap pour spécifier l'emplacement du fichier d'amorçage:

$ ./vendor/bin/phpunit tests --bootstrap vendor/autoload.php

Cependant, il est préférable d'utiliser un fichier de configuration PHPunit :

<!-- /phpunit.xml.dist -->
<?xml version="1.0" encoding="utf-8" ?>
<phpunit bootstrap="./vendor/autoload.php">

    <testsuites>
        <testsuite name="The project's test suite">
            <directory>./tests</directory>
        </testsuite>
    </testsuites>

</phpunit>

Maintenant, vous pouvez exécuter la commande et il détectera automatiquement le fichier de configuration:

$ ./vendor/bin/phpunit

Si vous placez le fichier de configuration dans un autre répertoire, vous devez indiquer le chemin d'accès à ce répertoire dans la commande avec l'option -c.

70
Wouter J

[Update2] Une autre approche plus simple consiste à utiliser la directive autoload-dev dans composer.json ( reference ). L'avantage est qu'il n'est pas nécessaire de gérer deux fichiers bootstrap.php (un pour prod, un pour dev) uniquement pour charger automatiquement différentes classes.

{
  "autoload": {
    "psr-4": { "MyLibrary\\": "src/" }
  },
  "autoload-dev": {
    "psr-4": { "MyLibrary\\Tests\\": "tests/" }
  }
}

[Update] La réponse de Wouter J est plus complète. Mais le mien peut aider les personnes qui souhaitent configurer le chargement automatique du PSR-0 dans le dossier tests/.
Phpunit analyse tous les fichiers avec ce modèle *Test.php. Nous n'avons donc pas besoin de les charger nous-mêmes. Mais nous souhaitons toujours charger automatiquement d'autres classes de support sous tests/, telles que fixture/stub ou certaines classes parentes.

Un moyen simple est de regarder comment le projet Composer lui-même configure le test phpunit. C'est en fait très simple. Notez la ligne avec "bootstrap".

référence: https://github.com/composer/composer/blob/master/phpunit.xml.dist

<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="Composer Test Suite">
            <directory>./tests/Composer/</directory>
        </testsuite>
    </testsuites>

    <groups>
        <exclude>
            <group>slow</group>
        </exclude>
    </groups>

    <filter>
        <whitelist>
            <directory>./src/Composer/</directory>
            <exclude>
                <file>./src/Composer/Autoload/ClassLoader.php</file>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

référence: https://github.com/composer/composer/blob/master/tests/bootstrap.php

<?php

/*
* This file is part of Composer.
*
* (c) Nils Adermann <[email protected]>
* Jordi Boggiano <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

error_reporting(E_ALL);

$loader = require __DIR__.'/../src/bootstrap.php';
$loader->add('Composer\Test', __DIR__);

La dernière ligne ci-dessus est le chargement automatique des classes de test phpunit sous l'espace de noms Composer\Test.

40
Chuan Ma

Aucune de ces réponses n'était ce que je cherchais. Oui, PHPUnit charge les fichiers de test, mais pas les stubs/fixtures. La réponse de Chaun Ma ne résout pas le problème, car l'exécution de vendor/bin/phpunit inclut déjà le chargement automatique. Il est donc impossible de faire en sorte qu'une instance de l'autochargeur envoie d'autres chemins vers sa pile à ce stade.

J'ai finalement trouvé ceci dans la documentation:

Si vous devez rechercher un même préfixe dans plusieurs annuaires, vous peut les spécifier comme un tableau en tant que tel:

{
    "autoload": {
        "psr-0": { "Monolog\\": ["src/", "lib/"] }
    }
}
6
Josh Ribakoff

Il existe un moyen très simple pour configurer phpunit avec autoloading et bootstap. Utilisez l'option --generate-configuration de phpunit pour créer votre configuration phpunit.xml en quelques secondes -:

vendor/bin/phpunit --generate-configuration

(Ou simplement phpunit --generate-configuration si phpunit est défini dans votre PATH). Cette option est disponible à partir de la version phpunit5.

Cette option vous demandera votre fichier d'amorçage ( vendor/autoload.php ), vos tests et les répertoires source. Si votre projet est configuré avec les valeurs par défaut du compositeur (voir la structure de répertoires ci-dessous), les options par défaut seront tout ce dont vous avez besoin. Il suffit d'appuyer sur RETURN trois fois!

project-dir
   -- src
   -- tests
   -- vendor

Vous obtenez un phpunit.xml par défaut qui est bon à aller. Vous pouvez bien sûr éditer pour inclure les spécialités (par exemple, colors="true") dont vous avez besoin -

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.1/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         executionOrder="depends,defects"
         forceCoversAnnotation="true"
         beStrictAboutCoversAnnotation="true"
         beStrictAboutOutputDuringTests="true"
         beStrictAboutTodoAnnotatedTests="true"
         verbose="true">
    <testsuites>
        <testsuite name="default">
            <directory suffix="Test.php">tests</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">src</directory>
        </whitelist>
    </filter>
</phpunit>
1
suspectus

Si vous utilisez PHPUnit 7 vous pouvez faire en sorte que vos classes du dossier src/ soient automatiquement chargées dans des tests comme celui-ci:

  1. Assurez-vous que votre fichier composer.json ressemble à ceci:

    {
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "require-dev": {
            "phpunit/phpunit": "^7"
        }
    }
    
  2. Pour appliquer les modifications dans composer.json, exécutez la commande:

    composer install
    
  3. Enfin, vous pouvez exécuter des tests dans le dossier tests/:

    ./vendor/bin/phpunit tests/
    
0
yesnik