web-dev-qa-db-de.com

Autoloading von Klassen in PHPUnit mit Composer und autoload.php

Ich habe PHPUnit Version 3.7.19 von Sebastian Bergmann über Composer installiert und eine Klasse geschrieben, die ich gerne als Unit-Test testen möchte.

Ich möchte, dass alle Klassen automatisch in jede Unit geladen werden , ohne dassinclude oder require oben in meinem Test verwendet werden muss. Dies ist jedoch schwierig.

So sieht meine Verzeichnisstruktur aus (ein abschließender Schrägstrich kennzeichnet ein Verzeichnis und keine Datei):

  • composer.json
  • composer.lock
  • komponist.phar
  • lib /
    • rückkehr.php
  • tests /
    • returningTest.php
  • verkäufer/
    • behälter/
      • phpunit
    • komponist/
    • phpunit /
    • symfony /
    • autoload.php

Meine composer.json -Datei enthält Folgendes:

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

Meine returning.php Klassendatei enthält Folgendes:

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

Meine Testdatei returningTest.php enthält Folgendes:

<?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()
    {

    }
}
?>

Wenn ich jedoch ./vendor/bin/phpunit tests von der Befehlszeile aus ausführen, erhalte ich die folgende Fehlermeldung:

PHP Schwerwiegender Fehler: Klasse 'Returning' wurde nicht in .__ gefunden. /files/code/php/db/tests/returningTest.php in Zeile 8

Ich habe festgestellt, dass composer eine autoload.php-Datei in vendor/autoload.php erstellt hat, aber nicht sicher ist, ob dies für mein Problem relevant ist.

In einigen anderen Antworten zu Stack Overflow haben die Leute auch etwas über die Verwendung von PSR-0 in composer und den namespace-Befehl in PHP erwähnt, aber es ist mir nicht gelungen, eine davon zu verwenden.

Bitte helfen Ich möchte nur meine Klassen in PHPUnit automatisch laden, damit ich sie einfach zum Erstellen von Objekten verwenden kann, ohne sich um include oder require kümmern zu müssen.


Update: 14. August 2013

Ich habe jetzt ein Open Source-Projekt mit dem Namen PHPUnit Skeleton erstellt, um Sie beim Einstieg in PHPUnit-Tests für Ihr Projekt zu unterstützen.

55
Jasdeep Khalsa

Nun, zuerst. Sie müssen dem Autoloader mitteilen, wo er die PHP-Datei für eine Klasse finden soll. Dies geschieht durch Befolgung des PSR-0-Standards.

Am besten verwenden Sie Namespaces. Der Autoloader sucht nach einer Acme/Tests/ReturningTest.php-Datei, wenn Sie eine Acme\Tests\ReturningTest-Klasse angefordert haben. Es gibt einige großartige Namespace-Tutorials, einfach suchen und lesen. Bitte beachten Sie, dass der Namensraum nicht ist. Dies ist etwas, das in PHP für das Autoloading verwendet wurde. Es ist etwas, das zum Autoloading verwendet werden kann.

Composer wird mit einem Standard-PSR-0-Autoloader geliefert (der in vendor/autoload.php). In Ihrem Fall möchten Sie den Autoloader anweisen, nach Dateien im Verzeichnis lib zu suchen. Wenn Sie dann ReturningTest verwenden, wird nach /lib/ReturningTest.php gesucht. 

Fügen Sie dies Ihrem composer.json hinzu:

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

Weitere Informationen in der Dokumentation .

Jetzt kann der Autoloader Ihre Klassen finden, die Sie benötigen, um PHPunit mitzuteilen, dass vor dem Ausführen der Tests eine Datei ausgeführt werden muss: eine Bootstrap-Datei. Mit der --bootstrap-Option können Sie angeben, wo sich die Bootstrap-Datei befindet:

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

Es ist jedoch besser, eine PHPunit-Konfigurationsdatei zu verwenden :

<!-- /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>

Jetzt können Sie den Befehl ausführen und die Konfigurationsdatei wird automatisch erkannt:

$ ./vendor/bin/phpunit

Wenn Sie die Konfigurationsdatei in ein anderes Verzeichnis verschieben, müssen Sie den Pfad zu diesem Verzeichnis im Befehl mit der Option -c angeben.

70
Wouter J

[Update2] Eine andere einfachere Alternative ist die Verwendung der autoload-dev-Direktive in composer.json ( reference ). Der Vorteil ist, dass Sie nicht zwei bootstrap.php (eine für prod, eine für dev) pflegen müssen, nur um verschiedene Klassen automatisch laden zu können.

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

[Update] Die Antwort von Wouter J ist vollständiger. Meiner kann aber Leuten helfen, die das automatische Laden von PSR-0 im tests/-Ordner einrichten möchten.
Phpunit scannt alle Dateien mit diesem Muster *Test.php. Wir müssen sie also nicht selbst laden. Andere unterstützende Klassen unter tests/, wie Fixture/Stub oder einige übergeordnete Klassen, möchten wir dennoch automatisch laden.

Eine einfache Möglichkeit besteht darin, zu überprüfen, wie das Composer-Projekt den phpunit-Test selbst einrichtet. Es ist eigentlich sehr einfach. Beachten Sie die Zeile mit "Bootstrap".

referenz: 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>

referenz: 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__);

Die letzte Zeile oben ist das automatische Laden von Phpunit-Testklassen unter dem Namespace Composer\Test.

40
Chuan Ma

Keine dieser Antworten war das, wonach ich suchte. Ja PHPUnit lädt Testdateien, aber keine Stubs/Fixtures. Die Antwort von Chaun Ma schneidet es nicht ab, da vendor/bin/phpunit bereits das automatische Laden beinhaltet. Es gibt also keine Möglichkeit, eine Instanz des Autoloaders dazu zu bringen, an diesem Punkt mehr Pfade zu seinem Stack zu verschieben.

Ich fand das schließlich in den Dokumenten:

Wenn Sie in mehreren Verzeichnissen nach demselben Präfix suchen müssen, geben Sie kann sie als Array als solches angeben:

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

Es gibt eine sehr einfache Möglichkeit, phpunit mit Autoloading und Bootstap einzurichten. Verwenden Sie die --generate-configuration-Option von phpunit, um Ihre phpunit.xml-Konfiguration in wenigen Sekunden zu erstellen -:

vendor/bin/phpunit --generate-configuration

(Oder einfach nur phpunit --generate-configuration wenn phpunit in deinem PATH gesetzt ist). Diese Option ist ab Version phpunit5 verfügbar.

Diese Option fordert Sie auf, Ihre Bootstrap-Datei ( vendor/autoload.php ), Tests und Quellverzeichnisse einzugeben. Wenn Ihr Projekt mit Composer-Standardeinstellungen eingerichtet ist (siehe Verzeichnisstruktur unten), sind die Standardoptionen alles, was Sie benötigen. Einfach dreimal RETURN drücken!

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

Sie erhalten eine phpunit.xml-Standarddatei, die einsatzbereit ist. Sie können natürlich bearbeiten, um alle Spezialisierungen (z. B. colors="true") einzuschließen, die Sie benötigen:

<?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

Wenn Sie PHPUnit 7 verwenden, können Sie Ihre Klassen aus dem src/-Ordner erstellen und in Tests wie folgt automatisch laden:

  1. Stellen Sie sicher, dass Ihre composer.json-Datei folgendermaßen aussieht:

    {
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "require-dev": {
            "phpunit/phpunit": "^7"
        }
    }
    
  2. Um änderungen anwenden in composer.json ausführen zu lassen:

    composer install
    
  3. Schließlich können Sie Tests im tests/-Ordner ausführen:

    ./vendor/bin/phpunit tests/
    
0
yesnik