17

私の最後のプロジェクトでは、ほぼ 100% cc で単体テストを行った結果、バグはほとんどありませんでした。

ただし、単体テストはホワイト ボックスにする必要があるため (必要な結果を得るには内部関数をモックする必要があるため、テストではコードの内部構造を知る必要があります)、関数の実装を変更するたびに、テストも変更。

関数のロジックは変更せず、実装のみを変更したことに注意してください。

非常に時間がかかり、間違った方法で作業しているように感じました。すべての適切な OOP ガイドライン (具体的にはカプセル化) を使用したため、実装を変更するたびに、残りのコードを変更する必要はありませんでしたが、単体テストを変更する必要がありました。

彼らが私たちに仕えるのではなく、私たちが試練に仕えているように感じました。

これを防ぐために、単体テストはブラック ボックス テストにすべきだと主張する人もいました。

ドメイン全体の 1 つの大きなモックを作成し、すべてのクラスのすべての関数のスタブを 1 か所で作成し、それをすべての単体テストで使用すれば、それが可能になります。

もちろん、特定のテストで特定の内部関数を呼び出す必要がある場合 (DB への書き込みを確認するなど)、スタブをオーバーライドできます。

したがって、関数の実装を変更するたびに (ヘルプ関数の呼び出しを追加または置換するなど)、メインの大きなモックを変更するだけで済みます。一部の単体テストを変更する必要がある場合でも、以前よりもはるかに少なくなります。

アプリが特定の場所で DB に書き込むことを確認するだけでなく、特に期待しない限り、他の場所の DB にアプリが書き込まれないことを確認する必要があるため、単体テストはホワイト ボックスでなければならないと主張する人もいます。に。これはもっともな意見ですが、ブラック ボックス テストの代わりにホワイト ボックス テストを書くことに時間をかける価値はないと思います。

結論として、2つの質問:

  1. ブラック ボックス ユニット テストの概念についてどう思いますか?

  2. そのコンセプトを実現する方法についてどう思いますか? もっと良いアイデアはありますか?

4

6 に答える 6

11

さまざまな種類のテストが必要です。

  • あなたがしたように、ホワイトボックステストであるべき単体テスト

  • システムの実際の実装を使用する機能と、ブラックボックス スタイルにする必要がある外部レイヤー (外部システム、データベースなど) との通信をテストする統合テスト (またはシステム テスト)。 CRUD テストなど)

  • 完全にブラックボックスである必要があり、機能要件によって駆動される受け入れテスト (ユーザーが言うように)。可能な限りエンドツーエンドで、選択した実装の内部を知りません。ブラック ボックス テストの教科書的な定義。

そして、ほとんどの場合、コード カバレッジは無意味であることを忘れないでください。高いライン カバレッジ (またはカウント方法が何であれ、メソッド カバレッジ) が必要ですが、通常は十分ではありません。考える必要がある概念は、機能範囲です。つまり、すべての要件と論理パスが確実にカバーされるようにします。

于 2012-05-13T10:27:02.603 に答える
6

tl;dr バージョン:

  1. ブラック ボックスの単体テストは、まさに単体テストの実行方法です。
  2. ブラック ボックスの単体テストは、まさに単体テストの実行方法です。適切な TDD の実践はまさにこれを行います。

完全版。

オブジェクトのプライベート メソッドをテストする必要はまったくありません。コードカバレッジにも影響はありません。

クラスを TDD するときは、そのクラスの動作をチェックするテストを作成します。動作は、そのクラスのパブリック メソッドを通じて表現されます。メソッドが実際にどのように実装されているかを気にするべきではありません。Googleの人々は、私がこれまでにできるよりもはるかに優れていると説明しました: http://googletesting.blogspot.ru/2013/08/testing-on-toilet-test-behavior-not.html

通常の間違いを犯し、静的に他のエンティティ クラスに依存したり、さらに悪いことに、アプリケーションの別のレイヤーのクラスに依存したりすると、テストで多くのことをチェックして準備する必要がある状況に陥ることは避けられません。それのためのたくさんのもの。これを解決するために、依存性注入の原則とデメテルの法則が存在します。

于 2014-01-31T09:52:02.180 に答える
6

その結果、バグはほとんどありませんでした

あなたが本当にこれを達成できたのなら、何も変えるべきではないと思います。

ブラック ボックス テストは紙の上では魅力的に聞こえるかもしれませんが、実際には、ほとんどの場合、テストされたクラスの内部動作の一部を知る必要があります。入力の提供、出力の検証は、実際には単純なケースでのみ機能します。ほとんどの場合、テストには、テストされたメソッド (外部の共同作業者とどのように対話するか、どのメソッドを呼び出すか、どの順序で呼び出すかなど) について少なくともある程度の知識が必要です。

モッキングとSOLID設計の背後にある全体的な考え方は、依存関係の実装の変更が他のクラスのテストの変更/失敗を引き起こす状況を回避することです. 逆に、テストされたメソッドの実装の詳細を変更する場合は、テストの実装の詳細を変更する必要があります。それはそれほど珍しいことではありません。

全体として、本当にほとんどバグを達成できなかった場合、私はそのアプローチに固執します.

于 2012-05-13T10:19:20.960 に答える
2

ユニットテストを書き続けるべきだと思います。脆弱性を減らしてください。

単体テストは低レベルである必要がありますが、結果をテストする必要があり、物事がどのように行われたかではありません。実装の変更によって多くのテスト変更が発生する場合、それは、要件をテストする代わりに、実際に実装をテストしていることを意味します。

「プライベートメソッドをテストしない」やモックオブジェクトを使用するなど、いくつかのルールがあります。

ドメイン全体をモック/シミュレーションすると、通常、達成しようとしていることとは逆になります。コードの動作が変更された場合は、テストを更新して、「シミュレートされたオブジェクト」が同じように動作することを確認する必要があります。プロジェクトの複雑さが増すにつれて。

ユニットテストを書き続けることをお勧めします-それらをより堅牢で壊れにくくする方法を学ぶだけです。

于 2012-05-13T10:26:08.583 に答える
1

「その結果、バグはほとんどありませんでした」 -- そのままにしておいてください。フラストレーションの唯一の原因は単体テストを維持する必要があることですが、これは実際にはそれほど悪いことではありません (別の方法はもっと悪いことです)。それらをより保守しやすくするだけです。Roy Osherove による「The art of Unit Testing」は、このような良いスタートを切りました。したがって、1)オプションではありません。(たとえば、アイデア自体が TDD の原則と矛盾しています) 2) このようなアプローチでは、メンテナンスの問題がはるかに多くなります。単体テストの哲学は、他のシステムから SUT を切り取って、スタブを入力として使用し、モックを出力 (シグナル?) として使用してテストすることです。

于 2012-05-14T10:46:38.790 に答える
0

黒、白、灰色のボックスとデシジョン テーブルの詳細については、すべてを説明している次の記事を参照してください。

Web ベースのアプリケーションのテスト: 最新技術と将来の傾向 (PDF)

于 2013-08-08T19:16:31.063 に答える