Changes between Version 1 and Version 2 of EC-CUBE標準規約/単体テストガイドライン


Ignore:
Timestamp:
2012/12/07 17:18:08 (11 years ago)
Author:
kim
Comment:

--

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.   テストを含めたフォルダ構成 == 
    812 
    913テストコードを含んだフォルダ構成は以下のようになります。[[BR]] 
     
    2226テストコードはそれぞれ対応するソースコードと同じ階層に保存します。 
    2327 
    24 === 2.  テストの実行方法 === 
    25 全体のテストを行う場合には、phingのtestターゲットを実行します。テストの内容はbuild.xmlの中に定義されているため、実際にはphpunitコマンドが発行されます。 
     28== 2.   テストの実行方法 == 
     29全体のテストを行う場合には、phingのtestターゲットを実行します。[[BR]] 
     30テストの内容はbuild.xmlの中に定義されているため、実際にはphpunitコマンドが発行されます。 
    2631{{{ 
    2732% phing test 
     
    3742下の例のようにディレクトリを指定した場合には、ディレクトリ以下にあるテストケースが実行されます。 
    3843 
    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]] 
     46Common_TestCaseの中には、次節で述べるAssertionを一度に行うverify()関数や[[BR]] 
     47テストの開始時と終了時にDBの準備・後片付けを行うsetUp()/tearDown()関数が含まれています。[[BR]] 
     48個々のテストクラスでは、Common_TestCaseのsetUp()/tearDown()の処理に必要な処理を追加して使います。[[BR]] 
     49また、テストに使用するユーティリティクラスもCommon_TestCaseでまとめてrequireします。 
    4150 
    4251{{{ 
     
    6372}}} 
    6473 
    65 === 4. Assertion(期待値の確認)の方法 === 
    66 PHPUnitにはassertEquals()、assertTrue()など様々な期待値の確認用funcitonが存在します。これらを細かく使用してテストの期待値を確認することもできますが、複数のasseritionを並べると最初の方で失敗した場合に後のassertionが実行されず、全体の修正までに時間がかかってしまう場合があります。これを防ぐため、基本的に期待値と実際の結果はarrayに格納して一度でassertできるようにします。もちろん、それぞれの値が1つずつの場合はarrayに入れなくても構いません。 
     74== 4. Assertion(期待値の確認)の方法 == 
     75PHPUnitにはassertEquals()、assertTrue()など様々な期待値の確認用funcitonが存在します。[[BR]] 
     76これらを細かく使用してテストの期待値を確認することもできますが、複数のasseritionを並べると[[BR]] 
     77最初の方で失敗した場合に後のassertionが実行されず、全体の修正までに時間がかかってしまう場合があります。[[BR]] 
     78これを防ぐため、基本的に期待値と実際の結果はarrayに格納して一度でassertできるようにします。[[BR]] 
     79もちろん、それぞれの値が1つずつの場合はarrayに入れなくても構いません。 
    6780 
    6881{{{ 
     
    7891}}} 
    7992 
    80 === 5. テストfunctionの分け方 === 
     93== 5. テストfunctionの分け方 == 
    8194原則として、1つのテストfunctionで1つの条件をテストします。 
    8295 
     
    120133 
    121134 
    122 === 6. テストfunctionの命名規則 === 
     135== 6. テストfunctionの命名規則 == 
    123136 
    124137テストfunctionの名称は、テストの内容を分かりやすくするため 
     
    126139test【function名】_【条件】_【期待する結果】() 
    127140}}} 
    128 という形式で統一します。命名規則を統一することで可読性が上がり、テストコードを書いた本人でなくてもJenkinsのテストレポートを見るとどのようなテストが行われているかが一目でわかります。また、条件・期待する結果は日本語で記載することでさらに分かりやすくすることができます。 
     141という形式で統一します。命名規則を統一することで可読性が上がり、[[BR]] 
     142テストコードを書いた本人でなくてもJenkinsのテストレポートを見るとどのようなテストが行われているかが一目でわかります。[[BR]] 
     143また、条件・期待する結果は日本語で記載することでさらに分かりやすくすることができます。 
    129144 
    130145 * 例 
     
    134149}}} 
    135150 
    136 === 7. テストクラスの分け方 === 
    137  
    138 テストクラスはテスト対象のfunction毎に1つずつ分けて作成します。ただし、後述する「定数による条件分岐」をテストする場合には条件毎にクラスを分ける必要があるためさらに細分化されます。 
    139  
    140 === 8.テストクラスの命名規則 ===  
     151== 7. テストクラスの分け方 == 
     152 
     153テストクラスはテスト対象のfunction毎に1つずつ分けて作成します。[[BR]] 
     154ただし、後述する「定数による条件分岐」をテストする場合には条件毎にクラスを分ける必要があるためさらに細分化されます。 
     155 
     156== 8.テストクラスの命名規則 ==  
    141157上で述べたとおり基本的にテストクラスはテスト対象のfunctionに対応するため、 
    142158{{{ 
     
    155171条件によってファイル名を分ける場合には、ファイル名は日本語を避けて定義するようにしてください。 
    156172 
    157 === 9. より網羅的にテストを書く方法 === 
     173== 9. より網羅的にテストを書く方法 == 
    158174 1. 定数による条件分岐 
    159175 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から呼び出すことにより、テスト時の実装を切り替えます。 
     176PHPUnitでテストを行う際には実際にphpのプログラムを走らせることになりますが、[[BR]] 
     177プログラム中にexitする箇所があるとそこでPHPUnit自体も終了してしまうため、有効なテスト結果を得ることができません。[[BR]] 
     178EC-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から呼び出すことにより、テスト時の実装を切り替えます。 
    162182 
    163183{{{ 
     
    175195}}} 
    176196 
    177 === 10. テストを書きやすくする対策 === 
     197== 10. テストを書きやすくする対策 == 
    178198 
    179199 1. functionを「単体」でテストする 
    180 functionの中でさらにfunctionが呼ばれている場合、いちばん外側のfunctionをそのまま実行すると中の分岐が多すぎてテストしきれない場合があります。そのような場合は、内側のfunctionの実装をモックに切り替えて欲しい値を自由に返すようにし、外側のfunctionだけをテストするようにします。 
     200functionの中でさらにfunctionが呼ばれている場合、いちばん外側のfunctionをそのまま実行すると中の分岐が多すぎてテストしきれない場合があります。[[BR]] 
     201そのような場合は、内側のfunctionの実装をモックに切り替えて欲しい値を自由に返すようにし、外側のfunctionだけをテストするようにします。 
    181202 
    182203 * ソースコード 
     
    218239 
    219240 2. ユーティリティクラスを使ってデータ準備を効率化する 
    220 テストで常に同じ結果を得られるようにするには、テスト実行のたびにDBの内容を期待値に合わせてリセットする必要があります。そのため、EC-CUBEのユーティリティであるSC_Queryクラスを使ってsetUp()の中でデータの準備を行い、tearDown()でロールバックを行います。 
     241テストで常に同じ結果を得られるようにするには、テスト実行のたびにDBの内容を期待値に合わせてリセットする必要があります。[[BR]] 
     242そのため、EC-CUBEのユーティリティであるSC_Queryクラスを使ってsetUp()の中でデータの準備を行い、tearDown()でロールバックを行います。 
    221243{{{ 
    222244class SampleTest extends PHPUnit_Framework_TestCase { 
     
    252274 
    253275 3. ユーティリティクラスを使って端末の種類を設定する 
    254 端末の種類がPC・モバイル・スマートフォンのいずれになっているかによって条件が分岐する場合は、テスト専用のユーティリティを使用して擬似的に端末の種別を設定します。ユーティリティはtests/class/test/util/User_Utils.phpに定義されています。 
     276端末の種類がPC・モバイル・スマートフォンのいずれになっているかによって条件が分岐する場合は、[[BR]] 
     277テスト専用のユーティリティを使用して擬似的に端末の種別を設定します。ユーティリティはtests/class/test/util/User_Utils.phpに定義されています。 
    255278{{{ 
    256279/** 
     
    272295 
    273296 4. ユーティリティクラスを使ってログイン状態を設定する 
    274 ユーザがログインしているかどうかによって処理が分岐する場合は、セッションの情報とDBの値を書き換えることによりテストで要求する分岐を実現します。情報を書き換えるfunctionは、端末種別設定と同じくtests/class/test/util/User_Utils.php内で定義されています。 
     297ユーザがログインしているかどうかによって処理が分岐する場合は、セッションの情報とDBの値を書き換えることによりテストで要求する分岐を実現します。[[BR]] 
     298情報を書き換えるfunctionは、端末種別設定と同じくtests/class/test/util/User_Utils.php内で定義されています。 
    275299{{{ 
    276300  /**