我有一个具有以下结构的项目:
- src + Guitar.php + Type.php + ToString.php - tests + GuitarTest.php composer.json
这就是我在composer.json中定义psr-4自动加载的方式:
"autoload": { "psr-4": { "Shop\Guitar\": "src/" } }
这是我的 Guitar.php:
<?php namespace Shop\Guitar; require_once __DIR__ . '/../vendor/autoload.php'; use Shop\Guitar\Type; class Guitar { public function __construct(public readonly string $serialNumber, public readonly Type $type) { } }
这是我的 ToString.php:
<?php namespace Shop\Guitar; require_once __DIR__ . '/../vendor/autoload.php'; interface ToString { public function toString(): string; }
这是我的 Type.php:
<?php namespace Shop\Guitar; require_once __DIR__ . '/../vendor/autoload.php'; enum Type implements ToString { case ACOUSTIC; case ELECTRIC; public function toString(): string { return match($this) { self::ACOUSTIC => 'Acoustic', self::ELECTRIC => 'Electric', }; } }
这是我的 GuitarTest.php:
<?php require_once __DIR__ . '/../vendor/autoload.php'; use PHPUnit\Framework\TestCase; use Shop\Guitar\Guitar; use Shop\Guitar\Type; final class InventoryTest extends TestCase { public function testGuitarConstructor(): void { $guitar = new Guitar('foo', Type::ELECTRIC); } }
但是当我运行测试时,出现以下错误:
Error: Class "Shop\Guitar\Guitar" not found
问题是什么?如何解决?
P粉7648364482024-03-27 12:15:40
这只是一个关于 PSR-4 配置中的 Composer 自动加载器的问题。
require_once
调用则不会。这是一个自动加载器,类文件一定不需要自动加载器。如果有疑问,请测试您的自动加载器配置。
后续步骤:
删除那些 require_once
调用,它们只会分散您的注意力并妨碍故障排除。自动加载配置要么有效,要么无效。如果您将包含点分布在不同的文件上,则需要进行更多维护工作,但完全没有必要这样做。
重新组织您的测试
模块以引入自动加载器配置测试,因为您遇到了问题:
将内容从 tests
移至 tests/unit
中,为单元测试提供专用目录。
创建 tests/php
子文件夹并在其中创建 autoloading.php
文件。该文件夹用于 PHP 测试,即直接使用 PHP 执行它们(例如 phptests/php/autoloading.php
)。文件内容:
参考文献:
运行自动加载器配置测试,检查文件是否可以加载
$ php tests/php/autoloading.php
(它不能打印任何内容,但可能会打印任何内容。重要的是它会运行,而不是文件未找到或类似类型的错误。
如果您能够以这种方式执行 PHP 文件,请将其绑定到 Composer 配置中。这样您就可以测试自动加载器配置。
将新脚本添加到您的 composer.json
配置中:
{
"script": {
"post-autoload-dump": [
"@php -dzend.assertions=1 -dassert.exception=0 tests/php/autoloading.php"
]
}
}
参考文献:
并测试它:
$ composer run-script post-autoload-dump > @php -dzend.assertions=1 -dassert.exception=0 tests/php/autoloading.php PHP Warning: assert(): [ ...
(它不能给出输出,这里我添加了一些警告以显示它的外观)
这将运行新的自动加载配置测试,并在警告模式下启用断言。也就是说,如果任何 ***_exists() 函数返回 false,您就会看到错误。这意味着无法加载接口/枚举/类。
您可以通过将 -dassert.exception=0
更改为 -dassert.exception=1
(0
-> <代码>1代码>)。然后测试将以非零代码退出(状态 255
因为未捕获的异常)。
这就是你想要的,将 -dassert.exception=0
更改为 -dassert.exception=1
并再次保存 composer.json
.
然后您可以使用任何转储自动加载器的 Composer 命令来测试您的自动加载器:
作曲家转储自动加载
作曲家安装
作曲家更新
测试愉快。
适当的测试,也许同时检查 phpunit 是否仍在运行:
$ composer exec phpunit -- tests/unit PHPUnit ...
再次进行测试,当您找到罪魁祸首并且一切都恢复正常时,您可以使用单个编写器脚本运行所有测试。
Common 是一个带有单词 test
的脚本:
{
"script": {
"post-autoload-dump": [
"@php -dzend.assertions=1 -dassert.exception=0 tests/php/autoloading.php"
],
"test": [
"@composer dump-autoload",
"@composer exec phpunit"
]
}
}
并且您不需要一直编写 composer run-script test
,只需 composer test
就足够了:
$ composer test
Generating autoload files
Generated autoload files
> @php -dzend.assertions=1 -dassert.exception=1 tests/php/autoloading.php
PHPUnit ...
Time: 28 ms, Memory: 4.00MB
No tests executed!
(在此示例输出中,我尚未配置 phpunit 测试,但您明白了)
那么这是什么样的测试呢?好吧,我称之为配置测试,它只是一个快速检查,您可以在其中验证一些 PHP 内容。不要添加许多这样的测试并保持较小的测试计划。您可以使用它来解决配置项目时遇到的问题。保留长达一年,如果您一直没有错误,那么您可以考虑将其删除。
但是,该示例显示了如何使某些检查更靠近配置位置并将它们绑定在一起。如果存在非零退出状态,Composer 将使整个过程失败。
此外,您可以为每个编写器脚本添加描述,以便显示一条消息:
{
"scripts-descriptions": {
"test": "Runs all tests."
}
}
$ composer list ... test Runs all tests. ...
(请参阅:自定义描述 - Composer 脚本文档)