4

有自动加载规则(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;

测试生成和自动加载问题

我为和类使用了工具/创建测试(从上下文菜单中),最终得到以下结构BarBaz

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

我希望引用这个例子能让我的问题更清楚。感谢您的阅读,我寻求好的建议

4

2 回答 2

2

伙计,多么大的问题。:) 好的,让我们解决一些问题。

  1. PHPUnit Skelgen 测试路径错误

    那绝对不是镜像对称的

    真的。这是 skelgen 的一个奇怪(我认为尚未解决)的路径问题。

    只需将生成的 *Test 文件移动到正确的文件夹中即可。

    同样的问题在这里:PHPUnit、Netbeans 和 Symfony2 和错误的测试位置

  2. 项目的文件夹结构

    是的,这是要使用的文件夹结构:

    src/
       … my code
    tests/
       … my tests 
    vendor/
       … third-party code
    
  3. 自动加载问题:

    (没有 Composer):您的自动加载器位于src. 在您的应用程序引导期间,您需要它,然后为src文件夹设置自动加载。src从现在开始,文件夹中的所有类都是自动加载的。

    现在开始测试:在测试引导过程中,您包括自动加载器 src并添加srctest。这使得所有类都可以src自动tests加载。

    (使用 Composer):如果您使用 Composer,则整个问题都不会成为问题。Composer 有 require 和 require-dev 部分来定义供应商依赖项。自动加载是自动生成的,您只需包含 Composer 自动加载文件并完成(在 src 引导期间包含一个,在测试自举期间包含一个)。如果项目安装了开发依赖项,那么这些将是自动加载的一部分,如果没有,它们将不会出现。

  4. NetBeans 中没有提示 PHPUnit

    是的,PHAR 不是自省或提取的,因此 Netbeans 不会知道 PHPUnit 的类名。

    解决方案 1:提取 PHAR。

    解决方案 2:添加一个以类名作为别名的 PHP 来引导 Netbeans。不知道身边有没有。但这是一个很常见的问题,很可能有人已经创建了它。

    解决方案 3:让我再次建议 Composer:只需将 phpunit 作为 require-dev 依赖项拉入您的项目即可。供应商路径由 Netbeans 扫描,类名将解析。

于 2015-03-25T14:36:37.063 回答
2

Jens A. Koch 的回答非常有帮助。但我想用对我有用的方式来写它们。

任务

使用 NetBeans IDE 7.4 为 PHP 项目编写和运行 PHPUnit 测试。

项目

项目结构

composer.json
index.php
src/
   Client.php
   MyPack/
      Foo/
         Bar.php

在哪里

  • src/Client.php包含在全局命名空间中定义的类
  • src/MyPack/Foo/Bar.php包含在MyPack\Foo命名空间中定义的类
  • composer.jsonsrc/为和tests/目录中定义的类声明需求,即 PHPUnit、PHPUnit Skeleton Generator 和 autoladers

composer.json

{
    "name": "vendor/php-project-with-tests",
    "autoload": {
        "psr-4": { 
            "": ["src/", "tests/"]
        }
    },
    "require": {},
    "require-dev": {
        "phpunit/phpunit": "4.7.7",
        "phpunit/phpunit-skeleton-generator": "2.0.1"
    }
}

脚步

1.设置工具

告诉 NetBeans PHPUnit 包含在哪里。我使用从https://phar.phpunit.de/下载的 PHAR 文件

  1. 选择菜单选项Tools -> Options ,
  2. 选择PHP,然后选择PHPUnit选项卡
  3. 设置脚本:
    • PHPUnit 脚本:MY_PATH\phpunit-4.7.7.phar
    • 骨架生成器脚本:MY_PATH\phpunit-skelgen-1.2.1.phar

2.设置测试目录

  1. 右键单击项目名称,从上下文菜单中选择属性
  2. 类别:来源
    • 测试文件夹最初为空
    • 浏览按钮
    • 在项目目录中创建tests目录并将其用作测试文件夹

3.设置测试提供者

  1. 右键单击项目名称,从上下文菜单中选择属性
  2. 类别:测试
    • 测试提供者:检查PHPUnit

4.生成测试类

  1. 右键单击类文件(例如 Bar.php),从上下文菜单中选择工具 -> 创建测试

5.安装依赖

  1. 右键单击项目名称,从上下文菜单中选择Composer -> Install (dev)

这实现了两个目标: - 生成自动加载器,以允许测试类使用 src 类 - 将 PHPUnit 库添加到项目中以进行提示

6.设置引导文件

引导文件在测试之前执行。对于这个项目 vendor/autoload.php 就足够了。

  1. 右键单击项目名称,从上下文菜单中选择属性
  2. 类别:测试/PHPUnit
    • 检查使用引导程序
    • 引导程序:PROJECT_MAIN_DIR\vendor\autoload.php

项目结构

测试类被放置在错误的路径中

在此处输入图像描述

我可以手动移动它们

在此处输入图像描述

测试以任何一种方式运行。

麻烦事

PHPUnit 4.8 不工作

版本 4.8.0 和 4.8.6 的 PHPUnit 不起作用。我收到消息 unrecognized option --run

所以我必须使用 PHPUnit 4.7.7

PHPUnit 骨架生成器 2.0.1 不工作

PHPUnit Skeleton Generator 2.0.1 无法生成测试。我收到消息 [InvalidArgumentException] Commans "MyPack\Foo\Bar" is not defined

所以我必须使用 PHPUnit Skeleton Generator 1.2.1

于 2015-09-16T09:24:05.617 回答