首页 文章

使用Composer和autoload.php在PHPUnit中自动加载类

提问于
浏览
54

我刚刚通过Composer安装了Sebastian Bergmann的PHPUnit版本3.7.19,并编写了一个我想进行单元测试的课程 .

我希望我的所有课程都自动加载到每个单元测试中 without 必须在我的测试顶部使用 includerequire ,但事实证明这很难!

这是我的目录结构的样子(尾部/斜杠表示目录,而不是文件):

  • composer.json

  • composer.lock

  • composer.phar

  • lib /

  • returning.php

  • 测试/

  • returningTest.php

  • 供应商/

  • bin /

  • phpunit

  • 作曲家/

  • phpunit /

  • symfony /

  • autoload.php

我的 composer.json 文件包括以下内容:

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

我的 returning.php 类文件包括以下内容:

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

我的 returningTest.php 测试文件包括以下内容:

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

    }
}
?>

但是,当我从命令行运行 ./vendor/bin/phpunit tests 时,我收到以下错误:

PHP致命错误:第8行的/files/code/php/db/tests/returningTest.php中找不到“返回”类

我注意到 composervendor/autoload.php 中生成了 autoload.php 文件,但不确定这是否与我的问题相关 .

此外,在Stack Overflow的其他一些答案中,人们提到了在composer中使用PSR-0和在PHP中使用 namespace 命令,但我没有成功使用任何一个 .

请帮忙!我只是想在PHPUnit中自动加载我的类,所以我可以使用它们来创建对象而不必担心 includerequire .


Update: 14th of August 2013

我现在已经创建了一个名为PHPUnit Skeleton的开源项目,以帮助您轻松启动并运行PHPUnit测试,以便为您的项目 .

4 回答

  • 39

    嗯,起初 . 你需要告诉自动加载器在哪里找到类的php文件 . 这是通过遵循PSR-0标准完成的 .

    最好的方法是使用命名空间 . 当您请求 Acme\Tests\ReturningTest 类时,自动装带器会搜索 Acme/Tests/ReturningTest.php 文件 . 有一些很棒的命名空间教程,只是搜索和阅读 . 请注意,命名空间不是PHP中用于自动加载的东西,它可以用于自动加载 .

    Composer附带标准的PSR-0自动加载器( vendor/autoload.php 中的自动加载器) . 在您的情况下,您想告诉自动装带器搜索 lib 目录中的文件 . 然后,当您使用 ReturningTest 时,它将查找 /lib/ReturningTest.php .

    将其添加到 composer.json

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

    the documentation中的更多信息 .

    现在,自动加载器可以找到你需要的类,让phpunit知道在运行测试之前有一个文件要执行:一个bootstrap文件 . 您可以使用 --bootstrap 选项指定引导程序文件的位置:

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

    但是,使用PHPunit configuration file更好:

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

    现在,您可以运行该命令,它将自动检测配置文件:

    $ ./vendor/bin/phpunit
    

    如果将配置文件放入另一个目录,则需要使用 -c 选项将该目录的路径放在命令中 .

  • 0

    [ Update2 ]另一种更简单的替代方法是在 composer.jsonreference)中使用 autoload-dev 指令 . 好处是你不需要维护两个bootstrap.php(一个用于prod,一个用于dev),只是为了自动加载不同的类 .

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

    [ Update ] Wouter J的答案更完整 . 但我的可以帮助想要在 tests/ 文件夹中设置PSR-0自动加载的人 .
    Phpunit使用此模式 *Test.php 扫描所有文件 . 所以我们不需要自己加载它们 . 但是我们仍然希望在 tests/ 下自动加载其他支持类,例如fixture / stub或一些父类 .

    一个简单的方法是查看Composer项目本身如何设置phpunit测试 . 它实际上非常简单 . 注意“bootstrap”行 .

    参考: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>
    

    参考:https://github.com/composer/composer/blob/master/tests/bootstrap.php

    <?php
    
    /*
    * This file is part of Composer.
    *
    * (c) Nils Adermann <naderman@naderman.de>
    * Jordi Boggiano <j.boggiano@seld.be>
    *
    * 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__);
    

    上面的最后一行是在命名空间Composer \ Test下自动加载phpunit测试类 .

  • 6

    这些答案都不是我想要的 . 是PHPUnit加载测试文件,但不加载存根/固定装置 . Chaun Ma 's answer doesn' t切断它因为运行 vendor/bin/phpunit 已经包含自动加载,所以那时有's no way to get an instance of the autoloader to push more paths to it'的堆栈 .

    我最终在文档中找到了这个:

    如果需要在多个目录中搜索相同的前缀,可以将它们指定为数组:{
    “autoload”:{
    “psr-0”:{“Monolog \”:[“src /”,“lib /”]}
    }
    }

  • 68

    如果您正在使用PHPUnit 7您可以在 src/ 文件夹中将您的类设置为自动加载,如下所示:

    • 确保 composer.json 文件与此类似:
    {
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "require-dev": {
            "phpunit/phpunit": "^7"
        }
    }
    
    • apply changes in composer.json run命令:
    composer install
    
    • 最后,您可以在 tests/ 文件夹中运行测试:
    ./vendor/bin/phpunit tests/
    

相关问题