現実的なデータに依存するクラスを単体テストするにはどうすればよいですか?


8

科学的測定の結果をカプセル化するクラスがあります。私は最初から単体テストを構築していますが、単体テストの経験があまりなく、どの動作をどのようにテストするべきかわかりません。

私のクラスは次の3種類のことを行います。

  1. ファイル(または文字列)からそのインスタンス変数に測定データを読み込みます
  2. 測定データをファイルまたは文字列に書き込みます
  3. データに対して計算を実行します(例:一連の数値の平均を取得)

私の現在のアプローチは、既知の良好なサンプルデータファイルをtestディレクトリに含めることです。1つのテストでは、ファイルからデータを読み取り、それをクラスに渡し、いくつかの基本的な健全性チェックを満たしていることを確認します。別のテストでは、ファイルのファイル名をクラスに渡し、クラスにそれを読み取らせ、同じテストを実行します。テストの残りの部分では、ファイルからデータを読み取り、それをクラスに渡し、データ処理方法の結果が正しいことを確認します。

しかし、これはかなり絡み合っているようです。(3)をチェックするテストは、(1)の動作が正しいことを暗黙的に想定しています。そして、(1)のテストは、(3)のテストによって行われた広範なチェックから利益を得ることができます。単体テストの構造が不十分ですか、それともテストで特定のデータセットを使用する必要があるという事実の自然な結果ですか?


2
統合テストへようこそ。真剣にあなたは正しい軌道に乗っています。いくつかの考慮事項:プロジェクトが迅速に完了しているように見せたい場合は、ビッグバン統合を試してください。プログラムの何が問題なのかを実際に把握できるようにしたい場合は、今後で、各サブシステムのテストケースを体系的に確立し続けてください。
Andyz Smith 2013

回答:


14

あなたがしているのは統合テストです。おそらくご存知のように、テストはコードの他の部分に依存しています。これは問題ありませんが、記事/例/その他を調べるときに知っておくとよいでしょう。オンライン。

考慮すべきいくつかのポイントと覚えておくべきこと:

  • アレンジアクトアサート。すべてのテストには、これらの3つのステップがあります。
    • さらに手順が必要ですか?あなたはおそらく1つのテストのためにあまりにも多くをテストしている
    • アレンジなし?外部依存関係があるため、ほとんどの場合、テストは不安定で信頼できなくなります。
    • 多くのアレンジコードは、通常、多くの依存関係、およびシステム状態タイプの依存関係を意味します。これは脆弱なコードのレシピです。
    • 行動しない?多くの場合、コンパイラをテストします。コンパイラ開発者に任せてください。
    • たくさんの行為?おそらく、もう一度1つのテストを実行しすぎています。
    • アサートなし?「エラーが発生しなかった」ことをテストしたい場合がよくあります。エラーなし!=正常に動作しています。
    • アサートがたくさん?テスト中のコードが実行している/処理しているシステムが多すぎる可能性があります。代わりに、個々のビットをリファクタリングしてテストしてみてください。
  • テストは独自に存在する必要があります。3をテストするものが1を実行するコードに依存するシナリオは避けてください。代わりに、1を実行するコードをテストコードに置き換えてください。あなたのシナリオでは:あなたがそれらをテスト年代になりたいものに値を設定してみてください手動整列行い、その後、ステップをアクト、その後、イオン(計算)ASSERT結果。
  • ハッピーパステストは、多くの場合、時間の無駄です。ほとんどの場合、最良のシナリオが機能します。あなたのテストはエラーとエッジケースを強制しようとしているはずです。
    • 処理する不良ストリームに合格するテストはありますか?
    • 処理するnull /存在しないファイル名を渡すテストはありますか?
    • 計算する数値が数値でない場合、または解析時にhugeである場合、または計算時に巨大な値が生成される場合はどうなりますか?
  • 驚くべきことに、テストを書いても、行ったことが正しいことを確認することはめったにありません。代わりに、デザインがいかに使いやすく、安定していて、柔軟であるかについての洞察を提供します。

edit>これはすでに受け入れられていますが、私はPragmatic Unit Testingを介してずっと前に学んだことを追加したいと思います。

あなたとのユニットテストを右BICEP

  • 結果は正しいですか?
  • CORRECT B oundary条件
    • Cの予想フォーマットにonform
    • Oは正しくrdered
    • 範囲は正しい
    • Rの外部依存関係へeferencesは安全です
    • Eの xistence(ヌルなど)
    • Cの ardinality
    • Tの iming(物事が正しいタイミングで、正しい順序で起こります)
  • 私は逆の関係
  • C他の手段とロス・チェックの結果
  • Eの rrorsを余儀なくされています
  • Pの erformance特性が許容範囲内であります

5

あなたのクラスは責任が多すぎるため、テストするのは難しいと思います。あなたは彼らに自分について言及します

  • ファイルからデータを読み取る
  • データをファイルに書き込む
  • 計算を行う

理想的には、クラスは単一の責任、または単一の責任範囲を持つ必要があります。この場合、計算を実行するためのロジックのみを含むクラスが確実に必要です。

もしそうなら、おそらく次のような機能を持つことができます:

CalculationResult PerformCalculation(Measurement[] measurements)
{ ... }

テストで明確に定義された一連の測定値を簡単に提供できるため、これはテストが比較的容易になります。

ここでは、すべての測定値を一度に取得するためにファイルから1回読み取ることを想定しています。時間の経過とともにファイルに書き込まれた新しい測定値を収集すると、クラスは次のようになります。

class Calculator {
    AddMeasurement(Measurement measurement) { ... }

    CalculationResult PerformCalculation() { ... }
}

ファイルシステムに依存することなく、テスト中に明確に定義された一連の測定値をクラスに提供し、結果を読み取ることができるため、テストは簡単です。

別のクラスが、ファイルから測定データを読み取る必要がある場合があります。これは、ファイルからのデータの読み取りと、データをMeasurementオブジェクトとして解析することに分割して、ファイルシステムなどに依存せずに解析ロジックを個別にテストできるようにすることもできます。

単体テストの作成が難しい場合、これは多くの場合、「ユニット」に複数の責任があるか、依存関係が多すぎるか、または他の点でSOLIDではないことを示しています。


3

ユニットテストでは、2つのケースセットをテストする必要があります。

非常に基本的なケース:計算は正しいか、合計を合計するか、など。これらのケースのデータをチェックするのは簡単で簡単です。

エッジケース:2016年2月29日の納期、注文数量999,999、価格が$ 0.00のアイテム、北極のGPS(西に移動してみてください!)など。


0

必須テストの数が多すぎて1つの単体テストインスタンスに結合されているように見えるという意味で、答えの多くは適切だと思います。だが。

多くの関数は複雑なデータを必要とし、複雑な結果を生成します。例えば、画像処理は、画像からマスクを生成するコンパクトな機能を持つことができます。テストドライバーは、画像を読み取って処理し、画像ファイルに書き込んで、結果のファイルを参照画像ファイルと比較します(適切だと私は主張します)。

そのすべての機能のターゲットで統合をテストすることは、統合テストになります。ターゲットの単一の機能、複雑な入力から複雑な出力へのテストは、適切な単体テストです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.