「PHPUnitテストを書く」の版間の差分

提供:MoodleDocs
移動先:案内検索
編集の要約なし
編集の要約なし
 
(同じ利用者による、間の65版が非表示)
1行目: 1行目:
{{Moodle 2.3}}
各テストの開始時、自動的にリセットされて新しくインストールされた状態となります。
 
作成中です - [[利用者:Mitsuhiro Yoshida|Mitsuhiro Yoshida]] ([[利用者・トーク:Mitsuhiro Yoshida|トーク]])
 
各テストの開始時に自動的にリセットされて新しくインストールされた状態となります。


=ネームスペース=
=ネームスペース=
*/testsディレクトリ以下のすべてのものはネームスペースを使用する場合に[[コーディングスタイル#**/testsディレクトリ内のネームスペース|いくつかの簡単なルールに従う]]必要があります。これらはテストケース、フィクスチャ、ジェネレータ、そして、一般的にはこれらのディレクトリ内すべてのクラスに適用されます。ご覧ください! (要約 = **/classes ディレクトリに適用されるルールと100% 同じです)。
*/testsディレクトリ以下のすべてはネームスペースを使用する場合に[[コーディングスタイル#**/testsディレクトリ内のネームスペース|いくつかの簡単なルールに従う]]必要があります。これらはテストケース、フィクスチャ、ジェネレータ、そして、一般的にはこれらのディレクトリ内すべてのクラスに適用されます。ご覧ください! (要約 = **/classes ディレクトリに適用されるルールと100% 同じです)。
=テストケースクラス=
=テストケースクラス=
すべてのMoodle単体テストで使用される3つの基本テストクラスがあります - basic_testcase、advanced_testcaseおよびprovider_testcaseです。各クラスファイルには1つのテストケースのみを置くことを強く推奨します。
すべてのMoodle単体テストで使用できる3つの基本テストクラスがあります - basic_testcase、advanced_testcaseおよびprovider_testcaseです。各クラスファイルには1つのテストケースのみを置くことを強く推奨します。
;basic_testcase : データベースおよびdataroot、そしてPHPのグローバルを変更しない非常にシンプルなテストです。例えば公式のPHPUnitチュートリアルにある例を試すときに使用します。
;basic_testcase : データベースおよびdataroot、そしてPHPのグローバルを変更しない非常にシンプルなテストです。例えば公式のPHPUnitチュートリアルにある例を試すときに使用します。
;advanced_testcase : Moodleのコードを簡単にテストできるよう強化されたテストケースクラスです。
;advanced_testcase : Moodleのコードを簡単にテストできるよう強化されたテストケースクラスです。
;provider_testcase: [[プライバシーAPI|プライバシープロバイダ]]のテストを容易にするために拡張された拡張テストケースクラスです。4番目のテストケースクラスはMoodleデータベースレイヤのテスト用に特別に設計されているため、他の目的では使用しないでください。
;provider_testcase: [[プライバシーAPI|プライバシープロバイダ]]のテストを容易にするために拡張された拡張テストケースクラスです。4番目のテストケースクラスはMoodleデータベースレイヤのテスト用に特別に設計されているため、他の目的で使用しないでください。
== アサーション Assertions ==
== アサーション Assertions ==
アサーションに関する完全なリストは以下で閲覧可能です。
アサーションに関する完全なリストは以下で確認できます。
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
36行目: 32行目:
|[https://phpunit.de/manual/6.5/en/assertions.html ドキュメンテーション]
|[https://phpunit.de/manual/6.5/en/assertions.html ドキュメンテーション]
|}
|}
==サンプルプラグインテストケース Sample plugin testcase==
==サンプルプラグインテストケース==
PHPUnit テストはプラグインの tests/*_test.phpファイル (例: mod/myplugin/tests/sample_test.php) に配置されます。このファイルにはadvanced_testcaseを継承したクラスを1つだけ含める必要があります。
PHPUnit テストはプラグインのtests/*_test.phpファイル (例: mod/myplugin/tests/sample_test.php) に配置されます。このファイルにはadvanced_testcaseを継承したクラスを1つだけ含む必要があります。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
  namespace mod_myplugin;
  namespace mod_myplugin;
49行目: 45行目:
詳細は[[PHPUnitインテグレーション#クラスおよびファイル命名規則]]をご覧ください。
詳細は[[PHPUnitインテグレーション#クラスおよびファイル命名規則]]をご覧ください。
==Moodleライブラリファイルのインクルード==
==Moodleライブラリファイルのインクルード==
あなたがいくつかのMoodleライブラリファイルをインクルードしたい場合、常に「global $CFG」を宣言する必要があります。これはテストケースファイルは自動的にグローバル$CFGを利用できない非Moodleコードからインクルードされる可能性があることが理由です。
あなたがいくつかのMoodleライブラリファイルをインクルードしたい場合、常に「global $CFG」を宣言する必要があります。これはテストケースファイルが自動的にグローバル$CFGを利用できない非Moodleコードからインクルードされる可能性があることが理由です。
==自動状態リセット==
==自動状態リセット==
デフォルトでは各テスト後にMoodleデータベースおよびdatarootは自動的にインストール直後の状態にリセットされます。データベースまたは標準グローバル変数の変更が予想される場合、$this->resetAfterTest()を使用してください
各テストの後、デフォルトではMoodleデータベースおよびdatarootは自動的にインストール直後の状態にリセットされます。データベースまたは標準グローバル変数の変更が予想される場合、$this->resetAfterTest()を使用してください


あなたが「Warning: unexpected database modification, resetting DB state」というエラーに遭遇した場合、テストが$this->resetAfterTest()を使用していないためだとお考え下さい。
あなたが「Warning: unexpected database modification, resetting DB state」というエラーメッセージに遭遇した場合、テストが$this->resetAfterTest()を使用していないためだとお考えください。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
  namespace mod_myplugin;
  namespace mod_myplugin;
71行目: 67行目:
</syntaxhighlight>
</syntaxhighlight>
=ジェネレータ=
=ジェネレータ=
デフォルトのインストールを修正する必要があるテストは新しいコースやユーザ等の作成にジェネレータを使用できます。このページのすべての例はadvanced_testcaseから派生したテストクラスのテストメソッドから使用する必要があります。
デフォルトのインストールを修正する必要のあるテストでは新しいコースまたはユーザ等の作成にジェネレータを使用できます。このページのすべての例はadvanced_testcaseから派生したテストクラスのテストメソッドから使用する必要があります。


単体テストのパラメータにPHPUnit [https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers @dataProvider]関数を使用している場合、あなたはデータプロバイダ関数でデータジェネレータの使用またはユーザ等を変更できないことに留意してください。データプロバイダでは「データのインスタンス化/生成」をしないでください'。ただ、定義のみしてください。そして、テスト本体ではインスタンス化/生成を進めれます。
単体テストのパラメータにPHPUnit [https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers @dataProvider]関数を使用している場合、あなたはデータプロバイダ関数でデータジェネレータを使用またはユーザ等を変更できないことに留意してください。データプロバイダでは「データのインスタンス化/生成」しないでください'。ただ、定義のみしてください。そして、テスト本体ではインスタンス化/生成を進めれます。


==ユーザを作成する Creating users==
==ユーザを作成する==
それぞれのテスト開始時にはゲストおよび管理者rの2種類のユーザのみ存在します。あなたがさらにテストアカウントを追加する必要がある場合、以下を使用してください:
それぞれのテスト開始時にはゲストおよび管理者の2種類のユーザのみ存在します。あなたがさらにテストアカウントを追加する必要がある場合、以下を使用してください:


<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
127行目: 123行目:
</syntaxhighlight>
</syntaxhighlight>
==コーホートを作成する==
==コーホートを作成する==
{{Moodle 2.4}}
Moodle 2.4以降、データジェネレータは新しいコホートの作成に対応しています。
2.4以降、データジェネレータは新しいコホートの作成に対応しています。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
  $cohort = $this->getDataGenerator()->create_cohort();
  $cohort = $this->getDataGenerator()->create_cohort();
</syntaxhighlight>
</syntaxhighlight>
==ユーザ登録の簡略化==
==ユーザ登録の簡略化==
{{Moodle 2.4}}
標準の登録APIの代わりにデータジェネレータの簡易メソッドを使用できます。これは自己登録および手動登録プラグインと一緒に使用することを意図しています。
標準の登録APIの代わりにデータジェネレータの簡易メソッドを使用できます。これは自己登録および手動登録プラグインと一緒に使用することを意図しています。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
184行目: 178行目:
==リポジトリ==
==リポジトリ==
===リポジトリインスタンスを作成する===
===リポジトリインスタンスを作成する===
{{Moodle 2.5}}
一部のリポジトリプラグインにはインスタンスジェネレータを含むものがあります。ジェネレータクラスは plugindirectory/tests/generator/lib.phpで定義されています。
一部のリポジトリプラグインにはインスタンスジェネレータを含むものがあります。ジェネレータクラスは plugindirectory/tests/generator/lib.php で定義されています。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
$this->getDataGenerator()->create_repository($type, $record, $options);
$this->getDataGenerator()->create_repository($type, $record, $options);
</syntaxhighlight>
</syntaxhighlight>
===リポジトリタイプを作成する===
===リポジトリタイプを作成する===
{{Moodle 2.5}}
一部のリポジトリプラグインにはタイプジェネレータを含むものがあります。ジェネレータクラスはplugindirectory/tests/generator/lib.phpで定義されています。
一部のリポジトリプラグインにはタイプジェネレータを含むものがあります。ジェネレータクラスは plugindirectory/tests/generator/lib.php で定義されています。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
$this->getDataGenerator()->create_repository_type($type, $record, $options);
$this->getDataGenerator()->create_repository_type($type, $record, $options);
212行目: 204行目:
</syntaxhighlight>
</syntaxhighlight>
==他のタイプのプラグイン==
==他のタイプのプラグイン==
{{Moodle 2.5}}
他のどのようなタイプのプラグインでもジェネレータを持てます。ジェネレータクラスではcomponent_generator_baseを継承する必要があります。そして、あなたは $mygenerator = $this->getDataGenerator()->get_plugin_generator($frankenstylecomponentname)でインスタンスを取得できます。
他のどのようなタイプのプラグインもジェネレータを持てます。ジェネレータクラスではcomponent_generator_baseを継承する必要があります。そして、あなたは $mygenerator = $this->getDataGenerator()->get_plugin_generator($frankenstylecomponentname)でインスタンスを取得できます。


いくつかのタイプのプラグインのために上で文書化されたmodのように拡張するcomponent_generator_baseよりも、さらに特定のクラス、例えばtesting_module_generatorのようなクラスがあるかもしれません、そのクラスでは使用すべきメソッド名の一貫したセットを与えることでしょう。そうでなければ、あなたが作業する必要のある異なったものを作成するためにジェネレータ上であなたが好きなどのようなメソッドでも作成できます。
いくつかのタイプのプラグインのために上で文書化されたmodのように拡張するcomponent_generator_baseよりも、さらに特定のクラス、例えばtesting_module_generatorのようなクラスがあるかもしれません、そのクラスでは使用すべきメソッド名の一貫したセットが与えてあることでしょう。そうでなければ、あなたが作業する必要のある別のものを作成するためにジェネレータ上でどのようなメソッドでも好きなように作成できます。
=長いテスト Long tests=
=長いテスト=
標準的なテストはすべて可能な限り高速に実行されるべきです。実行に時間を要するもの (10秒以上) または負荷のかかるもの (たとえば外部のサーバへの問い合わせに開発マシンが殺到してしまった場合等) はPHPUNIT_LONGTESTがtrueの場合のみ実行されるようにしなければなりません。この定数はphpunit.xmlあるいはconfig.phpで直接設定できます。
標準的なテストはすべて可能な限り高速に実行されるべきです。実行に時間を要するもの (10秒以上) または負荷のかかるもの (たとえば外部のサーバへの問い合わせに開発マシンが殺到してしまった場合等) はPHPUNIT_LONGTESTがtrueの場合のみ実行されるようにしなければなりません。この定数はphpunit.xmlあるいはconfig.phpで直接設定できます。
=長いテストデータ=
=長いテストデータ=
大きなテストデータセットをコード内の配列としてではなく、ファイルとして簡単に管理する方法に関して、advanced_testcase::createXMLDataSet()、advanced_testcase::createCsvDataSet()および関連関数を参照してください。詳細はPHPUnit_integration#Extra_methods]]を参照してください。
大きなテストデータセットをコード内の配列としてではなく、ファイルとして簡単に管理する方法に関して、advanced_testcase::createXMLDataSet()、advanced_testcase::createCsvDataSet()および関連関数を参照してください。詳細はPHPUnit_integration#Extra_methods]]を参照してください。
=メッセージ送信テスト=
=メッセージ送信テスト=
{{Moodle 2.4}}
あなたはmessage_send()で送信されたすべてのメッセージを一時的にメッセージシンクオブジェクトにリダイレクトできます。これにより開発者はテストしたコードが期待どおりのメッセージを送信しているかどうか確認できます。
あなたはmessage_send()で送信されたすべてのメッセージを一時的にメッセージシンクオブジェクトにリダイレクトできます。これにより開発者はテストしたコードが期待どおりのメッセージを送信しているかどうか確認できます。


232行目: 222行目:
$messages = $sink->get_messages();
$messages = $sink->get_messages();
$this->assertEquals(3, count($messages));
$this->assertEquals(3, count($messages));
//.. . テストメッセージが正しい順序で、適切な内容で生成されました。
//.. . テストメッセージが正しい順序および適切な内容で生成されました。
</syntaxhighlight>
</syntaxhighlight>
=メール送信テスト=
=メール送信テスト=
{{Moodle 2.6}}
あなたはemail_to_user()で送信されたメールを一時的にメールメッセージシンクオブジェクトにリダイレクトできます。これにより、開発者はテストしたコードが期待とおりのメールを送信しているかどうかを確認できます。
あなたはemail_to_user()で送信されたメールを一時的にemail message sinkオブジェクトにリダイレクトできます。これにより、開発者はテストしたコードが期待通りのメールを送信しているかどうかを確認できます。


メッセージングを使ったコードをテストする場合、まず「noemailever」の設定を解除してください。メールを新しいメッセージシンクにリダイレクトすることにより、 後で結果を確認できます。
メッセージングを使ったコードをテストする場合、まず「noemailever」の設定を解除してください。メールを新しいメッセージシンクにリダイレクトすることにより、 後で結果を確認できます。
257行目: 246行目:
</syntaxhighlight>
</syntaxhighlight>
=あなたのカバレッジを確認する=
=あなたのカバレッジを確認する=
{{Moodle 3.7}}
PHPUnitには単体テストのコードカバレッジ情報を生成する機能があります。
PHPUnit には単体テストのコードカバレッジ情報を生成する機能があります。


Moodle 3.7以前、このカバレッジはすべてのファイルを読み込み、そのファイルが全くカバーできないかどうか、または意図的にカバーされているかどうかに関係なく、すべてに対してカバレッジを生成していました。
Moodle 3.7以前、このカバレッジはすべてのファイルを読み込み、そのファイルが全くカバーできないかどうか、または意図的にカバーされているかどうかに関係なく、すべてに対してカバレッジを生成していました。
264行目: 252行目:
Moodle 3.7以降、「phpunit.xml」設定には各コンポーネントの生成されたカバレッジインクルードおよびエクスクルード情報が含まれています。
Moodle 3.7以降、「phpunit.xml」設定には各コンポーネントの生成されたカバレッジインクルードおよびエクスクルード情報が含まれています。
==インクルードおよびエクスクルード設定を生成する==
==インクルードおよびエクスクルード設定を生成する==
{{Moodle 3.11}}
あなたが書いているテストと一緒に<tt>coverage.php</tt>ファイルを作成することにより、どのファイルがカバレッジのためにチェックされるかプログラム的に記述できます。
あなたが書いているテストと一緒に<tt>coverage.php</tt>ファイルを作成することにより、どのファイルがカバレッジのためにチェックされるかプログラム的に記述できます。


Moodle 4.0以降、デフォルト設定がすべてのプラグインに適用されるため、あなたが追加ファイルをカバーしたい場合を除き、coverage.phpを提供する必要はありません。
Moodle 4.0以降、デフォルト設定がすべてのプラグインに適用されるため、あなたが追加ファイルをカバーしたい場合を除き、coverage.phpを提供する必要はありません。


<tt>coverage.php</tt>ファイルではテスト対象のコンポーネントに含まれるファイルおよびフォルダを一覧表示できます。指定されたすべてのパスはテストされるコンポーネントからの相対パスです。例えば「'mod_forum」を扱う場合、あなたのコードは「'mod_forum」に置かれます。また、単体テストは「mod/forum/tests/example_test.php」にあります。カバレッジファイルは「mod/forum/tests/coverage.php」にあります。指定されたすべてのパスは「mod/forum」からの相対パスとなります。
<tt>coverage.php</tt>ファイルではテスト対象のコンポーネントに含まれるファイルおよびフォルダを一覧表示できます。指定されたすべてのパスはテストされるコンポーネントからの相対パスです。例えば「mod_forum」を扱う場合、あなたのコードは「mod_forum」に置かれます。また、単体テストは「mod/forum/tests/example_test.php」にあります。カバレッジファイルは「mod/forum/tests/coverage.php」にあります。指定されたすべてのパスは「mod/forum」からの相対パスとなります。


含まれるファイル、含まれるフォルダ、除外されるファイルおよび除外されるフォルダを組み合わせて指定できます。これにより、例えば「classes」ディレクトリ全体を含み、その中の特定のファイルまたはフォルダを除外できます。
含まれるファイル、含まれるフォルダ、除外されるファイルおよび除外されるフォルダを組み合わせて指定できます。これにより、例えば「classes」ディレクトリ全体を含みながら、その中の特定のファイルまたはフォルダを除外できます。


以下「mod_forum」の<tt>coverage.php</tt>の例です:
以下「mod_forum」の<tt>coverage.php</tt>の例です:
296行目: 283行目:
また、<tt>@covers</tt>アノテーションの使用により、各テストがどのクラスまたは関数を効果的にカバーしているか、より明確に定義できることに留意してください。詳細は[https://phpunit.readthedocs.io/en/9.5/code-coverage-analysis.html#specifying-covered-code-parts ドキュメンテーション]をご覧ください。
また、<tt>@covers</tt>アノテーションの使用により、各テストがどのクラスまたは関数を効果的にカバーしているか、より明確に定義できることに留意してください。詳細は[https://phpunit.readthedocs.io/en/9.5/code-coverage-analysis.html#specifying-covered-code-parts ドキュメンテーション]をご覧ください。


Moodle 4.0以降、以下のデフォルト設定が適用されます:{{Moodle 4.0}}
Moodle 4.0以降、以下のデフォルト設定が適用されます:
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
return new class extends phpunit_coverage_info {
return new class extends phpunit_coverage_info {
325行目: 312行目:
あなたが単体テストを書く場合に考慮すべきいくつかのベストプラクティス、提案、そして避けるべき点があります。そのいくつかを以下に説明します。
あなたが単体テストを書く場合に考慮すべきいくつかのベストプラクティス、提案、そして避けるべき点があります。そのいくつかを以下に説明します。
==コードカバレッジ==
==コードカバレッジ==
PHPUnitには単体テストのコードカバレッジ情報を生成する機能があり、Moodle 3.7からサポートされています。コードを書く場合、あなたのプラグインのカバレッジのチェックを検討することをお勧めします。
PHPUnitには単体テストのコードカバレッジ情報を生成する機能があり、Moodle 3.7からサポートされています。あなたがコードを書く場合、プラグインのカバレッジの確認を検討することをお勧めします。


[https://phpunit.readthedocs.io/en/9.5/annotations.html#appendixes-annotations-covers-tables-annotations PHPUnitドキュメンテーション]で説明されているように@coversアノテーションを明示的に設定することを推奨します。
[https://phpunit.readthedocs.io/en/9.5/annotations.html#appendixes-annotations-covers-tables-annotations PHPUnitドキュメンテーション]で説明されているように@coversアノテーションを明示的に設定することを推奨します。
331行目: 318行目:
==resetAfterTestの使用を最小限に留める==
==resetAfterTestの使用を最小限に留める==
上で説明した例の多くでは<syntaxhighlight lang="php">resetAfterTest</syntaxhighlight>という命名法を用いてテスト終了後にデータベースおよびファイルシステムをリセットしていますが、 必要がなければこれを使用しないのが理想的でしょう。
上で説明した例の多くでは<syntaxhighlight lang="php">resetAfterTest</syntaxhighlight>という命名法を用いてテスト終了後にデータベースおよびファイルシステムをリセットしていますが、 必要がなければこれを使用しないのが理想的でしょう。
一般的に言えばモック可能で実際の修正を必要としないコードを書くことを目指すべきでしょう。resetAfterTestを使用した場合、テストの速度が低下します。
一般的に言えばモック可能で実際の修正を必要としないコードを書くことを目指すべきでしょう。resetAfterTestを使用した場合、テストの速度は低下してしまいます。


==共有setUpおよびインスタンス変数の扱いに注意する==
==共有setUpおよびインスタンス変数の扱いに注意する==
あなたはPHPUnit のテストでは以下の主な2つの理由のためインスタンス変数の作成方法および使用方法に注意する必要があります:
あなたはPHPUnit のテストで以下の主な2つの理由のためインスタンス変数の作成方法および使用方法に注意する必要があります:
#  あなたがsetUpでフィクスチャを作成またはresetAfterTest関数をコールした場合、 そのフィクスチャおよび条件はテストスイートのすべてのテストに適用されます。これらの条件を満たさないテストをスイートに追加した場合、 その条件が満たされることはありません。これによりテストが遅くなる可能性があります。
#  あなたがsetUpでフィクスチャを作成またはresetAfterTest関数をコールした場合、 そのフィクスチャおよび条件はテストスイートのすべてのテストに適用されます。これら条件を満たさないテストをスイートに追加した場合、 その条件が満たされることはありません。これによりテストが遅くなる場合があります。
# PHPUnit creates an instance of each testcase during its bootstrap phase, and does not dispose of it for the lifetime of the test run. Anything which causes data to be stored as instance data within the testcase will be stored in memory until the _entire suite_ completes. This means that any fixture which is setup and not actively discarded will not be garbage collected and lead to memory bloat. In severe cases this can lead to memory exhaustion.
# PHPUnitは起動時に各テストケースのインスタンスを作成して、 テストが実行される間はそれを破棄しません。テストケース内のデータをインスタンスデータとして保存する場合、_entire suite_が終了するまでメモリに保存されます。これはセットアップされて積極的に破棄されないフィクスチャはガベージコレクションされずにメモリの肥大化に繋がることを意味します。ひどい場合にはメモリの枯渇に繋がる可能性があります。
# PHPUnit は起動時に各テストケースのインスタンスを作成して、 テストが実行される間はそれを破棄しません。テストケース内のデータをインスタンスデータとして保存する場合、_entire suite_が終了するまでメモリに保存されます。これはセットアップされて積極的に破棄されないフィクスチャはガベージコレクションされずにメモリの肥大化につながることを意味します。ひどい場合にはメモリの枯渇に繋がる可能性があります。


Existing testcases which contain setUp which either generate data, or set resetAfterTest should be phased out, and no new cases should be introduced.
データを生成およびresetAfterTestを設定するsetUpを含む既存のテストケースは段階的に廃止して、新しいケースを導入しないでください。
==Make use of the dataProvider functionality==
 
The dataProvider functionality of PHPUnit is an extremely powerful and useful feature which allows you to verify a function quickly and easily with a range of different conditions.
==dataProvider関数を活用する==
However, the following rules should be followed when using dataProviders:
PHPUnitのdataProvider機能は非常に強力で便利であり、 あなたは様々な条件で関数を素早く簡単に検証できます。
* Keep addition of resettable data requring resetAfterTest to a minimum - this will lead to many slow tests
しかし、dataProvidersを使用する場合、以下のルールに従ってください:
* Data providers '''must not instantiate/create data'''. Just define it. And then, the test body can proceed with the instantiation/creation. The dataProvider is called after the testSuite is instantiated, but before any tests are run. Each test will run a full setUp and tearDown, which will destroy any data which was created.
* resetAfterTestを必要とするリセット可能なデータの追加を最小限に抑えてください。
* データプロバイダでは'''データをインスタンス化/生成しないでください'''。データを定義するのみにしてください。そして、テスト本体はインスタンス化/作成に進めます。データプロバイダはtestSuiteがインスタンス化された後、どのテストが実行される前にもコールされます。各テストは完全なsetUpおよびtearDownを実行して、作成されたデータはすべて破棄されます。
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
/**
/**
375行目: 362行目:
}
}
</syntaxhighlight>
</syntaxhighlight>
=Extra test settings=
=追加テスト設定=
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.
通常、テストは外部システムとは連動せずに、どのシステムでも同じように動作する必要があります。しかし、時にはあなたは外部システムとの接続またはシステム構成のために何らかのオプションを指定する必要があります。config.phpから$CFG設定を使用することは意図的に不可能です。
カスタム設定を追加するには以下のようにいくつかの方法があります:
* phpunit.xmlファイルでテスト設定定数を定義する。
* config.phpでテスト設定定数を定義する。
これらの定数はテストまたはプラグインのコードで使用できます。
 
=Moodle 3.11およびそれ以上で動作するよう単体テストをアップグレードする (PHPUnit 9.5)=
Moodle 3.11は'''PHPUnitは9.5'''にアップグレードされました (以前のバージョンでは8.5が使用されていました)。これはMoodle 3.11でサポートされるPHPのバージョン (7.3、7.4、[[MoodleおよびPHP|8.0]]) にテスト環境を合わせるためです (詳細はMDL-71036および関連する報告をご覧ください)。
 
既存のテストの多くはPHPUnit 9.5でもそのまま動作しますが、'''かなりの数の非推奨の警告''' (テストの出力では「W」) が表示されるはずです。これらの警告は次のPHPUnitのアップグレードですべてエラーになるため、'''可能な限り早く新しい対応するものに置き換えるべき'''でしょう。


There are several ways how to inject your custom settings:
PHPUnit 9.5での変更点については以下の資料をご覧ください:
* define test setting constants in your phpunit.xml file
* [https://thephp.cc/news/2020/02/migrating-to-phpunit-9 良記事] リリースの主要な変更点が説明されています。
* define test setting constants in your config.php
* [https://phpunit.de/announcements/phpunit-9.html PHPUnit 9リリースアナウンスメント]
These constants may be then used in your test or plugin code.
* 詳細変更履歴 (いずれも変更を必要とする修正を含んでいるため):  [https://github.com/sebastianbergmann/phpunit/blob/9.0.0/ChangeLog-9.0.md 9.0], [https://github.com/sebastianbergmann/phpunit/blob/9.1.0/ChangeLog-9.1.md 9.1], [https://github.com/sebastianbergmann/phpunit/blob/9.3.0/ChangeLog-9.3.md 9.3], [https://github.com/sebastianbergmann/phpunit/blob/9.5.0/ChangeLog-9.5.md 9.5]
=Upgrading unit tests to work with Moodle 3.11 and up (PHPUnit 9.5)=
* [https://phpunit.readthedocs.io/en/9.5/ 公式PHPUnitマニュアル]
{{Moodle 3.11}}
すべての'''実行すべき変更および置換'''の要約は[https://github.com/moodle/moodle/blob/e3a46964dc6d8ca1558c6e1e8dfdf3c1745eeaed/lib/upgrade.txt#L5-L65 lib/upgrade.txt]ファイルにあります。主なポイントは以下のとおりです:
* PHPUnit 8.5で非推奨となった変更点 (以下のセクションを参照) はすべて削除されたため、エラーが発生するようになりました。
* assertContains()はより厳しく比較するようになりました (assertSame() のように)。新しいassertContainsEquals()が作成され、以前の挙動を提供します。
*<tt>phpunit.xml</tt>スキーマへの変更 (ほとんどが内部的なものです)。あなたがカスタム<tt>phpunit.xml</tt>ファイルを使用している場合のみ、これらが影響します。
** 前の<tt><filter></tt>セクションは現在 (良い意味で) <tt><coverage></tt>と呼ばれています。そして、その中では:
*** <tt><whitelist></tt>は<tt><include></tt>に置換されました。
*** <tt><exclude></tt>は<tt><whitelist></tt>の子ではなくなりました。代わりに<tt><coverage></tt>の子になりました。
** しかし、coverage.phpファイルで使用されていた<tt>$whitelistxxx</tt>プロパティが非推奨となったため、 [[#あなたのカバレッジを確認する|カバレッジ情報]]を定義する際には代わりに<tt>includelistfolders</tt>および<tt>includelistfiles</tt> (xmlの要素をより適切にマッピングするため) を使用するという意味があります。
* 警告: 個別のテストファイルは実行できないようになりました。実行したいテストを指定するには別の実行方法 (filter、suite、config) のいずれかを使用してください。これは最善の方法が合意された場合にMDL-71049で修正されることを期待しています。
* よく使われるアサーション: ファイルアサーション、正規表現アサーション、例外期待値等 ... これらはすべて次のPHPUnitのアップデートでエラーになることに注意してください。そのため、早急に更新することをお勧めします。


With Moodle 3.11, '''PHPUnit was upgraded to 9.5''' (from 8.5 being used in previous versions). This was done to '''better align''' the testing environment with PHP versions supported by Moodle 3.11 (7.3, 7.4 and [[Moodle and PHP|8.0]]) (see MDL-71036 and linked issues for more details).
最後に[https://github.com/moodle/moodle/compare/fc335f5...713722c 問題に関連する変更を点確認する]のも良いアイデアです。可能であればコミットメッセージに有用で十分な説明を添えてください。
=Moodle 3.10以降で動作するようにユニットテストをアップグレードする (PHPUnit 8.5)=


While a lot of existing tests will work without modification with PHPUnit 9.5, you will get a '''good number of deprecation warnings''' ("W" in the tests output) that '''should be replaced by their new counterparts as soon as possible''', because all those warnings will become errors with next PHPUnit upgrade.
Moodle 3.10ではPHPUnitが8.5にアップグレードされました (旧バージョンでは7.5が使用されていました)。これはMoodle 3.10でサポートされるPHPのバージョン (7.2、7.3および7.4) およびテスト環境の整合性を高めるため、およびMoodle 3.11 (php バージョン 7.3、7.4および 8.0) で必要となるPHPUnit 9.xへの移行を容易にして、多くの非推奨要素を事前に削除するために実施されました (MDL-67673およびMDL-64600を参照してください)。(詳細はMDL-67673およびMDL-64600を参照してください)。


To find more information about the changes coming with PHPUnit 9.5, it's recommended to read the following resources:
既存のテストの99%はPHPUnit 8.5でそのまま動作しますが、'''かなりの数の非推奨の警告''' ("W" が出力されます) が表示されます。これらの警告は次のPHPUnitアップグレードですべてエラーになるため、可能な限り早く解消すべきです。
* [https://thephp.cc/news/2020/02/migrating-to-phpunit-9 A good article] explaining all the main changes in the release.
* [https://phpunit.de/announcements/phpunit-9.html PHPUnit 9 release Announcement].
* These multiple detailed changelogs (because all them have included modifications requiring changes): [https://github.com/sebastianbergmann/phpunit/blob/9.0.0/ChangeLog-9.0.md 9.0], [https://github.com/sebastianbergmann/phpunit/blob/9.1.0/ChangeLog-9.1.md 9.1], [https://github.com/sebastianbergmann/phpunit/blob/9.3.0/ChangeLog-9.3.md 9.3], [https://github.com/sebastianbergmann/phpunit/blob/9.5.0/ChangeLog-9.5.md 9.5]
* [https://phpunit.readthedocs.io/en/9.5/ Official PHPUnit manual].
A good summary of all the '''changes and replacements to perform''' is available in the [https://github.com/moodle/moodle/blob/e3a46964dc6d8ca1558c6e1e8dfdf3c1745eeaed/lib/upgrade.txt#L5-L65 lib/upgrade.txt] file. With main points being:
* All the changes that were deprecated with PHPUnit 8.5 (see the section below) are now removed and will lead to errors.
* <tt>assertContains()</tt> now performs stricter comparison (like <tt>assertSame()</tt> does). New <tt>assertContainsEquals()</tt> has been created to provide the old behavior.
* Changes to the <tt>phpunit.xml</tt> schema, mostly internal. These only will impact if you are using custom <tt>phpunit.xml</tt> files:
** The previous <tt><filter></tt> section is now (better) called <tt><coverage></tt>. And, within it:
*** <tt><whitelist></tt> has been replaced by <tt><include></tt>.
*** <tt><exclude></tt> is not a child of <tt><whitelist></tt> anymore, but of <tt><coverage></tt>.
** But with implications when defining the [[#Check your coverage|coverage information]] because <tt>$whitelistxxx</tt> properties used by the <tt>coverage.php</tt> files have been deprecated, instead use <tt>includelistfolders</tt> and <tt>includelistfiles</tt> (to better map the elements in the xml).
* Warning: It's not possible to run individual test files any more. Use any of the alternative execution methods (filter, suite, config) to specify which tests you want to run. This will be hopefully fixed in MDL-71049 once it has been agreed which the best way to proceed is.
* Deprecations, deprecations, deprecations. Lots of them in often used assertions: file assertions, regexp assertions, exception expectations... again, note that all them will become errors with the next PHPUnit update, so '''the recommendation is to update them ASAP'''.
Finally, it's also a good idea to [https://github.com/moodle/moodle/compare/fc335f5...713722c browse the changes associated with the issue], hopefully with useful explanations in the commit messages.
=Upgrading unit tests to work with Moodle 3.10 and up (PHPUnit 8.5)=
{{Moodle 3.10}}


With Moodle 3.10, '''PHPUnit was upgraded to 8.5''' (from 7.5 being used in older version). This was done to '''better align''' the testing environment with PHP versions supported by Moodle 3.10 (7.2, 7.3 and 7.4) and also to provide an '''easier jump to PHPUnit 9.x''' that will be needed for Moodle 3.11 (php versions 7.3, 7.4 and 8.0), removing a lot of deprecated stuff in advance. (see MDL-67673 and MDL-64600 for more details).
PHPUnit 8.5での変更点に関して、以下のリソースをご覧ください:
* [https://thephp.cc/news/2019/02/help-my-tests-stopped-working 良記事] リリースの主要変更点すべてが説明されています。
* [https://phpunit.de/announcements/phpunit-8.html PHPUnit 8リリースアナウンスメント]
* [https://github.com/sebastianbergmann/phpunit/blob/130104cf796a88dd1547dc5beb8bd555c2deb55e/ChangeLog-8.0.md リリースの詳細変更ログ]
* [https://phpunit.readthedocs.io/en/8.5/ 公式PHPUnitマニュアル]
*すべての'''実行すべき変更および置換'''に関する分かりやすい要約は[https://github.com/moodle/moodle/blob/6594c54b2eef62499d304bfa0939999e3a14246e/lib/upgrade.txt#L5-L37 lib/upgrade.txt]ファイルにあります。主なポイントは以下のとおりです:
** すべてのテンプレートメソッド (setUp()、tearDown()) がvoidを返す必要があるようになったため、PHP 7.0のサポートは廃止されました。これはPHP 7.0をサポートするMoodleの古いブランチに対して同じテストを実行していたサードパーティプラグインのほとんどに影響が生じます。


While 99% of existing tests will work without modification with PHPUnit 8.5, you will get a '''good number of deprecation warnings''' ("W" in the tests output) that '''should be replaced by their new counterparts as soon as possible''', because all those warnings will become errors with next PHPUnit upgrade.
** <tt>PHPUnit/DBUnit</tt>は削除されて、軽い代替システムと置換されました。
** 多くはアサーション (<tt>assertContains()</tt>, <tt>assertEquals()</tt>...) および<tt>@expectedExceptionXXX</tt>アノテーションで使用されます。再度、これらすべてはPHPUnit 9でエラーとなることに留意してください。
* 最後に[https://github.com/moodle/moodle/compare/5903054...b13ec3c 課題に関連する変更点の閲覧]も良いアイデアです。可能であればコミットメッセージに有用で十分な説明を添えてください。


To find more information about the changes coming with PHPUnit 8.5, it's recommended to read the following resources:
=Moodle 3.7およびそれ以上で動作するよう単体テストをアップグレードする (PHPUnit 7.5)=
* [https://thephp.cc/news/2019/02/help-my-tests-stopped-working A good article] explaining all the main changes in the release.
* [https://phpunit.de/announcements/phpunit-8.html PHPUnit 8 release Announcement].
* [https://github.com/sebastianbergmann/phpunit/blob/130104cf796a88dd1547dc5beb8bd555c2deb55e/ChangeLog-8.0.md Detailed changelog of the release].
* [https://phpunit.readthedocs.io/en/8.5/ Official PHPUnit manual].
* A good summary of all the '''changes and replacements to perform''' is available in the [https://github.com/moodle/moodle/blob/6594c54b2eef62499d304bfa0939999e3a14246e/lib/upgrade.txt#L5-L37 lib/upgrade.txt] file. With main points being:
** Support for PHP 7.0 dropped (because all template methods (<tt>setUp()</tt>, <tt>tearDown()</tt>..) now require to return void. This will mostly impact 3rd-part plugins that were still running the same tests against old branches of Moodle with PHP 7.0 support.
** <tt>PHPUnit/DBUnit</tt> has been removed are replaced by a lightweight alternative.
** Deprecations, deprecations, deprecations. Lots of them in often used assertions (<tt>assertContains()</tt>, <tt>assertEquals()</tt>...) and also <tt>@expectedExceptionXXX</tt> annotations. Again, note that all them will become errors with PHPUnit 9.
* Finally, it's also a good idea to [https://github.com/moodle/moodle/compare/5903054...b13ec3c browse the changes associated with the issue], hopefully with useful enough explanations in the commit messages.
=Upgrading unit tests to work with Moodle 3.7 and up (PHPUnit 7.5)=
{{Moodle 3.7}}


With Moodle 3.7, '''PHPUnit was upgraded to 7.5''' (from 6.x being used in older version). This was done to better align the testing environment with PHP versions supported by Moodle 3.7 (7.1, 7.2 and 7.3). (see MDL-65204 and linked issues for more details). While internally [https://phpunit.de/announcements/phpunit-7.html a lot of things changed with PHPUnit 7] (PHP 7.1-isms, typed signatures, void returns, assertEquals() changes), thanks to our '''wrapping layer''' (basic and advanced testcases...) impact expected into old existing unit tests is expected to be reduced and upgrades, easy to achieve.
Moodle 3.7では'''PHPUnitが7.5'''にアップグレードされました (旧バージョンでは6.xが使用されていました)。これはMoodle 3.7 (7.1、7.2および7.3) でサポートされるPHPバージョンとテスト環境の整合性を高めるために実施されました (詳細はMDL-65204およびリンクされた問題をご覧ください)。内部的には[https://phpunit.de/announcements/phpunit-7.html PHPUnit 7で多くのことが変わりました] (PHP 7.1らしさ、型付きシグネチャ、 voidリターン、assertEquals()の変更) が我々の '''wrapping layer''' (基本および拡張テストケース ...) によって既存のユニットテストへの影響は少なく、アップグレードも簡単になると予想されます。


To find more information about the changes coming with PHPUnit 7, it's recommended to read the following resources:
PHPUnit 7での変更点に関して、以下のリソースをお読みください:
* [https://phpunit.de/announcements/phpunit-7.html  PHPUnit 7 release Announcement].
* [https://phpunit.de/announcements/phpunit-7.html  PHPUnit 7リリースアナウンスメント]
* [https://github.com/sebastianbergmann/phpunit/blob/520723129e2b3fc1dc4c0953e43c9d40e1ecb352/ChangeLog-7.5.md Detailed changelog of the release], paying special attention to the added, deprecated, changed and deleted sections.
* [https://github.com/sebastianbergmann/phpunit/blob/520723129e2b3fc1dc4c0953e43c9d40e1ecb352/ChangeLog-7.5.md リリースの詳細変更記録]です。特に追加、廃止、変更および削除セクションに注意を払ってください。
* [https://phpunit.readthedocs.io/en/7.5/ Official PHPUnit manual].
* [https://phpunit.readthedocs.io/en/7.5/ 公式PHPUnitマニュアル]
* Changes performed into core, mainly: new, stricter, signatures ([https://github.com/moodle/moodle/commit/26218b7 26218b7]) and assertEquals() changes, specially important when comparing strings, now performed using strict (===) equals ([https://github.com/moodle/moodle/commit/85f47ba 85f47ba]).
* コアに実施された修正点です。主に次のとおりです: new, stricter, signatures ([https://github.com/moodle/moodle/commit/26218b7 26218b7]) および assertEquals() に関する変更。特にストリングの比較時に重要です。現在、厳格な等号 (===) を使用して実行されます ([https://github.com/moodle/moodle/commit/85f47ba 85f47ba])
=Upgrading unit tests to work with Moodle 3.4 and up (PHPUnit 6)=
=Moodle 3.4およびそれ以上で動作するよう単体テストをアップグレードする (PHPUnit 6)=
{{Moodle 3.4}}
Moodle 3.4ではPHPUnitが6.4にアップグレードされました (旧バージョンでは5.5が使用されていました)。これはMoodle 3.4でサポートされるPHPのバージョン (7.0、7.1および7.2) およびテスト環境の整合性を高めるためです (詳細はMDL-60611およびリンクされた報告をご覧ください)。内部的には [https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-6.0.0#backwards-compatibility-issues PHPUnit 6で多くが変わりましたが]  (名前空間付きのクラスはより顕著です) 私たちの'''ラッピングレイヤ'''のおかげで (基本および高度なテストケース ...)  古い既存の単体テストへの影響は少なくなり、簡単にアップグレードもできるようになると思われます。


With Moodle 3.4, '''PHPUnit was upgraded to 6.4''' (from 5.5 being used in older version). This was done to better align the testing environment with PHP versions supported by Moodle 3.4 (7.0, 7.1 and 7.2). (see MDL-60611 and linked issues for more details). While internally [https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-6.0.0#backwards-compatibility-issues a lot of things changed with PHPUnit 6] (namespaced classes being the more noticeable), thanks to our '''wrapping layer''' (basic and advanced testcases...) impact expected into old existing unit tests is expected to be reduced and upgrades, easy to achieve.
しかし、特にphpuni のクラスを直接使用している場合、古い (3.4 以前) テストと新しいテスト間で互換性を維持できない場合があります。幸いなことにtravisおよびCIの両テストがこの状況を検出してくれるため、コアでサポートされているすべてのブランチを問題なく通過させるのは難しいことではないでしょう。プラグインの場合、同じブランチが複数のコアブランチに対して動作しようとしていて、それらがphpunitクラスを直接使用している場合、よりやっかいになるかもしれません。


Still, in '''some cases, it will impossible to maintain compatibility''' of tests between old (pre 3.4) tests and new ones, especially '''when direct use of any phpunit class is performed'''. Luckily, both travis and CI tests will detect this situation and it shouldn't be hard to keep all supported branches in core passing ok. Plugins may be trickier, if the same branch is attempting to work against multiple core branches and they are using some phpunit class directly.
PHPUnit 6での変更点に関して、以下のリソースをご覧ください:
* [https://thephp.cc/news/2017/02/migrating-to-phpunit-6 良記事] リリースの主要変更点すべてが説明されています。
* [https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-6.0.0#backwards-compatibility-issues PHPUnit 6リリースアナウンスメント]
* [https://github.com/sebastianbergmann/phpunit/blob/9d0c024d2099531442d862b66b0ad7cf35ed8e78/ChangeLog-6.0.md
リリースの詳細変更記録]です。特に変更および削除セクションに注意を払ってください。
* コアに実施された修正点です。主に次のとおり:  ネームスペースクラスのリネーム ([https://github.com/moodle/moodle/commit/801a372dadb6e11c8781547603e3f0a59ce5638f 801a372]) および廃止予定 ([https://github.com/moodle/moodle/commit/796e48a58bf18533bdca423fff7949ab119101c4 796e48a])


To find more information about the changes coming with PHPUnit 6, it's recommended to read the following resources:
=関連情報=
* [https://thephp.cc/news/2017/02/migrating-to-phpunit-6 A very good mini-guide] showing all the important changes.
* [[PHPUnitインテグレーション]]
* [https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-6.0.0#backwards-compatibility-issues PHPUnit 6 release Announcement].
* [https://github.com/sebastianbergmann/phpunit/blob/9d0c024d2099531442d862b66b0ad7cf35ed8e78/ChangeLog-6.0.md Detailed changelog of the release], paying special attention to the changed and deleted sections.
* Changes performed into core, mainly: namespace class renaming ([https://github.com/moodle/moodle/commit/801a372dadb6e11c8781547603e3f0a59ce5638f 801a372]) and deprecated stuff ([https://github.com/moodle/moodle/commit/796e48a58bf18533bdca423fff7949ab119101c4 796e48a])
=See also=
* [[PHPUnit integration]]
* [[PHPUnit]]
* [[PHPUnit]]
[[Category:Unit testing]]
[[Category:単体テスト]]


[[en:dev/Writing_PHPUnit_tests]]
[[en:dev/Writing_PHPUnit_tests]]

2022年8月5日 (金) 15:21時点における最新版

各テストの開始時、自動的にリセットされて新しくインストールされた状態となります。

ネームスペース

  • /testsディレクトリ以下のすべてはネームスペースを使用する場合にいくつかの簡単なルールに従う必要があります。これらはテストケース、フィクスチャ、ジェネレータ、そして、一般的にはこれらのディレクトリ内すべてのクラスに適用されます。ご覧ください! (要約 = **/classes ディレクトリに適用されるルールと100% 同じです)。

テストケースクラス

すべてのMoodle単体テストで使用できる3つの基本テストクラスがあります - basic_testcase、advanced_testcaseおよびprovider_testcaseです。各クラスファイルには1つのテストケースのみを置くことを強く推奨します。

basic_testcase
データベースおよびdataroot、そしてPHPのグローバルを変更しない非常にシンプルなテストです。例えば公式のPHPUnitチュートリアルにある例を試すときに使用します。
advanced_testcase
Moodleのコードを簡単にテストできるよう強化されたテストケースクラスです。
provider_testcase
プライバシープロバイダのテストを容易にするために拡張された拡張テストケースクラスです。4番目のテストケースクラスはMoodleデータベースレイヤのテスト用に特別に設計されているため、他の目的で使用しないでください。

アサーション Assertions

アサーションに関する完全なリストは以下で確認できます。

Moodle version PHPUnit version Links
Moodle 3.11 PHPUnit 9.5 ドキュメンテーション
Moodle 3.10 PHPUnit 8.5 ドキュメンテーション
Moodle 3.7 - 3.9 PHPUnit 7.5 ドキュメンテーション
Moodle 3.4 - 3.6 PHPUnit 6.5 ドキュメンテーション

サンプルプラグインテストケース

PHPUnit テストはプラグインのtests/*_test.phpファイル (例: mod/myplugin/tests/sample_test.php) に配置されます。このファイルにはadvanced_testcaseを継承したクラスを1つだけ含む必要があります。

 namespace mod_myplugin;

 class sample_test extends \advanced_testcase {
     public function test_adding() {
         $this->assertEquals(2, 1+2);
     }
 }

詳細はPHPUnitインテグレーション#クラスおよびファイル命名規則をご覧ください。

Moodleライブラリファイルのインクルード

あなたがいくつかのMoodleライブラリファイルをインクルードしたい場合、常に「global $CFG」を宣言する必要があります。これはテストケースファイルが自動的にグローバル$CFGを利用できない非Moodleコードからインクルードされる可能性があることが理由です。

自動状態リセット

各テストの後、デフォルトではMoodleデータベースおよびdatarootは自動的にインストール直後の状態にリセットされます。データベースまたは標準グローバル変数の変更が予想される場合、$this->resetAfterTest()を使用してください

あなたが「Warning: unexpected database modification, resetting DB state」というエラーメッセージに遭遇した場合、テストが$this->resetAfterTest()を使用していないためだとお考えください。

 namespace mod_myplugin;

 class test_something extends \advanced_testcase {
     public function test_deleting() {
         global $DB;
         $this->resetAfterTest(true);
         $DB->delete_records('user');
         $this->assertEmpty($DB->get_records('user'));
     }
     public function test_user_table_was_reset() {
         global $DB;
         $this->assertEquals(2, $DB->count_records('user', array()));
     }
 }

ジェネレータ

デフォルトのインストールを修正する必要のあるテストでは新しいコースまたはユーザ等の作成にジェネレータを使用できます。このページのすべての例はadvanced_testcaseから派生したテストクラスのテストメソッドから使用する必要があります。

単体テストのパラメータにPHPUnit @dataProvider関数を使用している場合、あなたはデータプロバイダ関数でデータジェネレータを使用またはユーザ等を変更できないことに留意してください。データプロバイダでは「データのインスタンス化/生成」しないでください'。ただ、定義のみしてください。そして、テスト本体ではインスタンス化/生成を進めれます。

ユーザを作成する

それぞれのテスト開始時にはゲストおよび管理者の2種類のユーザのみ存在します。あなたがさらにテストアカウントを追加する必要がある場合、以下を使用してください:

 $user = $this->getDataGenerator()->create_user();

あなたはユーザアカウントのプロパティも指定できます。例えば以下のようになります:

 $user1 = $this->getDataGenerator()->create_user(array('email'=>'user1@example.com', 'username'=>'user1'));

デフォルトではユーザはログインしていないため、 現在の$USER値を変更するにはsetUser()メソッドを使用してください:

 $this->setUser($user1);

ゲストおよび管理者アカウントにはショートカットメソッドがあります:

 $this->setGuestUser();
 $this->setAdminUser();

現在のユーザをログインなしにするためにNullを使用できます:

 $this->setUser(null);

コースカテゴリを作成する

 $category1 = $this->getDataGenerator()->create_category();
 $category2 = $this->getDataGenerator()->create_category(array('name'=>'Some subcategory', 'parent'=>$category1->id));

コースを作成する

 $course1 = $this->getDataGenerator()->create_course();
 
 $category = $this->getDataGenerator()->create_category();
 $course2 = $this->getDataGenerator()->create_course(array('name'=>'Some course', 'category'=>$category->id));

活動を作成する

活動プラグインの中にはインスタンスジェネレータが含まれているものもあります。ジェネレータクラスはplugindirectory/tests/generator/lib.phpで定義されています。

以下、1ページのリソースで新しいコースを作成する例です:

 $course = $this->getDataGenerator()->create_course();
 $generator = $this->getDataGenerator()->get_plugin_generator('mod_page');
 $generator->create_instance(array('course'=>$course->id));

以下、機能的には同じですが、少し短くなります:

 $course = $this->getDataGenerator()->create_course();
 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));

コーホートを作成する

Moodle 2.4以降、データジェネレータは新しいコホートの作成に対応しています。

 $cohort = $this->getDataGenerator()->create_cohort();

ユーザ登録の簡略化

標準の登録APIの代わりにデータジェネレータの簡易メソッドを使用できます。これは自己登録および手動登録プラグインと一緒に使用することを意図しています。

$this->getDataGenerator()->enrol_user($userid, $courseid);
$this->getDataGenerator()->enrol_user($userid, $courseid, $teacherroleid);
$this->getDataGenerator()->enrol_user($userid, $courseid, $teacherroleid, 'manual');

尺度を作成する

$this->getDataGenerator()->create_scale();
$this->getDataGenerator()->create_scale(array('name' => $name, 'scale' => $scale, 'courseid' => $courseid, 'userid' => $userid, 'description' => description, 'descriptionformat' => $descriptionformat));

ロールを作成する

$this->getDataGenerator()->create_role();
$this->getDataGenerator()->create_role(array('shortname' => $shortname, 'name' => $name, 'description' => description, 'archetype' => $archetype));

タグを作成する

$this->getDataGenerator()->create_tag();
$this->getDataGenerator()->create_tag(array(
    'userid' => $userid, 
    'rawname' => $rawname,
    'name' => $name, 
    'description' => $description, 
    'descriptionformat' => $descriptionformat,
    'flag' => $flag
));

グループ

グループを作成する

$this->getDataGenerator()->create_group(array('courseid' => $courseid));
$this->getDataGenerator()->create_group(array('courseid' => $courseid, 'name' => $name, 'description' => $description, 'descriptionformat' => $descriptionformat));

グループにユーザを追加する

$this->getDataGenerator()->create_group_member(array('userid' => $userid, 'groupid' => $groupid));
$this->getDataGenerator()->create_group_member(array('userid' => $userid, 'groupid' => $groupid, 'component' => $component, 'itemid' => $itemid));

グルーピングを作成する

$this->getDataGenerator()->create_grouping(array('courseid' => $courseid));
$this->getDataGenerator()->create_grouping(array('courseid' => $courseid, 'name' => $name, 'description' => $description, 'descriptionformat' => $descriptionformat));

グルーピングにグループを追加する

$this->getDataGenerator()->create_grouping_group(array('groupingid' => $groupingid, 'groupid' => $groupid));

リポジトリ

リポジトリインスタンスを作成する

一部のリポジトリプラグインにはインスタンスジェネレータを含むものがあります。ジェネレータクラスは plugindirectory/tests/generator/lib.phpで定義されています。

$this->getDataGenerator()->create_repository($type, $record, $options);

リポジトリタイプを作成する

一部のリポジトリプラグインにはタイプジェネレータを含むものがあります。ジェネレータクラスはplugindirectory/tests/generator/lib.phpで定義されています。

$this->getDataGenerator()->create_repository_type($type, $record, $options);

評定を作成する

評定カテゴリ

$this->getDataGenerator()->create_grade_category(array('courseid' => $courseid));
$this->getDataGenerator()->create_grade_category(array('courseid' => $courseid, 'fullname' => $fullname));

評定アイテム

$this->getDataGenerator()->create_grade_item();
$this->getDataGenerator()->create_grade_item(array('itemtype' => $itemtype, 'itemname' => $itemname, 'outcomeid' => $outcomeid, 'scaleid' => $scaleid, 'gradetype' => $gradetype));

アウトカム

$this->getDataGenerator()->create_grade_outcome();
$this->getDataGenerator()->create_grade_item(array('fullname' => $fullname));

他のタイプのプラグイン

他のどのようなタイプのプラグインでもジェネレータを持てます。ジェネレータクラスではcomponent_generator_baseを継承する必要があります。そして、あなたは $mygenerator = $this->getDataGenerator()->get_plugin_generator($frankenstylecomponentname)でインスタンスを取得できます。

いくつかのタイプのプラグインのために上で文書化されたmodのように拡張するcomponent_generator_baseよりも、さらに特定のクラス、例えばtesting_module_generatorのようなクラスがあるかもしれません、そのクラスでは使用すべきメソッド名の一貫したセットが与えてあることでしょう。そうでなければ、あなたが作業する必要のある別のものを作成するためにジェネレータ上でどのようなメソッドでも好きなように作成できます。

長いテスト

標準的なテストはすべて可能な限り高速に実行されるべきです。実行に時間を要するもの (10秒以上) または負荷のかかるもの (たとえば外部のサーバへの問い合わせに開発マシンが殺到してしまった場合等) はPHPUNIT_LONGTESTがtrueの場合のみ実行されるようにしなければなりません。この定数はphpunit.xmlあるいはconfig.phpで直接設定できます。

長いテストデータ

大きなテストデータセットをコード内の配列としてではなく、ファイルとして簡単に管理する方法に関して、advanced_testcase::createXMLDataSet()、advanced_testcase::createCsvDataSet()および関連関数を参照してください。詳細はPHPUnit_integration#Extra_methods]]を参照してください。

メッセージ送信テスト

あなたはmessage_send()で送信されたすべてのメッセージを一時的にメッセージシンクオブジェクトにリダイレクトできます。これにより開発者はテストしたコードが期待どおりのメッセージを送信しているかどうか確認できます。

メッセージングを使ったコードをテストする場合、まずトランザクションを無効にしてください。 メッセージングを新しいメッセージシンクにリダイレクトすることにより、 後で結果を確認できます。

$this->preventResetByRollback();
$sink = $this->redirectMessages();
//... メッセージを送信するコード
$messages = $sink->get_messages();
$this->assertEquals(3, count($messages));
//.. . テストメッセージが正しい順序および適切な内容で生成されました。

メール送信テスト

あなたはemail_to_user()で送信されたメールを一時的にメールメッセージシンクオブジェクトにリダイレクトできます。これにより、開発者はテストしたコードが期待とおりのメールを送信しているかどうかを確認できます。

メッセージングを使ったコードをテストする場合、まず「noemailever」の設定を解除してください。メールを新しいメッセージシンクにリダイレクトすることにより、 後で結果を確認できます。

unset_config('noemailever');
$sink = $this->redirectEmails();
//... code that is sending email
$messages = $sink->get_messages();
$this->assertEquals(1, count($messages));

ログストア

あなたはログストアに書き込まれたイベントをテストできますが、テスト実行の前にイベントがデータベースに書き込まれるようトランザクションを無効にして、少なくとも1つの有効なログストアを有効にした上で、ログストアのバッファリングを無効にする必要があります。

$this->preventResetByRollback();
set_config('enabled_stores', 'logstore_standard', 'tool_log');
set_config('buffersize', 0, 'logstore_standard');
get_log_manager(true);

あなたのカバレッジを確認する

PHPUnitには単体テストのコードカバレッジ情報を生成する機能があります。

Moodle 3.7以前、このカバレッジはすべてのファイルを読み込み、そのファイルが全くカバーできないかどうか、または意図的にカバーされているかどうかに関係なく、すべてに対してカバレッジを生成していました。

Moodle 3.7以降、「phpunit.xml」設定には各コンポーネントの生成されたカバレッジインクルードおよびエクスクルード情報が含まれています。

インクルードおよびエクスクルード設定を生成する

あなたが書いているテストと一緒にcoverage.phpファイルを作成することにより、どのファイルがカバレッジのためにチェックされるかプログラム的に記述できます。

Moodle 4.0以降、デフォルト設定がすべてのプラグインに適用されるため、あなたが追加ファイルをカバーしたい場合を除き、coverage.phpを提供する必要はありません。

coverage.phpファイルではテスト対象のコンポーネントに含まれるファイルおよびフォルダを一覧表示できます。指定されたすべてのパスはテストされるコンポーネントからの相対パスです。例えば「mod_forum」を扱う場合、あなたのコードは「mod_forum」に置かれます。また、単体テストは「mod/forum/tests/example_test.php」にあります。カバレッジファイルは「mod/forum/tests/coverage.php」にあります。指定されたすべてのパスは「mod/forum」からの相対パスとなります。

含まれるファイル、含まれるフォルダ、除外されるファイルおよび除外されるフォルダを組み合わせて指定できます。これにより、例えば「classes」ディレクトリ全体を含みながら、その中の特定のファイルまたはフォルダを除外できます。

以下「mod_forum」のcoverage.phpの例です:

メモ: Moodleバージョン3.7および3.10では使用される文法が少しだけ異なります。

return new class extends phpunit_coverage_info {
    /** @var array The list of folders relative to the plugin root to include in coverage generation. */
    protected $includelistfolders = [
        'classes',
        'externallib.php',
    ];

    /** @var array The list of files relative to the plugin root to include in coverage generation. */
    protected $includelistfiles = [];

    /** @var array The list of folders relative to the plugin root to exclude from coverage generation. */
    protected $excludelistfolders = [];

    /** @var array The list of files relative to the plugin root to exclude from coverage generation. */
    protected $excludelistfiles = [];
};

また、@coversアノテーションの使用により、各テストがどのクラスまたは関数を効果的にカバーしているか、より明確に定義できることに留意してください。詳細はドキュメンテーションをご覧ください。

Moodle 4.0以降、以下のデフォルト設定が適用されます:

return new class extends phpunit_coverage_info {
    /** @var array The list of folders relative to the plugin root to include in coverage generation. */
    protected $includelistfolders = [
        'classes',
        'tests/generator',
    ];

    /** @var array The list of files relative to the plugin root to include in coverage generation. */
    protected $includelistfiles = [
        'externallib.php',
        'lib.php',
        'locallib.php',
        'renderer.php',
        'rsslib.php',
    ];

    /** @var array The list of folders relative to the plugin root to exclude from coverage generation. */
    protected $excludelistfolders = [];

    /** @var array The list of files relative to the plugin root to exclude from coverage generation. */
    protected $excludelistfiles = [];
};

すでにcoverage.phpファイルが存在する場合、定義済みの値にデフォルトが追加されます。

ベストプラクティス

あなたが単体テストを書く場合に考慮すべきいくつかのベストプラクティス、提案、そして避けるべき点があります。そのいくつかを以下に説明します。

コードカバレッジ

PHPUnitには単体テストのコードカバレッジ情報を生成する機能があり、Moodle 3.7からサポートされています。あなたがコードを書く場合、プラグインのカバレッジの確認を検討することをお勧めします。

PHPUnitドキュメンテーションで説明されているように@coversアノテーションを明示的に設定することを推奨します。

resetAfterTestの使用を最小限に留める

上で説明した例の多くでは

resetAfterTest

という命名法を用いてテスト終了後にデータベースおよびファイルシステムをリセットしていますが、 必要がなければこれを使用しないのが理想的でしょう。

一般的に言えばモック可能で実際の修正を必要としないコードを書くことを目指すべきでしょう。resetAfterTestを使用した場合、テストの速度は低下してしまいます。

共有setUpおよびインスタンス変数の扱いに注意する

あなたはPHPUnit のテストで以下の主な2つの理由のためインスタンス変数の作成方法および使用方法に注意する必要があります:

  1. あなたがsetUpでフィクスチャを作成またはresetAfterTest関数をコールした場合、 そのフィクスチャおよび条件はテストスイートのすべてのテストに適用されます。これら条件を満たさないテストをスイートに追加した場合、 その条件が満たされることはありません。これによりテストが遅くなる場合があります。
  2. PHPUnitは起動時に各テストケースのインスタンスを作成して、 テストが実行される間はそれを破棄しません。テストケース内のデータをインスタンスデータとして保存する場合、_entire suite_が終了するまでメモリに保存されます。これはセットアップされて積極的に破棄されないフィクスチャはガベージコレクションされずにメモリの肥大化に繋がることを意味します。ひどい場合にはメモリの枯渇に繋がる可能性があります。

データを生成およびresetAfterTestを設定するsetUpを含む既存のテストケースは段階的に廃止して、新しいケースを導入しないでください。

dataProvider関数を活用する

PHPUnitのdataProvider機能は非常に強力で便利であり、 あなたは様々な条件で関数を素早く簡単に検証できます。 しかし、dataProvidersを使用する場合、以下のルールに従ってください:

  • resetAfterTestを必要とするリセット可能なデータの追加を最小限に抑えてください。
  • データプロバイダではデータをインスタンス化/生成しないでください。データを定義するのみにしてください。そして、テスト本体はインスタンス化/作成に進めます。データプロバイダはtestSuiteがインスタンス化された後、どのテストが実行される前にもコールされます。各テストは完全なsetUpおよびtearDownを実行して、作成されたデータはすべて破棄されます。
/**
 * Test function accepts parameters passed from the specified data provider.
 *
 * @dataProvider foobar_provider
 * @param int $foor
 * @param int $bar
 */
public function test_foobar(int $foo, int $bar) {
    // Perform the tests here.
}

/**
 * Data provider for {@see self::test_foobar()}.
 *
 * @return array List of data sets - (string) data set name => (array) data
 */
public function foobar_provider(): array {
    return [
        'Same numbers' => [
            'foo' => 42,
            'bar' => 42,
        ],
        'Different numbers' => [
            'foo' => 21,
            'bar' => 84,
        ],
    ];
}

追加テスト設定

通常、テストは外部システムとは連動せずに、どのシステムでも同じように動作する必要があります。しかし、時にはあなたは外部システムとの接続またはシステム構成のために何らかのオプションを指定する必要があります。config.phpから$CFG設定を使用することは意図的に不可能です。 カスタム設定を追加するには以下のようにいくつかの方法があります:

  • phpunit.xmlファイルでテスト設定定数を定義する。
  • config.phpでテスト設定定数を定義する。

これらの定数はテストまたはプラグインのコードで使用できます。

Moodle 3.11およびそれ以上で動作するよう単体テストをアップグレードする (PHPUnit 9.5)

Moodle 3.11はPHPUnitは9.5にアップグレードされました (以前のバージョンでは8.5が使用されていました)。これはMoodle 3.11でサポートされるPHPのバージョン (7.3、7.4、8.0) にテスト環境を合わせるためです (詳細はMDL-71036および関連する報告をご覧ください)。

既存のテストの多くはPHPUnit 9.5でもそのまま動作しますが、かなりの数の非推奨の警告 (テストの出力では「W」) が表示されるはずです。これらの警告は次のPHPUnitのアップグレードですべてエラーになるため、可能な限り早く新しい対応するものに置き換えるべきでしょう。

PHPUnit 9.5での変更点については以下の資料をご覧ください:

すべての実行すべき変更および置換の要約はlib/upgrade.txtファイルにあります。主なポイントは以下のとおりです:

  • PHPUnit 8.5で非推奨となった変更点 (以下のセクションを参照) はすべて削除されたため、エラーが発生するようになりました。
  • assertContains()はより厳しく比較するようになりました (assertSame() のように)。新しいassertContainsEquals()が作成され、以前の挙動を提供します。
  • phpunit.xmlスキーマへの変更 (ほとんどが内部的なものです)。あなたがカスタムphpunit.xmlファイルを使用している場合のみ、これらが影響します。
    • 前の<filter>セクションは現在 (良い意味で) <coverage>と呼ばれています。そして、その中では:
      • <whitelist><include>に置換されました。
      • <exclude><whitelist>の子ではなくなりました。代わりに<coverage>の子になりました。
    • しかし、coverage.phpファイルで使用されていた$whitelistxxxプロパティが非推奨となったため、 カバレッジ情報を定義する際には代わりにincludelistfoldersおよびincludelistfiles (xmlの要素をより適切にマッピングするため) を使用するという意味があります。
  • 警告: 個別のテストファイルは実行できないようになりました。実行したいテストを指定するには別の実行方法 (filter、suite、config) のいずれかを使用してください。これは最善の方法が合意された場合にMDL-71049で修正されることを期待しています。
  • よく使われるアサーション: ファイルアサーション、正規表現アサーション、例外期待値等 ... これらはすべて次のPHPUnitのアップデートでエラーになることに注意してください。そのため、早急に更新することをお勧めします。

最後に問題に関連する変更を点確認するのも良いアイデアです。可能であればコミットメッセージに有用で十分な説明を添えてください。

Moodle 3.10以降で動作するようにユニットテストをアップグレードする (PHPUnit 8.5)

Moodle 3.10ではPHPUnitが8.5にアップグレードされました (旧バージョンでは7.5が使用されていました)。これはMoodle 3.10でサポートされるPHPのバージョン (7.2、7.3および7.4) およびテスト環境の整合性を高めるため、およびMoodle 3.11 (php バージョン 7.3、7.4および 8.0) で必要となるPHPUnit 9.xへの移行を容易にして、多くの非推奨要素を事前に削除するために実施されました (MDL-67673およびMDL-64600を参照してください)。(詳細はMDL-67673およびMDL-64600を参照してください)。

既存のテストの99%はPHPUnit 8.5でそのまま動作しますが、かなりの数の非推奨の警告 ("W" が出力されます) が表示されます。これらの警告は次のPHPUnitアップグレードですべてエラーになるため、可能な限り早く解消すべきです。

PHPUnit 8.5での変更点に関して、以下のリソースをご覧ください:

  • 良記事 リリースの主要変更点すべてが説明されています。
  • PHPUnit 8リリースアナウンスメント
  • リリースの詳細変更ログ
  • 公式PHPUnitマニュアル
  • すべての実行すべき変更および置換に関する分かりやすい要約はlib/upgrade.txtファイルにあります。主なポイントは以下のとおりです:
    • すべてのテンプレートメソッド (setUp()、tearDown()) がvoidを返す必要があるようになったため、PHP 7.0のサポートは廃止されました。これはPHP 7.0をサポートするMoodleの古いブランチに対して同じテストを実行していたサードパーティプラグインのほとんどに影響が生じます。
    • PHPUnit/DBUnitは削除されて、軽い代替システムと置換されました。
    • 多くはアサーション (assertContains(), assertEquals()...) および@expectedExceptionXXXアノテーションで使用されます。再度、これらすべてはPHPUnit 9でエラーとなることに留意してください。
  • 最後に課題に関連する変更点の閲覧も良いアイデアです。可能であればコミットメッセージに有用で十分な説明を添えてください。

Moodle 3.7およびそれ以上で動作するよう単体テストをアップグレードする (PHPUnit 7.5)

Moodle 3.7ではPHPUnitが7.5にアップグレードされました (旧バージョンでは6.xが使用されていました)。これはMoodle 3.7 (7.1、7.2および7.3) でサポートされるPHPバージョンとテスト環境の整合性を高めるために実施されました (詳細はMDL-65204およびリンクされた問題をご覧ください)。内部的にはPHPUnit 7で多くのことが変わりました (PHP 7.1らしさ、型付きシグネチャ、 voidリターン、assertEquals()の変更) が我々の wrapping layer (基本および拡張テストケース ...) によって既存のユニットテストへの影響は少なく、アップグレードも簡単になると予想されます。

PHPUnit 7での変更点に関して、以下のリソースをお読みください:

Moodle 3.4およびそれ以上で動作するよう単体テストをアップグレードする (PHPUnit 6)

Moodle 3.4ではPHPUnitが6.4にアップグレードされました (旧バージョンでは5.5が使用されていました)。これはMoodle 3.4でサポートされるPHPのバージョン (7.0、7.1および7.2) およびテスト環境の整合性を高めるためです (詳細はMDL-60611およびリンクされた報告をご覧ください)。内部的には PHPUnit 6で多くが変わりましたが (名前空間付きのクラスはより顕著です) 私たちのラッピングレイヤのおかげで (基本および高度なテストケース ...) 古い既存の単体テストへの影響は少なくなり、簡単にアップグレードもできるようになると思われます。

しかし、特にphpuni のクラスを直接使用している場合、古い (3.4 以前) テストと新しいテスト間で互換性を維持できない場合があります。幸いなことにtravisおよびCIの両テストがこの状況を検出してくれるため、コアでサポートされているすべてのブランチを問題なく通過させるのは難しいことではないでしょう。プラグインの場合、同じブランチが複数のコアブランチに対して動作しようとしていて、それらがphpunitクラスを直接使用している場合、よりやっかいになるかもしれません。

PHPUnit 6での変更点に関して、以下のリソースをご覧ください:

リリースの詳細変更記録]です。特に変更および削除セクションに注意を払ってください。

  • コアに実施された修正点です。主に次のとおり: ネームスペースクラスのリネーム (801a372) および廃止予定 (796e48a)

関連情報