モックできない具体的な外部実装に依存するコードのテストをどのように記述しますか?


17

背景:私が取り組んでいるモジュール用にいくつかを作成することで、同僚に単体テストの概念を導入しようと考えています。要件が最近変更され、さらに抽象化/相互作用が必要になったため、アプリケーションを手動で確認することなく機能することを「証明」する一連のテストを開発するのに適した方法のようです。

ただし、問題は、モジュールがPDFやXSLなどのモックできない外部要因に依存していることです。基本的に、データベースからXMLを読み取り、XSL変換を適用してから、ABCPDFと呼ばれるライブラリを使用してPDFに変換します。このPDFは、静的テンプレートに基づいて別のPDFとマージされます。XMLをテストし、値が正しいことを確認できることはわかっていますが、潜在的なバグや問題の多くは、完成したドキュメントの実際の表示に関連しています。たとえば、テキスト文字列が折り返される時間や、特定のHTMLエリア文書等、との関係にあり、その名前を私は[ない受け入れテスト、他の種類]、およびない忘れテストの第三種...(私はこれらはおそらく統合テストやある実現これらのものをテストすることも可能ですユニットは、 テスト)私の知る限り、PDFを作成してから読み返すか、HTML文字列(つまり、変換されたXML)を作成して手作業で解析し、特定のテーブルセルの存在を確認するまで、他のテーブルセルとの関係。

このような状況では、情報が正しいことを確認するために単体テストに焦点を当て、PDF を作成するか、それらをマージするか、実際の表示の問題を手動でテストする必要がありますか?


6
「モック不可能な外部要因」は、そもそもユニットテストを行っていないというヒントです。それは統合テストを意味ます。どっちにしたい?ユニットテストあなたの本のコードや統合テストの複合の事?両方を同時に話すのは難しいため、どちらかを選択してください。
S.Lott

2
「偽物」を購入していません。「モックの方法がわからない」ということは受け入れます。つまり、あなたの本当の質問は「どのようにモックすればよいのか」ということです。
ラインヘンリヒス

おそらく:)私は使用されているXMLのモック作成には精通していますが、書式設定が重要な実際のPDFまたはHTMLドキュメントをモックする方法には精通していません。
ウェインモリナ

1
「機能」(エンドツーエンドのアプリケーション)または「システム」(エンドツーエンドの複数のアプリケーション)テストを意味すると思います
ゲイリーロウ

@Gary-はい、機能的という言葉でした。Railsの学習からそれらを覚えています:ユニットテストモデル、機能テストコントローラー、統合テストすべて。
ウェインモリナ

回答:


13

ユニットではなく機能をテストする

既知のxml入力を使用してPDFを出力し、PDFが正しいことを手動で(そして細心の注意を払って)検証します。次に、参照として保存します。

同じxml入力を使用する今後のテストでは、参照とバイナリファイルの比較を行うことができます。

ファイルレベルの比較が不十分な場合は、テストの最後にPDFを表示してスクリーンショットを撮り、自動テストを参照スクリーンショットと比較させます。


+1は、このレベルの最終結果にのみ関心があるためです。PDFの取得方法の実装を変更する場合、機能テストを変更する必要はありません。
ゲイリーロウ

2
+1をお勧めします。これは現在のプロジェクトで行っていることです。PDF比較を行うためのカスタムツールセットを作成しました。これにより、タイムスタンプなどのドキュメント内の変更部分を省略することができます。警告:別の(バージョンの)PDFレンダラーに切り替えると、レイアウトにわずかな変更が生じ、誤検出のシグナルヒープと直接バイナリ比較が行われる場合があります。
ペテルトレック

5

通常、このような場合、インターフェイスで使用できる実装の背後でテストできないすべてを抽象化します。それは理にかなっているように思えるので、私はPDFビルダーのような愚かなことをするだけです。

public class PdfBuilder : IPdfBuilder
{
  public byte[] BuildPdf(...)
  {
    // actual untestable code here
  }
}

public interface IPdfBuilder
{
  byte[] BuildPdf(...);
}

その後、テストでIPdfBuilderをモックして、必要な処理を実行できます。これは、多くの場合、IoCコンテナー(/programming/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code/programming/21288/which-net-dependency-injection-frameworks-are-worth-looking-intoを開始する場所として使用している場合)

また、単体テストではないテストは、多くの場合、統合テストと呼ばれます。複雑な統合テストは、それだけの価値はないことが多いので、その部分を抽象化し、その抽象化のビジネスロジックの量を減らして、単体テストでテストできるようにします。

これが完全に明確でない場合はお知らせください。


テスト不可能なコードを隠すための+1。その後、適切な結果を得るためにそのインターフェイスを通過する必要があるものを見つけるまで手動テストを実行し、適切に生成されたユニットテストを実行て回帰ユニットテストを取得します。
エセルエヴァンス

1

しばらく前に非常によく似たものを作成し、基本的な視覚テストを使用しました。テストを自動化する必要はありません。そのため、予想される結果を探すだけでも問題はありません(明らかに、あらかじめ決められたさまざまな状況で)。多くの場合、画像はビジュアルが関係する1000回のテストに値します。私は自動化された単体テストを広範に使用していますが、GUIテストや視覚的なIMHOに取り掛かるときに少し夢中になる人もいると思います。特定の製品では、この「十分な」アプローチでは不十分であるため、YMMVを認識しています。

しかし、モックできない外部性について少し心配になるでしょう。これは密結合の兆候である可能性がありますが、これは一般的な経験則として避けるのがよいですが、その点に関しては、詳細なしにあまり推測しません。


非常に密結合ですが、疎結合にするための賛同がなく、リファクタリング専用のリソースがないため、それは修正できません(しかし、それはまったく別の問題です)。
ウェインモリナ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.