4

私の新しい仕事でのテストは、私が以前に遭遇したテストとはまったく異なります。

彼らがユニットテストを書いているとき(おそらくコードの前に)、彼らは「When」で始まるクラスを作成します。名前は、テストが実行されるシナリオ(フィクスチャ)を表します。コードを介して、ブランチごとにサブクラスを作成します。クラス内のすべてのテストは「should」で始まり、実行後にコードのさまざまな側面をテストします。そのため、各モック(DOC)が正しく呼び出されていることを確認し、該当する場合は戻り値を確認するためのメソッドがあります。この方法は、テストごとにまったく同じ実行コードが実行されていることを意味し、これは無駄に思えるため、少し混乱しています。彼らが適応したかもしれないこれに似た技術があるかどうか疑問に思いました。スタイルとそれがどのように実装されることになっているのかを説明するリンクは素晴らしいでしょう。

また、SUTを「実行」するための繰り返しの呼び出しをセットアップメソッドに移動したことにも気づきました。これにより、例外を予期しているときに問題が発生します。これは、チェックを実行するための組み込みツール(PythonユニットテストのassertRaises)を使用できないためです。これは、戻り値をテストクラスのバッキングフィールドとして格納することも意味します。また、モックの多くをバッキングフィールドとして保存する必要があります。クラス階層全体で、各モックの構成を区別することが困難になります。

また、コードのテスト方法も少し異なります。それは本当に彼らが統合テストと考えるものに帰着します。それらは、テストされている関数からコンテキストを奪うものをすべてモックアウトします。これは、同じクラス内のプライベートメソッドを意味する場合があります。私は常に、データベース、ファイルシステム、日付など、テストの結果に影響を与える可能性のあるリソースにモックを制限してきました。このアプローチにはいくつかの価値があります。ただし、現在の使用方法では、脆弱なテスト(コードを変更するたびに失敗するテスト)につながることがわかります。統合テストがないと、この場合、サードパーティのAPIを誤って使用している可能性がありますが、単体テストは引き続き合格するため、心配しています。このアプローチについてももっと知りたいです。

したがって、これらのアプローチのいくつかについてさらに学ぶ場所に関するリソースがあれば便利です。彼らが物事をやっている方法を理解していないという理由だけで、私は素晴らしい学習の機会を逃したくありません。また、これらのアプローチのネガティブな点に焦点を当てるのをやめ、メリットがどこにあるのかを見ていきたいと思います。

4

2 に答える 2

3

最初の段落の説明を正しく理解していれば、それは私がよく行うことと非常によく似ています。(テストフレームワークで簡単にできるかどうかによって異なります。また、多くのモックフレームワークはそれをサポートしていませんが、Mockitoのようなスパイフレームワークの方が優れています。)

たとえば、ここにあるスタックの例を参照してください。これには、共通のセットアップ(スタックに物を追加する)と、それぞれが1つの物をチェックする一連の独立したテストがあります。これはさらに別の例です。今回は、どのテスト(@Test)も共通のフィクスチャ(@Before)を変更しませんが、それぞれが発生するはずの1つの独立したことをチェックすることに焦点を当てています。テストの焦点が非常に合っている場合は、本番コードを変更して、他のすべてのテストに合格している間に1つのテストを失敗させることができるはずです(最近、単体テストの焦点の分離で説明しました)。

主なアイデアは、各テストで単一の機能/動作をチェックすることです。これにより、テストが失敗したときに、失敗した理由を簡単に見つけることができます。その他の例とそのスタイルについては、このTDDチュートリアルを参照してください。

1つのテストを実行するのに1ミリ秒かかる場合、同じコードパスが複数回実行されることを心配していません(すべての単体テストを実行するのに数秒以上かかる場合は、テストが大きすぎる可能性があります)。あなたの説明から、モックごとに1つのテストがあることが体系的である場合、テストが機能ではなく実装に緊密に結合されている可能性があるのではないかと心配しています。テストの名前は、テストがどの程度適切に構造化されているか、またはどれほど脆弱であるかを示す良い指標になります。機能またはその機能の実装方法を説明していますか。

モックについては、テストによってガイドされるオブジェクト指向ソフトウェアの成長を読むのに適した本です。すでに述べた理由から、サードパーティのAPI(所有しておらず、変更できないAPI)を模倣するべきではありませんが、それを使用するシステムのニーズによりよく適合し、機能する抽象化を作成する必要があります。あなたがそれを望む方法。その抽象化はサードパーティのAPIと統合テストする必要がありますが、抽象化を使用するすべてのテストでそれをモックすることができます。

于 2012-08-06T22:33:22.583 に答える
1

まず、使用しているパターンはキュウリに基づいています-ここにリンクがあります。スタイルはBDD(ビヘイビア駆動開発)アプローチからのものです。従来のTDDに比べて2つの利点があります。

  1. 言語-BDDのテナントの1つは、使用する言語がエンドユーザーの言語で話すように強制することで、思考に影響を与えることです。プログラマーの焦点からテストを作成する場合とは異なるテストを作成することになります。
  2. ロックコードをテストします-BDDはコードを適切なレベルでロックします。テストでよくある問題の1つは、多数のテストを作成することです。これにより、コードを変更するときに多数のテストも変更する必要があるため、コードベースがより脆弱になります。BDDは、コードの実装ではなく、コードの動作をロックするように強制します。このように、テストが失敗したとき、それは意味がある可能性が高くなります。

これらの効果を達成するためにCucumberスタイルのテストを使用する必要はなく、それを使用するとオーバーヘッドの層が追加されることに注意してください。しかし、従来のxUnitツール(TDD)を使用しながら、BDDの考え方を維持することに成功したプログラマーはほとんどいません。

また、「私がやったら、確認してください」と言いたいシナリオがあるようです。現在のBDDxUnitフレームワークでは、プリミティブ(strings、ints、doubles、booleans ....)しか検証できないため、通常、多数の個別のテスト(Assertごとに1つ)が発生します。ApprovalTestsなどのGoldenMasterパラダイムテストツール使用して、より複雑な検証を行うことができます。これはこのビデオの例です。

最後に、DanNorthのブログへのリンクがあります-彼はすべてを始めました。

于 2012-08-07T02:52:35.570 に答える