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

Posted

技术标签:

【中文标题】使用 Composer 和 autoload.php 在 PHPUnit 中自动加载类【英文标题】:Autoloading classes in PHPUnit using Composer and autoload.php 【发布时间】:2021-06-18 04:55:41 【问题描述】:

我刚刚通过 Composer 安装了 Sebastian Bergmann 的 phpUnit 3.7.19 版,并编写了一个我想进行单元测试的类。

我希望将我的所有类自动加载到每个单元测试中不必在我的测试顶部使用includerequire,但事实证明这很困难! p>

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

composer.json composer.lock composer.phar lib/ returning.php 测试/ returningTest.php 供应商/ 斌/ phpunit 作曲家/ phpunit/ symfony/ 自动加载.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 致命错误:未找到“返回”类 /files/code/php/db/tests/returningTest.php 在第 8 行

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

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

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


更新:2013 年 8 月 14 日

我现在创建了一个名为 PHPUnit Skeleton 的开源项目,以帮助您轻松地为您的项目启动和运行 PHPUnit 测试。

【问题讨论】:

感谢您将问题组织得很好。 【参考方案1】:

嗯,一开始。您需要告诉自动加载器在哪里可以找到类的 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 选项指定引导文件所在的位置:

$ ./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选项把那个目录的路径。

【讨论】:

Wouter,感谢您非常详细的解释。我尝试了这些确切的步骤,但我仍然收到错误PHP Fatal error: Class 'Returning' not found in /files/code/php/db/tests/returningTest.php on line 8。如何找出我做错了什么? @WouterJ &lt;phpunit bootstrap="./vendor/autoload.php"&gt; 只为“lib/”下的类设置自动加载器。您仍然需要在“tests/”下自动加载类。 @ChuanMa 不,PHPunit 会扫描tests/ 目录并运行测试类,那里已经自动加载了。 @jasdeepkhalsa 更新 composer.json 文件后,您是否运行过“composer.phar install”?它应该在那之后工作(它对我有用)。该命令所做的是更新此自动加载器文件(vendor/composer/autoload_namespaces.php)以自动加载返回类。仅更改 composer.json 是不够的。 我的问题在于phpunit.xml 文件中没有bootstrap="./vendor/autoload.php"。现在它自动加载正常!谢谢!【参考方案2】:

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


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

[更新] 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 测试类。

【讨论】:

同样使用“require-dev”块而不是“require”块在composer.json中添加phpunit包。您不希望在生产中安装 phpunit 代码。有关更多信息,请参阅作曲家文档。 值得一提的是,您应该在进行此更改后运行composer dump-autoload --optimize。这将重新生成需要包含在项目中的所有类的列表。【参考方案3】:

这些答案都不是我想要的。是的 PHPUnit 加载测试文件,但不加载存根/固定装置。 Chaun Ma 的回答并没有削减它,因为运行 vendor/bin/phpunit 已经包含自动加载,所以没有办法让自动加载器的实例在那时将更多路径推送到它的堆栈。

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

如果您需要在多个目录中搜索相同的前缀,您 可以将它们指定为数组:


    "autoload": 
        "psr-0":  "Monolog\\": ["src/", "lib/"] 
    

【讨论】:

是的。最新的 phpunit 已经包含 composer autoloader。但是我的方法仍然有效(我们已经使用了将近 2 年了)。好处是我们不想在生产中自动加载测试类。这是另一个有用的 SO 链接(由作曲家维护者回答):***.com/questions/12790681/… 请注意,即使 vendor\bin\phpunit 已经是 require composer 的自动加载器类,它不会阻止您再次使用 require 并获取 $loader 对象来添加新类。【参考方案4】:

有一种非常简单的方法可以设置 phpunit 并自动加载和引导。使用 phpunit 的 --generate-configuration 选项创建您的 phpunit.xml 配置几秒钟内-:

vendor/bin/phpunit --generate-configuration

(或者只是phpunit --generate-configuration,如果你的PATH中设置了phpunit)。从 phpunit5 及更高版本开始提供此选项。

此选项将提示您输入引导文件 (vendor/autoload.php)、测试和源目录。如果您的项目使用 composer 默认设置(请参见下面的目录结构),则默认选项将是您所需要的。只需按三下 RETURN!

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

你会得到一个默认的 phpunit.xml,这很好。您当然可以编辑以包含您需要的任何专业(例如colors="true")-:

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

【讨论】:

【参考方案5】:

如果您使用PHPUnit 7,您可以将src/ 文件夹中的类自动加载到测试中,如下所示:

    确保您的 composer.json 文件与此类似:

    
        "autoload": 
            "classmap": [
                "src/"
            ]
        ,
        "require-dev": 
            "phpunit/phpunit": "^7"
        
    
    

    composer.json 运行命令中应用更改

    composer install
    

    终于可以在tests/ 文件夹中运行测试了:

    ./vendor/bin/phpunit tests/
    

【讨论】:

以上是关于使用 Composer 和 autoload.php 在 PHPUnit 中自动加载类的主要内容,如果未能解决你的问题,请参考以下文章

composer install 和updaterequire的使用

composer 安装和修改中国镜像

Composer 安装和使用

PHP composer 日常使用和理解

Composer安装和使用

composer安装和使用