0

私はユニットテストと一般的なテストにまったく慣れていません。私はphpUnitを使用して開発していますが、私の質問はより一般的/設計上の質問であるため、実際の環境はそれほど重要ではありません。

テストケースをできるだけ具体的に書くのは良い習慣だと思います。例(遅いほど良い):

assertNotEmpty($myObject);              // myObject is not Null 
assertInternalType('array', $myObject); // myObject is an array
assertGreaterThan(0, count($myObject)); // myObject actually has entries

それが正しければ、ここに私の質問があります

テスト対象のオブジェクトの状態が外部ソース(つまりDB)に依存している場合、または一般的に、テストケース内にフロー制御を記述することは受け入れられている方法ですか?

好き:

if (myObject !== null) {
    if (count(myObject) > 0) {
    // assert some Business Logic
    }
    else {
    // assert some different Business Logic  
    }
} 

テストケース内のこの種のフロー制御は許容されますか、それとも「コードの臭い」であり、回避する必要がありますか?よろしければ、ここで覚えておくべきヒントや実践はありますか?

4

2 に答える 2

3

Paulの回答は、テストメソッドのスコープとアサーションに対応していますが、質問のコードが暗示していることの1つは、返されたオブジェクトの値がXの場合はAをテストし、値がYの場合はBをテストすることです。つまり、テストでは複数の値を期待してテストします。それが実際に得たものに基づいて異なるもの。

一般に、各テストに1つの既知の正しい値がある場合、テスターはより幸せになります。これは、固定された既知のテストデータを使用することで実現します。多くの場合、テスト自体の内部に設定します。一般的なパスは次の3つです。

  • すべてのテストで使用される一連の固定データをデータベースに入力します。これは、テストや機能を追加するにつれて進化し、物事が進むにつれて最新の状態に保つのが面倒になる可能性があります。データを変更するテストがある場合は、各テストの後にデータをリセットするか、変更をロールバックする必要があります。
  • テストごとに合理化されたデータセットを作成します。テスト中setUp()に、特定のデータセットを使用してデータベースを削除して再作成します。最初はテストの作成が簡単になりますが、オブジェクトが進化するにつれてデータセットを更新する必要があります。これにより、テストの実行に時間がかかる場合もあります。
  • これらのDAOを直接テストしない場合は、データアクセスオブジェクトにモックを使用してください。これにより、テストでどのデータをいつ返すかを正確に指定できます。DAOコードをテストしていないので、モックアウトしても問題ありません。これにより、テストが迅速に実行され、データセットを管理する必要がなくなります。ただし、モックデータを管理し、モックコードを作成する必要があります。PHPUnit独自の組み込みフレームワークを含め、好みに応じて多くのモックフレームワークがあります。
于 2011-07-05T22:41:08.393 に答える
2

テストケース内にいくつかの制御フローを含めることは問題ありませんが、一般に、単体テストは、互いに素である場合、つまり、それぞれが異なることをテストする場合に最適に機能することを理解してください。これがうまくいく理由は、テストケースが失敗したときに、何がうまくいかなかったかを確認するために大きなテストケースの内部を深く調べる必要があるのではなく、失敗したテストケースから失敗が何であるかを正確に確認できるためです。通常のメトリックは、単体テストケースごとに1つのアサーションです。とはいえ、すべてのルールには例外があり、それは確かにそのうちの1つです。特にテストケースシナリオのセットアップ/分解が特に難しい場合は、テストケースにいくつかのアサーションを含めることに必ずしも問題はありません。ただし、避けたい実際のコードの臭いは、「テスト」が1つある状況です。

于 2011-07-05T20:18:32.850 に答える