Changes between Version 1 and Version 2 of EC-CUBE標準規約/単体テストガイドライン
- Timestamp:
- 2012/12/07 17:18:08 (11 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
EC-CUBE標準規約/単体テストガイドライン
v1 v2 1 = 単体テストガイドライン = 2 3 本ガイドラインはEC-CUBEの単体テストをPHPUnitを使って行う上でのガイドラインを、株式会社Shift様([http://www.shiftinc.jp/])のご協力によりまとめたものとなります。 4 5 == 各クラス共通のガイドライン == 6 7 === 1. テストを含めたフォルダ構成 === 1 2 = 単体テストガイドライン = 3 4 [[PageOutline]] 5 6 本ガイドラインはEC-CUBEの単体テストをPHPUnitを使って行う上でのガイドラインを[[BR]] 7 株式会社Shift様([http://www.shiftinc.jp/])のご協力によりまとめたものとなります。 8 9 = 各クラス共通のガイドライン = 10 11 == 1. テストを含めたフォルダ構成 == 8 12 9 13 テストコードを含んだフォルダ構成は以下のようになります。[[BR]] … … 22 26 テストコードはそれぞれ対応するソースコードと同じ階層に保存します。 23 27 24 === 2. テストの実行方法 === 25 全体のテストを行う場合には、phingのtestターゲットを実行します。テストの内容はbuild.xmlの中に定義されているため、実際にはphpunitコマンドが発行されます。 28 == 2. テストの実行方法 == 29 全体のテストを行う場合には、phingのtestターゲットを実行します。[[BR]] 30 テストの内容はbuild.xmlの中に定義されているため、実際にはphpunitコマンドが発行されます。 26 31 {{{ 27 32 % phing test … … 37 42 下の例のようにディレクトリを指定した場合には、ディレクトリ以下にあるテストケースが実行されます。 38 43 39 === 3. テストクラスの構成 === 40 テストクラスは、基本的にtests/class/Common_TestCase.phpを継承して作成します。Common_TestCaseの中には、次節で述べるAssertionを一度に行うverify()関数やテストの開始時と終了時にDBの準備・後片付けを行うsetUp()/tearDown()関数が含まれています。個々のテストクラスでは、Common_TestCaseのsetUp()/tearDown()の処理に必要な処理を追加して使います。また、テストに使用するユーティリティクラスもCommon_TestCaseでまとめてrequireします。 44 == 3. テストクラスの構成 == 45 テストクラスは、基本的にtests/class/Common_TestCase.phpを継承して作成します。[[BR]] 46 Common_TestCaseの中には、次節で述べるAssertionを一度に行うverify()関数や[[BR]] 47 テストの開始時と終了時にDBの準備・後片付けを行うsetUp()/tearDown()関数が含まれています。[[BR]] 48 個々のテストクラスでは、Common_TestCaseのsetUp()/tearDown()の処理に必要な処理を追加して使います。[[BR]] 49 また、テストに使用するユーティリティクラスもCommon_TestCaseでまとめてrequireします。 41 50 42 51 {{{ … … 63 72 }}} 64 73 65 === 4. Assertion(期待値の確認)の方法 === 66 PHPUnitにはassertEquals()、assertTrue()など様々な期待値の確認用funcitonが存在します。これらを細かく使用してテストの期待値を確認することもできますが、複数のasseritionを並べると最初の方で失敗した場合に後のassertionが実行されず、全体の修正までに時間がかかってしまう場合があります。これを防ぐため、基本的に期待値と実際の結果はarrayに格納して一度でassertできるようにします。もちろん、それぞれの値が1つずつの場合はarrayに入れなくても構いません。 74 == 4. Assertion(期待値の確認)の方法 == 75 PHPUnitにはassertEquals()、assertTrue()など様々な期待値の確認用funcitonが存在します。[[BR]] 76 これらを細かく使用してテストの期待値を確認することもできますが、複数のasseritionを並べると[[BR]] 77 最初の方で失敗した場合に後のassertionが実行されず、全体の修正までに時間がかかってしまう場合があります。[[BR]] 78 これを防ぐため、基本的に期待値と実際の結果はarrayに格納して一度でassertできるようにします。[[BR]] 79 もちろん、それぞれの値が1つずつの場合はarrayに入れなくても構いません。 67 80 68 81 {{{ … … 78 91 }}} 79 92 80 == = 5. テストfunctionの分け方 ===93 == 5. テストfunctionの分け方 == 81 94 原則として、1つのテストfunctionで1つの条件をテストします。 82 95 … … 120 133 121 134 122 == = 6. テストfunctionの命名規則 ===135 == 6. テストfunctionの命名規則 == 123 136 124 137 テストfunctionの名称は、テストの内容を分かりやすくするため … … 126 139 test【function名】_【条件】_【期待する結果】() 127 140 }}} 128 という形式で統一します。命名規則を統一することで可読性が上がり、テストコードを書いた本人でなくてもJenkinsのテストレポートを見るとどのようなテストが行われているかが一目でわかります。また、条件・期待する結果は日本語で記載することでさらに分かりやすくすることができます。 141 という形式で統一します。命名規則を統一することで可読性が上がり、[[BR]] 142 テストコードを書いた本人でなくてもJenkinsのテストレポートを見るとどのようなテストが行われているかが一目でわかります。[[BR]] 143 また、条件・期待する結果は日本語で記載することでさらに分かりやすくすることができます。 129 144 130 145 * 例 … … 134 149 }}} 135 150 136 === 7. テストクラスの分け方 === 137 138 テストクラスはテスト対象のfunction毎に1つずつ分けて作成します。ただし、後述する「定数による条件分岐」をテストする場合には条件毎にクラスを分ける必要があるためさらに細分化されます。 139 140 === 8.テストクラスの命名規則 === 151 == 7. テストクラスの分け方 == 152 153 テストクラスはテスト対象のfunction毎に1つずつ分けて作成します。[[BR]] 154 ただし、後述する「定数による条件分岐」をテストする場合には条件毎にクラスを分ける必要があるためさらに細分化されます。 155 156 == 8.テストクラスの命名規則 == 141 157 上で述べたとおり基本的にテストクラスはテスト対象のfunctionに対応するため、 142 158 {{{ … … 155 171 条件によってファイル名を分ける場合には、ファイル名は日本語を避けて定義するようにしてください。 156 172 157 == = 9. より網羅的にテストを書く方法 ===173 == 9. より網羅的にテストを書く方法 == 158 174 1. 定数による条件分岐 159 175 2. exitする箇所のテスト 160 PHPUnitでテストを行う際には実際にphpのプログラムを走らせることになりますが、プログラム中にexitする箇所があるとそこでPHPUnit自体も終了してしまうため、有効なテスト結果を得ることができません。EC-CUBEの場合は、pages以下のクラスでSC_Response_Ex::sendRedirect()やSC_Response_Ex::actionExit()を呼んでいる箇所がそれにあたります。このような部分をきちんとテストするために、テスト実施時はSC_Response_Exの実装を切り替えてexitしないようにします。 161 実装を切り替えた後のクラスはtests/class/replace以下に存在します。このクラスをCommon_TestCaseから呼び出すことにより、テスト時の実装を切り替えます。 176 PHPUnitでテストを行う際には実際にphpのプログラムを走らせることになりますが、[[BR]] 177 プログラム中にexitする箇所があるとそこでPHPUnit自体も終了してしまうため、有効なテスト結果を得ることができません。[[BR]] 178 EC-CUBEの場合は、pages以下のクラスでSC_Response_Ex::sendRedirect()やSC_Response_Ex::actionExit()を呼んでいる箇所がそれにあたります。[[BR]] 179 このような部分をきちんとテストするために、テスト実施時はSC_Response_Exの実装を切り替えてexitしないようにします。[[BR]] 180 実装を切り替えた後のクラスはtests/class/replace以下に存在します。[[BR]] 181 このクラスをCommon_TestCaseから呼び出すことにより、テスト時の実装を切り替えます。 162 182 163 183 {{{ … … 175 195 }}} 176 196 177 == = 10. テストを書きやすくする対策 ===197 == 10. テストを書きやすくする対策 == 178 198 179 199 1. functionを「単体」でテストする 180 functionの中でさらにfunctionが呼ばれている場合、いちばん外側のfunctionをそのまま実行すると中の分岐が多すぎてテストしきれない場合があります。そのような場合は、内側のfunctionの実装をモックに切り替えて欲しい値を自由に返すようにし、外側のfunctionだけをテストするようにします。 200 functionの中でさらにfunctionが呼ばれている場合、いちばん外側のfunctionをそのまま実行すると中の分岐が多すぎてテストしきれない場合があります。[[BR]] 201 そのような場合は、内側のfunctionの実装をモックに切り替えて欲しい値を自由に返すようにし、外側のfunctionだけをテストするようにします。 181 202 182 203 * ソースコード … … 218 239 219 240 2. ユーティリティクラスを使ってデータ準備を効率化する 220 テストで常に同じ結果を得られるようにするには、テスト実行のたびにDBの内容を期待値に合わせてリセットする必要があります。そのため、EC-CUBEのユーティリティであるSC_Queryクラスを使ってsetUp()の中でデータの準備を行い、tearDown()でロールバックを行います。 241 テストで常に同じ結果を得られるようにするには、テスト実行のたびにDBの内容を期待値に合わせてリセットする必要があります。[[BR]] 242 そのため、EC-CUBEのユーティリティであるSC_Queryクラスを使ってsetUp()の中でデータの準備を行い、tearDown()でロールバックを行います。 221 243 {{{ 222 244 class SampleTest extends PHPUnit_Framework_TestCase { … … 252 274 253 275 3. ユーティリティクラスを使って端末の種類を設定する 254 端末の種類がPC・モバイル・スマートフォンのいずれになっているかによって条件が分岐する場合は、テスト専用のユーティリティを使用して擬似的に端末の種別を設定します。ユーティリティはtests/class/test/util/User_Utils.phpに定義されています。 276 端末の種類がPC・モバイル・スマートフォンのいずれになっているかによって条件が分岐する場合は、[[BR]] 277 テスト専用のユーティリティを使用して擬似的に端末の種別を設定します。ユーティリティはtests/class/test/util/User_Utils.phpに定義されています。 255 278 {{{ 256 279 /** … … 272 295 273 296 4. ユーティリティクラスを使ってログイン状態を設定する 274 ユーザがログインしているかどうかによって処理が分岐する場合は、セッションの情報とDBの値を書き換えることによりテストで要求する分岐を実現します。情報を書き換えるfunctionは、端末種別設定と同じくtests/class/test/util/User_Utils.php内で定義されています。 297 ユーザがログインしているかどうかによって処理が分岐する場合は、セッションの情報とDBの値を書き換えることによりテストで要求する分岐を実現します。[[BR]] 298 情報を書き換えるfunctionは、端末種別設定と同じくtests/class/test/util/User_Utils.php内で定義されています。 275 299 {{{ 276 300 /**