4

自動ロード ( http://www.php-fig.org/psr/psr-0/ ) と PHPunit テスト ( https://phpunit.de/manual/current/en/organizing-tests.html )にはルールがあります。個別に実装するのは簡単ですが、それらを組み合わせるのは簡単ではありません。

テストを整理するためのPHPUnitのベストプラクティスのトピックも読みましたが、答えを適用することは私には明らかではありません。私自身のプロジェクトを書いているときに、おそらくコード構成に同じ起源を持ついくつかの問題がありました。本当に簡単な例のレシピがあればいいのにと思います。したがって、私は自分の質問をかなり大きくします。

サンプルプロジェクト

PHPUnit、SVN、および Doxygen をサポートしているため、私はNetBeans IDE 7.4を使用しています (ただし、その 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

以来src、名前空間ではありません

  • ファイルsrc/MyPack/Foo/Bar.phpにはクラスが含まれていますMyPack\Foo\Bar
  • ファイルsrc/MyPack/Quu/Baz.phpにはクラスが含まれていますMyPack\Qoo\Baz
  • ファイルsrc/Client.php にはクラスが含まれていますClient

srcAutoload.phphttps://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 は test ディレクトリを再帰的にトラバースすることで、テストを自動的に検出して実行できます。私にはうまくいきません。my がない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 ではソース フォルダーをテスト フォルダーとして使用できないため、同じクラスに対して 2 つのオートローダーが必要です。それが良い習慣かどうかはわかりません。

オートロードは、同じプロジェクトで作業している他のプログラマーを悩ませるべきではありません。もっと一般的なものを探します。

また、将来的にはサードパーティのコードを使用できます。彼らのオートローダーも複製する必要がありますか?

src/およびtests/フォルダは最上位にする必要がありますvendor/

私はしばらく前にオートローディングのルールを学んでいます。src/PSR-0 は PSR-4 に従って非推奨としてマークされており、パスの途中に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

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.phpMyPack\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. ツールを設定する

PHPUnit が含まれている場所を NetBeans に伝えます。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) を選択します。

これにより、次の 2 つの目標が達成されます。 - オートローダーを生成し、テスト クラスが src クラスを使用できるようにする - ヒンティング目的で PHPUnit ライブラリをプロジェクトに追加する

6. ブートストラップファイルの設定

ブートストラップ ファイルは、テストの前に実行されます。このプロジェクトでは vendor/autoload.php で十分です。

  1. プロジェクト名を右クリックし、コンテキスト メニューから[プロパティ] を選択します。
  2. カテゴリ: テスト/PHPユニット
    • ブートストラップを使用するにチェックを入れる
    • ブートストラップ: PROJECT_MAIN_DIR\vendor\autoload.php

プロジェクトの構造

テスト クラスが間違ったパスに配置されている

ここに画像の説明を入力

手動で移動できます

ここに画像の説明を入力

テストはどちらの方法でも実行されます。

トラブル

PHPUnit 4.8 が動作しない

バージョン 4.8.0 および 4.8.6 の PHPUnit は機能しません。メッセージが届きます unrecognized option --run

したがって、PHPUnit 4.7.7 を使用する必要があります

PHPUnit Skeleton Generator 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 に答える
2

男、なんて大きな質問だ。:) わかりました、いくつかの問題に取り組みましょう。

  1. PHPUnit Skelgen テストの間違ったパス

    それは間違いなくミラー対称ではありません

    真実。これは、スケルゲンの奇妙な (そして未解決だと思う) パスの問題です。

    生成された *Test ファイルを正しいフォルダーに移動するだけです。

    ここで同じ質問: PHPUnit、Netbeans、Symfony2、および間違ったテストの場所

  2. プロジェクトのフォルダー構造

    はい、これは使用するフォルダー構造です。

    src/
       … my code
    tests/
       … my tests 
    vendor/
       … third-party code
    
  3. 自動読み込みの問題:

    (Composer なし): オートローダーは のどこかにありsrcます。アプリケーションのブートストラップ中にそれが必要になり、その後、srcフォルダーの自動読み込みがセットアップされます。srcフォルダ内のすべてのクラスは、今後自動ロードされます。

    テストに移りましょう: テスト ブートストラップ中に、オートローダー from をインクルードし、 srcと を追加srctestます。これにより、すべてのクラスが自動ロード可能にsrcなりtestsます。

    (Composer を使用): Composer を使用している場合、この問題全体は問題になりません。Composer には、ベンダーの依存関係を定義するための require セクションと require-dev セクションがあります。オートロードは自動的に生成されます。Composer オートロード ファイルを含めるだけで完了します (src ブートストラップ中に 1 つ、テスト ブーストラップ中に 1 つ含めます)。プロジェクトが開発依存関係とともにインストールされている場合、それらは自動読み込みの一部になります。そうでない場合、それらは表示されません。

  4. NetBeans での PHPUnit のヒントなし

    はい、PHAR はイントロスペクトまたは抽出されないため、Netbeans は PHPUnit のクラス名を認識しません。

    解決策 1: PHAR を抽出します。

    解決策 2: クラス名をエイリアスとして使用して PHP を追加し、Netbeans をガイドします。周りにいるかどうかはわかりません。しかし、これはかなり一般的な問題であり、誰かが既に作成している可能性が高いです。

    解決策 3: もう一度 Composer を提案させてください。phpunit を require-dev 依存関係としてプロジェクトにプルするだけです。ベンダー パスは Netbeans によってスキャンされ、クラス名が解決されます。

于 2015-03-25T14:36:37.063 に答える