有自动加载规则(http://www.php-fig.org/psr/psr-0/)和 PHPunit 测试(https://phpunit.de/manual/current/en/organizing-tests.html)。分开它们很容易实现,但组合起来却不是。
我还阅读了一个 PHPUnit 最佳实践来组织测试的主题,但应用答案对我来说并不明显。编写我自己的项目时,我遇到了几个问题,这些问题可能与代码组织的起源相同。我希望我能有一个真正简单的例子的食谱。因此,我提出了很大的问题。
示例项目
我使用NetBeans IDE 7.4因为它支持 PHPUnit、SVN 和 Doxygen(但我缺乏使用该 IDE 的经验)。
项目属性是
- 项目文件夹:C:\xampp\htdocs\myapps\PhpProject1
- 源文件夹:C:\xampp\htdocs\myapps\PhpProject1
- 测试文件夹:C:\xampp\htdocs\myapps\PhpProject1\tests
有第一个问题。NetBeans 从一开始就阻止了镜像 src/tests 结构。Source Folder没有Browse按钮。Test 文件夹必须不同于Source 文件夹。
我使用位于项目外部的 PHAR 文件中的 PHPUnit 和 skelgen。(工具->选项->PHP/PHPUnit)
- PHPUnit 脚本:C:\xampp\phar\phpunit.phar
- 骨架生成器脚本:C:\xampp\phar\phpunit-skelgen-1.2.1.phar
我在项目目录中有以下文件结构
index.php
src/
Client.php
srcAutoload.php
MyPack/
Foo/
Bar.php
Quu/
Baz.php
wheresrc
不是命名空间,因为
- 文件
src/MyPack/Foo/Bar.php
包含类MyPack\Foo\Bar
- 文件
src/MyPack/Quu/Baz.php
包含类MyPack\Qoo\Baz
- 文件
src/Client.php
包含类Client
srcAutoload.php
包含来自https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md的修改后的 PSR-0 自动加载实现。不同之处在于在执行require()
PSR-0 文件名之前以src/
$fileName = 'src' . DIRECTORY_SEPARATOR . $fileName;
测试生成和自动加载问题
我为和类使用了工具/创建测试(从上下文菜单中),最终得到以下结构Bar
Baz
index.php
src/
Client.php
srcAutoload.php
MyPack/
Foo/
Bar.php
Quu/
Baz.php
tests/
src/
BarTest.php
BazTest.php
MyPack/
Foo/
Quu/
这绝对不是镜像对称的。此外,生成的测试不知道如何加载他们正在测试的类。
Fatal error: Class 'MyPack\Foo\Bar' not found in C:\xampp\htdocs\myapps\PhpProject1\tests\src\BarTest.php on line 20
我的自动加载解决方法
如前所述,测试运行器的工作目录与项目不同。所以用于测试的自动加载器应该创建不同的完整文件名。我复制了 PSR-0 自动加载器,将其另存为tests/srcAutoloadFromTests.php
并添加了另一个前缀
/// after PSR-0 implementation code
/// I have PSR-0 $fileName
/* Escaping from tests subfolder by "../" prefix*/
$fromTests = '..' . DIRECTORY_SEPARATOR;
/* Prefixing full filename with "src/" */
$fileName = $fromTests . 'src' . DIRECTORY_SEPARATOR . $fileName;
if (is_file($fileName)) {
require $fileName;
}
之后,我添加了Use Bootstrap (Project Properties->Testing/PHPUnit )。文件tests/bootstrap.php
包含:
require_once 'srcAutoloadFromTests.php';
这个解决方案使 PHPUnit 执行测试,但对我来说看起来很丑。
更具体的问题
为什么镜像src/
对tests/
自动加载没有帮助?
我通过创建正确的文件夹和移动文件手动创建了镜像结构:
index.php
src/
Client.php
srcAutoload.php
MyPack/
Foo/
Bar.php
Quu/
Baz.php
tests/
bootstrap.php
srcAutoloadFromTests.php
MyPack/
Foo/
BarTest.php
Quu/
BazTest.php
根据https://phpunit.de/manual/current/en/organizing-tests.html PHPUnit可以通过递归遍历测试目录自动发现和运行测试。它对我不起作用。如果没有我srcAutoloadFromTests.php
,我会得到与以前的非镜像结构相同的错误。
Fatal error: Class 'MyPack\Foo\Bar' not found in C:\xampp\htdocs\myapps\PhpProject1_1\tests\MyPack\Foo\BarTest.php on line 20
自动加载代码重复怎么办
因为 NetBeans 不允许将源文件夹用作测试文件夹,所以我必须为同一个类设置两个自动加载器。我不确定这是否是一个好习惯。
自动加载不应该打扰其他从事同一项目的程序员。我寻找更通用的东西。
此外,将来我可以使用第三方代码。他们的自动装载机也需要复制吗?
src/
和文件夹是否应该tests/
是顶级的vendor/
我前段时间一直在学习自动加载规则。现在我发现 PSR-0 根据 PSR-4 被标记为已弃用src/
,tests/
应该放在路径中间的某个地方。
但是有一种做法是将第三方代码放在顶级vendor/
文件夹中。src/
和文件夹不tests/
应该放在同一级别。
src/
… my code
tests/
… my tests
vendor/
… third-party code
这使得整个结构更具PSR-0风格。
NetBeans 中没有提示 PHPUnit
在编写 BazTest 和 BarTest 代码时,NetBeans IDE 不会提示 PHPUnit 方法,尽管这两个类都扩展\PHPUnit_Framework_TestCase
namespace MyPack\Foo;
class BarTest extends \PHPUnit_Framework_TestCase { /* ... */ }
是因为我使用 PHAR 的 PHPUnit 吗?
我希望引用这个例子能让我的问题更清楚。感谢您的阅读,我寻求好的建议