0

不透明な構造に基づいてAPIで作成したライブラリがあります。不透明な構造を使用することには多くの利点があり、私はそれに非常に満足しています。

私のAPIは仕様に関して安定しているので、リリースする前にしっかりとしたベースを確認するために、単体テストの完全なバッテリーを作成したいと思います。

私の懸念は単純ですが、主な目標が内部ロジックを隠すことである不透明な構造に基づいてAPIをどのように単体テストしますか?

たとえば、非常に単純なオブジェクト、非常に単純なテストを含む配列を考えてみましょう。

WSArray a = WSArrayCreate();
int foo = 5;
WSArrayAppendValue(a, &foo);
int *bar = WSArrayGetValueAtIndex(a, 0);

if(&foo != bar)
    printf("Eroneous value returned\n");
else
    printf("Good value returned\n");

WSRelease(a);

もちろん、これは配列が実際に1つの値で希望どおりに動作するなど、いくつかの事実をテストしますが、少なくともCで単体テストを作成するときは、通常、データ構造のメモリフットプリントを既知の状態と比較します。

私の例では、配列の内部状態が壊れているかどうかはわかりません。

それをどのように処理しますか?ユニットテストのためだけに実装ファイルにコードを追加することは避けたいと思います。モジュールの緩い結合を強調します。実装にユニットテストを挿入することは、私にはかなり侵襲的であるように思われます。

私が最初に考えたのは、実装ファイルを単体テストに含めて、単体テストをライブラリに静的にリンクすることでした。

例えば:

#include <WS/WS.h>
#include <WS/Collection/Array.c>

static void TestArray(void)
{
    WSArray a = WSArrayCreate();
    /* Structure members are available because we included Array.c */
    printf("%d\n", a->count);     
}

それはいい考えですか?

もちろん、単体テストはカプセル化の恩恵を受けることはありませんが、実際に機能していることを確認するためにここにあります。

4

3 に答える 3

2

私はAPIのみをテストし、考えられるすべてのコーナーケースのテストに焦点を合わせます。

メモリ構造が期待どおりのものを保持していることを確認することに関心があることがわかります。これを行うと、テストを実装の詳細に緊密に結合することになり、多くの長期的なメンテナンスが作成されると思います。

ここでの私の考えは、APIが契約であり、それを実行すると、yoruコードが機能しているということです。後で実装を変更する場合、おそらく知っておく必要があることの1つは、契約が維持されていることです。あなたのユニットテストはそれを確認します。

于 2009-12-27T07:54:48.000 に答える
0

単体テストは、テストしているコードの内部の詳細に依存するべきではありません。最初の例は、実際にはかなり良いテストです。1つのことを実行してから、オブジェクトの状態が期待どおりであることを確認します。

もちろん、APIの他の部分の動作も検証するテストを作成する必要があります。たとえば、配列の場合、項目を追加および削除した後、配列が正しく報告された場合の長さを検証するテストケースが必要になります。

既知の良好なメモリスナップショットとの完全一致に依存する単体テストを作成することは、実装を変更するたびにテストが失敗するという点で、一般的には非常に悪い考えです。スナップショットベースのテストを使用する場合は、「正常な」スナップショットを簡単に再生成できることを確認してください。

于 2009-12-27T08:13:49.443 に答える
0

ユニットテストをホワイトボックスブラックボックスのユニットテストに分割することをお勧めします。ホワイトボックステストはAPIインターフェースと結果の正確さに焦点を合わせ、ブラックボックステストは内部に焦点を合わせます。

これを容易にするために、他の内部/プライベートである関数プロトタイプ用のプライベートヘッダー(例example_priv.h)を使用します。#ifdef TESTINGしたがって、一般的なケースでそれらを公開することなく、ユニットテストの目的で内部機能を実行できます。

この方法での唯一の損失はstatic、ソースファイルのように内部関数に明示的にラベルを付ける機能を失うことです。

お役に立てば幸いです。

于 2010-03-28T16:38:47.547 に答える