ブラックボックスユニットテストとは何ですか?


11

最近、修士プログラムのソフトウェアエンジニアリングコースの最終試験を受けましたが、試験の質問の1つは次のとおりです。

Unit Testing is considered:
a. White-box Testing
b. Black-box Testing
c. Either

7年間のソフトウェア開発経験の中で、ユニットテストは常にホワイトボックスアプローチを採用してきました。テスターは、テストを作成する間、常にユニットの実装について完全な知識を持っています。ブラックボックステストは、統合、システム、および受け入れテストという形で常に後になります。

ただし、(教授によると)試験に対する正解は、単体テストはホワイトボックステストまたはブラックボックステストのいずれかであるということです。

私はいくつかの調査を行いましたが、多くの場合、「ブラックボックスユニットテスト」は、コードが作成される前にユニットテストが記述されるテストファーストアプローチを記述するために使用されているようです。しかし、私の意見では、これはまだホワイトボックステストです。実装はまだ存在していませんが、テストを書いている人は一般に、ソースコードの実装方法についてかなり良い考えを持っています。

ブラックボックスユニットテストのしくみ(本当にそうである場合)とホワイトボックスユニットテストとの違いを誰かに説明してもらえますか?


4
これについて彼らに尋ねたとき、教授はこれをどのように明らかにしましたか?(インタビューの質問がなぜSoftware Engineering.SEの質問を貧弱にするのかを参照してください)
gnat

「テストを書いている人はだいたい、テストがどのように実装されるかについてかなり良い考えを持っています」-それはあなたがテストがどのように実装されるか知っているかどうかではなく、あなたがどのように物事を知っている(白)か(黒)かではありませんテスト中です。
Jesper

@ジェスパーごめんなさい。「ソースコードがどのように実装されるのか」と言うつもりでした。質問で修正しました。
バックキャブ2017

2
While the implementation does not yet exist, whoever is writing the test generally has a pretty good idea about how the source code is going to be implemented.-はい、しかしテスト自体はしません。 ホワイトボックステストとは、変数の値など、メソッドまたはクラスの内部で何かをテストすることを意味します。テスト作成者がテスト中のコードがどのように見えるかを知っているという意味ではありません。
ロバートハーベイ

回答:


20

あなたの教授は正しいです:単体テストはブラックボックスまたはホワイトボックスのいずれかです。違いは、テスターが知っていることではなく、テストケースの生成方法です。

ブラックボックステストでは、インターフェースと(存在する場合)コンポーネントの仕様のみを確認します。関数にシグネチャがある場合、int foo(int a, int b)興味深い整数をテストするだけで、いくつかのテストケースをすぐに生成できます:0、1、マイナス1、複数桁の数値、INT_MAX、INT_MAX-1など。ブラックボックステストは、実装から独立しているため優れています。しかし、彼らはまた重要なケースを見逃すかもしれません。

ホワイトボックステストでは、実装、つまりソースコードを確認し、そこからテストケースを生成します。たとえば、関数のパスカバレッジを100%にしたいとします。次に、すべてのパスが選択されるように入力値を選択します。ホワイトボックステストは、ブラックボックステストよりもはるかに自信を持ってコードの一部を徹底的に実行できるため、優れています。ただし、実装の詳細をテストするだけで、実際には重要な動作ではない場合があります。場合によっては、明らかに時間の無駄です。

ホワイトボックステストは実装から派生しているため、後でしか記述できません。ブラックボックステストは、設計/インターフェイス/仕様から導出されるため、実装の前または後に記述できます。TDDは明らかにブラックボックスでもホワイトボックスでもありません。すべての動作は最初にテストで表現され、次にその動作の最小限のコードが実装されるため、TDDはホワイトボックステストと同様のテストケースになります。しかし、情報フローを見ると、TDDテストはソースコードからではなく、外部の要件から派生しています。したがって、TDDはよりブラックボックスのようなものです。


3
「ホワイトボックステストは実装から派生しているため、後でしか記述できません」 -さて、既存の関数またはクラスに追加したい次の新しい機能について、失敗したテストをTDDスタイルで記述する場合、まず現在の実装を調べて、これまでサポートされていないものを調べ、より意味のある(最初は失敗する)テストを設計できるようにします。私はこれをテストファーストホワイトボックスアプローチと呼び、後で書かれたテストとは呼びません。(それにもかかわらず、私からの+1)。
Doc Brown

4

テスト駆動開発を実施している場合、理論上はすべてのユニットテストをブラックボックスにする必要があります。これが「テストファーストアプローチ」です。コントラクト(インターフェイス)を作成し、そのコントラクトのテストを作成すると、実装によってコントラクトが実行されます。したがって、テストは実装について何も知らず、何も知らないはずです。

結局、テストを書くとき、何をテストしていますか?パブリックメソッド/関数。

クラスのインターフェースを作成してからテストを作成し、その後バスにぶつかった場合、入院中にクラスを作成する人はインターフェースからそうすることができるはずですよね?彼はそれを捨てて、彼自身のインターフェースとテストを書く必要はありません。

これが多少ばらつくのは、実装に依存するものをモックする必要がある場合ですが、公に公開されていないものをモックしている状況に陥った場合、間違いを犯し、依存性の注入を見。したがって、私は、ブラックではなく、ホワイトボックスのユニットテストが例外であるべきだと主張します。

「トイレでのテスト-実装ではなくテストの動作」を検討してください。クラスの実装は変更されますが、テストは引き続き有効です。

ただし、コードカバレッジがアップしていることを確認する必要がある場合(つまり、すべての条件付きパスが実装内でテストされていることを確認する必要がある場合)、ユニットテストをホワイトボックス化する必要があります。パスは、実装のパスを見ることです。


2
If you were to write the interface for a class, and then write the tests, and then you get hit by a bus, the guy who writes the class while you're in hospital should be able to do so from your interface, right? - ではない正確に。ほとんどのAPIコントラクトは、実際にはセマンティクスや動作ではなく、メソッドシグネチャのみを指定します。
Robert Harvey、

あなたが正しい; 私の考えでは、あなたのインターフェースには、文字通りMyClassInterfaceのテキストだけでなく、それが書かれた仕様が含まれていると考えました。
AdamJS 2017

@RobertHarveyほとんどのインターフェイスがセマンティクスや動作を明示的に記述していないことは事実ですが、一般的には暗黙的にそこにあると思います。それがなければ、特定のセマンティクスを必要とするコードは、抽象化に依存することができません。また、コメントやdocblocsとしてのセマンティクスや動作の詳細など、インターフェースを停止するものは何もありません。たとえば、github.com / php
fig

3

よく書かれた単体テストはすべて本質的に「ブラックボックス」であると私は主張します。確かに、テストを作成するときに実装を念頭に置いているかもしれませんが、その実装はリファクタリングすると変わる可能性があります。したがって、テストでは、実装ではなく機能をテストするために、テスト中にのみパブリックAPIを使用する必要があります。実装の詳細は関係ないため、ブラックボックステストを行います。

テスト対象のユニットの内部またはプライベートな側面にアクセスするテストを作成する場合、実装の詳細をテストしています。つまり、ホワイトボックステストです。しかし、実装が変更されたときに簡単に壊れる可能性がある脆弱なテストも書いています。したがって、このようなホワイトボックステストは悪い考えであり、避ける必要があります。

結論:ユニットテストを使用したホワイトボックステストの場合、テストの構成が不十分です。それらの単体テストでのバックボックステストのみ。あなたの教授は正しいです:それはどちらでもかまいません。しかし、ひどい場合にのみ。


1

私はブラックボックステストを実行するユニットテストを書いている最中でした。つまり、私はクラスでパブリックメソッドをテストし、それらが呼び出すプライベートメソッドで結果テストロジックを暗黙的にテストしています。

私はこれを行うために、ユニットテストされるパブリックメソッドへの入力を変更し、サポートされるプライベートメソッドのロジックによって決定または変更される予想出力をテストします。

したがって、単体テストでブラックボックステストを実行するのを妨げるものは何もありません。誰かが隠されたサポートロジックの実装に手を加えると、テストが中断します。実際、これは、クラス内のすべてをテストするためのホワイトボックスユニットよりも優れた効率的なアプローチのようです。私は教授と一緒です。

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