来週は、ユニットテストとテスト駆動開発について、私の部署と話し合う予定です。この一環として、最近作成したコードから実際の例をいくつか紹介しますが、トークで作成する非常に単純な例もいくつか紹介したいと思います。
私はウェブで良い例を探していましたが、私たちの開発分野に特に当てはまるものを見つけるのに苦労していました。私たちが作成するほとんどすべてのソフトウェアは、小型のマイクロコントローラーで実行される深く埋め込まれた制御システムです。 「下」のレイヤーに直接触れない限り、単体テストに簡単に適用できるCコードがたくさんあります(ここでは、ターゲット自体ではなくPCでの単体テストについて話します)。直接話し合うものマイクロコントローラ周辺機器に。しかし、私が見つけたほとんどの例は文字列処理に基づいている傾向があります(たとえば、優れたDive Into Pythonローマ数字の例))。文字列をほとんど使用しないため、これは本当に適切ではありません(私たちのコードが通常使用するライブラリ関数はmemcpy
、memcmp
およびmemset
だけなので、strcat
または正規表現に基づくものは正しくありません) 。
それで、質問に:ライブセッションでユニットテストを示すために使用できる関数の良い例を誰かに提供できますか?私の(変更される可能性がある)意見での良い答えは、おそらく次のようになります。
>
のではなく >=
)これは簡単に入れることができますが、ほとんどの場合は機能しますが、特定のEdgeケースでは機能しません。ユニットテストで簡単に識別して修正できます。何かご意見は?
おそらく関連性はありませんが、テスト自体はおそらくGoogleテストフレームワークを使用してC++で記述されます。すべてのヘッダーにはすでに#ifdef __cplusplus extern "C" {
それらの周りのラッパー。これは、これまでに行ったテストでうまく機能しています。
lenバイトでチェックサムを生成することになっている単純な関数を次に示します。
int checksum(void *p, int len)
{
int accum = 0;
unsigned char* pp = (unsigned char*)p;
int i;
for (i = 0; i <= len; i++)
{
accum += *pp++;
}
return accum;
}
これにはフェンスポストのバグがあります。forステートメントでは、テストはi < len
。
楽しいのは、このようなテキスト文字列に適用すると...
char *myString = "foo";
int testval = checksum(myString, strlen(myString));
あなたは「正しい答え」を得るでしょう!これは、チェックサムされた余分なバイトがゼロ文字列ターミネーターだったためです。したがって、このチェックサム関数をコードに組み込んで、場合によっては出荷して、問題に気付かないようにすることができます。つまり、テキスト文字列以外の何かに適用し始めるまでは。
これは、このバグにフラグを付ける簡単な単体テストです(ほとんどの場合... :-)
void main()
{
// Seed the random number generator
srand(time(NULL));
// Fill an array with junk bytes
char buf[1024];
int i;
for (i = 0; i < 1024; i++)
{
buf[i] = (char)Rand();
}
// Put the numbers 0-9 in the first ten bytes
for (i = 0; i <= 9; i++)
{
buf[i] = i;
}
// Now, the unit test. The sum of 0 to 9 should
// be 45. But if buf[10] isn't 0 - which it won't be,
// 255/256 of the time - this will fail.
int testval = checksum(buf, 10);
if (testval == 45)
{
printf("Passed!\n");
}
else
{
printf("Failed! Expected 45, got %d\n", testval);
}
}
bubble sort のようなソート関数の実装についてはどうですか? sort関数が機能するようになったら、ユニットテストとTDDを導入するのと同じくらい良い binary search を続行できます。
並べ替えと検索は、間違ってしまいがちな比較に依存しています。また、ポインタの交換も必要です。ポインタの交換には注意が必要です。どちらもエラーが発生しやすいので、ごちゃごちゃしてください:)
さらにいくつかのアイデア:
qsort
のようなより強力なソートに変更できます。テストは引き続きパスし、新しいソート関数も機能することを証明します。