PHPUnitユニットテストを名前空間階層に編成するための2つのオプションが表示されます。これらの2つのアプローチの利点と欠点は何ですか?私が考慮していない明らかな欠陥があるので、それが明らかにより良い選択になるでしょうか?
\SomeFramework\Utilities\AwesomeClass
のようなサンプルクラスを考えます。
アプローチ1:各TestCaseクラスを、対象のクラスと同じ名前空間に配置します。
\SomeFramework\Utilities\AwesomeClassTest
アプローチ2:各TestCaseを、対象のクラスにちなんで名付けられた名前空間に配置します。
\SomeFramework\Utilities\AwesomeClass\Test
私の提案する解決策とその背後にある理由:
_.
├── src
│ ├── bar
│ │ └── BarAwesomeClass.php
│ └── foo
│ └── FooAwesomeClass.php
└── tests
├── helpers
│ └── ProjectBaseTestClassWithHelperMethods.php
├── integration
│ ├── BarModuleTest.php
│ └── FooModuleTest.php
└── unit
├── bar
│ └── BarAwesomeClassTest.php
└── foo
└── FooAwesomeClassTest.php
_
_helpers/
_フォルダーには、テストではないがテストコンテキストでのみ使用されるクラスが含まれています。通常、そのフォルダーにはBaseTestClassが含まれている可能性があり、おそらくプロジェクト固有のヘルパーメソッドと、再利用が容易なスタブクラスがいくつか含まれているため、モックはそれほど必要ありません。
_integration/
_フォルダーには、より多くのクラスにまたがるテストとシステムの「より大きな」部分をテストするテストが含まれています。それほど多くはありませんが、本番クラスへの1対1のマッピングはありません。
_unit/
_フォルダーは、1:1を_src/
_にマップします。したがって、すべての製品クラスには、そのクラスのすべてのnitテストを含む1つのクラスがあります。
アプローチ1:各TestCaseクラスを、対象のクラスと同じ名前空間に配置します。
このフォルダーアプローチは、アプローチ1を使用して、欠点の1つを解決する必要があります。純粋な1対1のマッピングで得られるよりも多くのテストを実行できる柔軟性がまだありますが、すべてが順序正しく配置されています。
名前空間の使用の背後にある原則に違反しているようです-無関係なテストは同じ名前空間にグループ化されています。
テストに「無関係」と思われる場合は、量産コードにも同じ問題があるのでしょうか?
テストが相互に依存していないのは事実ですが、テストは「近い」クラスをモックとして使用するか、DTOまたは値オブジェクトの場合は実際のクラスを使用する場合があります。だから私はつながりがあると思います。
アプローチ2:対象のクラスにちなんで名付けられた名前空間に各TestCaseを配置します。
これを行うプロジェクトはいくつかありますが、通常は少し異なって構成されています。
これは_\SomeFramework\Utilities\AwesomeClass\Test
_ではなく_\SomeFramework\Tests\Utilities\AwesomeClassTest
_であり、1:1マッピングを保持していますが、追加のテスト名前空間が追加されています。
私の個人的な見解では、個別のテスト名前空間を持つことは好きではないので、その選択に対する賛成と反対の議論をいくつか見つけようとします。
実際のクラスが別の名前空間にある場合、テストはそのクラスを独自のモジュールの外で使用する方法を示します。
実際のクラスが同じ名前空間にある場合、テストはそのモジュール内からそのクラスを使用する方法を示します。
違いはごくわずかです(通常、「使用」ステートメントまたは完全修飾パスのカップル)。
PHP 5.5の代わりに$this->getMock(AwesomeClass::CLASS)
と言う可能性がある場合、$this->getMock('\SomeFramework\Utilities\AwesomeClass')
ではなく、すべてのモックにuseステートメントが必要になります。
私にとって、モジュール内での使用はほとんどのクラスにとってより価値があります
_new \SomeFramework\Utilities\A
_と言うと、オートコンプリートでAwesomeClass
とAwesomeClassTest
が表示される場合があり、それを望まない人もいます。外部で使用する場合、またはソースを出荷する場合。テストは出荷されないため、もちろん問題にはなりませんが、検討する必要があるかもしれません。
私が使用する3番目のオプションがあり、composer autoloading:Test
名前空間を階層の最初のステップの後に挿入します。この場合、名前空間は\SomeFramework\Tests\Utilities\
になります。そしてあなたのクラスは\SomeFramework\Tests\Utilities\AwesomeClassTest
になります。
次に、テストを他のクラスと一緒に\SomeFramework\Test
ディレクトリに配置するか、別のディレクトリに配置できます。 composer.json
のオートロード情報は次のようになります。
{
"autoload": {
"psr-0": {
"SomeFramework\\": "src/",
}
},
"autoload-dev": {
"psr-0": {
"SomeFramework\\Tests\\": "tests/"
}
}
}
3番目のアプローチの利点は次のとおりです。
私は一貫性を維持するために最初のアプローチを好みます-PHPUnitプラクティスと他のプロジェクトで。さらに、テスト対象のクラスごとに1つのテストケースのみを作成します。それぞれを独自の名前空間に置くのはやり過ぎのようです。 KingCrunchが言ったように、テストするクラスは関連しているため、テストは関連しています。
多くの場合、テストケースにはフィクスチャなどのサポートファイルが必要ですが、それらはクラスの名前が付けられたサブディレクトリ/名前空間に簡単に編成され、複数のテストケースで共有されることがよくあります。
2番目の方法の大きな欠点の1つは、すべてのテストケースの名前がTest
であり、いくつかの影響があることです。