917

私はこの夏、ストレート C で書かれた組み込みシステムに取り組みました。それは、私が働いている会社が引き継いだ既存のプロジェクトでした。私は JUnit を使用して Java で単体テストを作成することにかなり慣れてきましたが、システムに追加された新しいコードだけでなく、既存のコード (リファクタリングが必要) の単体テストを作成する最良の方法について途方に暮れていました。

単純な C コードの単体テストを、JUnit を使用した Java コードの単体テストと同じくらい簡単にするプロジェクトはありますか? 組み込み開発 (arm-linux プラットフォームへのクロスコンパイル) に特に適用される洞察をいただければ幸いです。

4

31 に答える 31

537

C の単体テスト フレームワークの 1 つがCheckです。C での単体テスト フレームワークのリストは、ここで見つけることができ、以下に再現されています。ランタイムに含まれる標準ライブラリ関数の数に応じて、それらのいずれかを使用できる場合と使用できない場合があります。

エースユニット

AceUnit (Advanced C and Embedded Unit) は、快適な C コード ユニット テスト フレームワークとしての地位を確立しています。JUnit 4.x を模倣しようとしており、リフレクションのような機能が含まれています。AceUnit は、組み込みソフトウェア開発などのリソースに制約のある環境で使用できます。重要なことに、単一の標準ヘッダー ファイルを含めることができず、ANSI / ISO C ライブラリから単一の標準 C 関数を呼び出すことができない環境でも問題なく動作します。また、Windows ポートも備えています。フォークを使用してシグナルをトラップすることはありませんが、作成者はそのような機能を追加することに関心を示しています。エースユニットのホームページをご覧ください。

GNU オートユニット

別のアドレス空間で単体テストを実行するための fork を含め、Check とほぼ同じ方向に沿っています (実際、Check の最初の作成者は GNU Autounit からアイデアを借用しました)。GNU Autounit は GLib を広範囲に使用します。つまり、リンクなどには特別なオプションが必要ですが、特に GTK や GLib を既に使用している場合は、これは大きな問題にはならないかもしれません。GNU Autounit ホームページを参照してください。

cUnit

また、GLib を使用しますが、単体テストのアドレス空間を保護するためにフォークしません。

C単位

標準 C、Win32 GUI 実装の計画あり。現在、単体テストのアドレス空間を fork したり、保護したりしません。初期開発中。CUnitのホームページを参照してください。

キュテスト

ソース ツリーにドロップする .c ファイルと .h ファイルを 1 つだけ含む単純なフレームワーク。CuTestのホームページを参照してください。

CppUnit

C++ 向けの優れた単体テスト フレームワーク。C コードのテストにも使用できます。安定しており、活発に開発されており、GUI インターフェイスを備えています。C に CppUnit を使用しない主な理由は、まず CppUnit が非常に大きいことと、次に C++ でテストを作成する必要があることです。これは、C++ コンパイラが必要であることを意味します。これらが懸念事項のように聞こえない場合は、他の C++ 単体テスト フレームワークと共に検討する価値があります。CppUnit のホームページを参照してください。

embUnit

embUnit (Embedded Unit) は、組み込みシステム用の別の単体テスト フレームワークです。これは、AceUnit に取って代わられたようです。組み込みユニットのホームページ

MinUnit

マクロの最小限のセット、それだけです! 要点は、コードの単体テストがいかに簡単かを示すことです。MinUnitのホームページを参照してください。

安藤さんのCUnit

かなり新しく、明らかにまだ開発の初期段階にある CUnit の実装です。安藤さんのCUnitのホームページを見てください。

このリストは、2008 年 3 月に最後に更新されました。

その他のフレームワーク:

Cモッカ

CMocka は、モック オブジェクトをサポートする C 用のテスト フレームワークです。使い方もセットアップも簡単です。

CMocka のホームページを参照してください。

基準

Criterion はクロスプラットフォームの C ユニット テスト フレームワークで、自動テスト登録、パラメーター化されたテスト、理論をサポートし、TAP や JUnit XML などの複数の形式に出力できます。各テストは独自のプロセスで実行されるため、必要に応じてシグナルとクラッシュを報告またはテストできます。

詳しくはCriterionのホームページをご覧ください。

HWUT

HWUT は、C を強力にサポートする一般的な単体テスト ツールです。Makefile の作成、最小限の「反復テーブル」でコード化された大規模なテスト ケースの生成、ステート マシンのウォークアローン、C スタブの生成などに役立ちます。一般的なアプローチは非常にユニークです。評決は「良い標準出力/悪い標準出力」に基づいています。ただし、比較関数は柔軟です。したがって、チェックには任意のタイプのスクリプトを使用できます。標準出力を生成できる任意の言語に適用できます。

HWUT のホームページを参照してください。

Cグリーン

C および C++ 用の最新の移植可能な言語間ユニット テストおよびモック フレームワーク。オプションの BDD 表記、モック ライブラリ、単一プロセスで実行する機能 (デバッグを容易にするため) を提供します。テスト関数を自動で発見するテストランナーが利用可能です。ただし、プログラムで独自のものを作成できます。

これらすべての機能 (およびそれ以上) は、CGreen マニュアルで説明されています。

ウィキペディアでは、ユニット テスト フレームワークのリストの下に、C ユニット テスト フレームワークの詳細なリストが示されています。

于 2008-09-15T19:14:36.837 に答える
178

個人的にはGoogle Test フレームワークが好きです。

C コードのテストで本当に難しいのは、外部モジュールへの依存関係を壊して、コードをユニットごとに分離できるようにすることです。これは、レガシー コードに関するテストを取得しようとしている場合に特に問題になる可能性があります。この場合、リンカーを使用してテストでスタブ関数を使用することがよくあります。

これは、人々が「継ぎ目」について話すときに言及しているものです。C では、唯一の選択肢は、プリプロセッサまたはリンカを使用して依存関係をモックアウトすることです。

私の C プロジェクトの 1 つの典型的なテスト スイートは、次のようになります。

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

実際にはヘッダー ファイルではなく C ファイルをインクルードしていることに注意してください。これにより、すべての静的データ メンバーにアクセスできるという利点があります。ここでは、ロガー (logger.o にある可能性があり、空の実装を提供する可能性があります) のモックを作成します。これは、テスト ファイルが残りのコード ベースから独立してコンパイルおよびリンクされ、分離して実行されることを意味します。

コードのクロスコンパイルに関しては、これが機能するには、ターゲットに適切な機能が必要です。PowerPC アーキテクチャ上の Linux にクロス コンパイルされた googletest でこれを行いました。結果を収集するための完全なシェルと OS があるため、これは理にかなっています。あまりリッチでない環境 (完全な OS のないものとして分類されます) では、ホスト上でビルドして実行するだけです。ビルドの一部としてテストを自動的に実行できるように、とにかくこれを行う必要があります。

オブジェクト指向コードは一般に手続き型よりもはるかに結合が少ないため、C++ コードのテストは一般的にはるかに簡単です (もちろん、これはコーディング スタイルに大きく依存します)。また、C++ では、依存性注入やメソッドのオーバーライドなどのトリックを使用して、カプセル化されているコードに継ぎ目を入れることができます。

Michael Feathers は、レガシー コードのテストに関する優れた本を出版しています。ある章では、私が強くお勧めするオブジェクト指向以外のコードを扱うテクニックについて説明しています。

編集: GitHub で入手可能なソースを使用して、手続き型コードの単体テストに関するブログ投稿を書きました。

編集: Pragmatic Programmers から出ている新しい本があり、特に C コードの単体テストに対処しています。これを強くお勧めします。

于 2009-09-11T10:19:22.913 に答える
143

Minunitは、信じられないほど単純な単体テスト フレームワークです。avrのCマイクロコントローラーコードの単体テストに使用しています。

于 2008-09-15T19:27:50.893 に答える
46

私はratkokとほぼ同じと言いますが、ユニットテストにひねりを加えている場合は...

Unity - C コードの単体テストに強く推奨されるフレームワーク.

#include <unity.h>

void test_true_should_be_true(void)
{
    TEST_ASSERT_TRUE(true);
}

int main(void)
{
    UNITY_BEGIN();
    RUN_TEST(test_true_should_be_true);
    return UNITY_END();
}

このスレッドTDD for embedded Cで言及されている本の例は、 Unity (および CppUTest) を使用して記述されています。

于 2011-11-08T08:40:21.147 に答える
43

現在、CuTest 単体テスト フレームワークを使用しています。

http://cute.sourceforge.net/

非常に軽量でシンプルなため、組み込みシステムに最適です。デスクトップだけでなく、ターゲット プラットフォームでも問題なく動作しました。単体テストの作成に加えて、必要なものは次のとおりです。

  • CuTest ルーチンを呼び出す場所に含まれるヘッダー ファイル
  • イメージにコンパイル/リンクされる単一の追加の「C」ファイル
  • ユニットテストをセットアップして呼び出すためにメインに追加されたいくつかの簡単なコード - ビルド中に UNITTEST が定義されている場合にコンパイルされる特別な main() 関数にこれがあります。

システムは、ヒープといくつかの stdio 機能をサポートする必要があります (すべての組み込みシステムがサポートしているわけではありません)。ただし、コードは単純なので、プラットフォームに要件がない場合は、おそらくこれらの要件の代わりに作業できます。

extern "C"{} ブロックを適切に使用することで、C++ のテストも問題なくサポートされます。

于 2008-09-16T18:00:38.300 に答える
37

また、Test Anything Protocol (TAP) を出力する C テスト フレームワークであるlibtapも参照してください。したがって、このテクノロジ用に出てくるさまざまなツールとうまく統合されます。主に動的言語の世界で使用されますが、使いやすく、非常に人気があります。

例:

#include <tap.h>

int main () {
    plan(5);

    ok(3 == 3);
    is("fnord", "eek", "two different strings not that way?");
    ok(3 <= 8732, "%d <= %d", 3, 8732);
    like("fnord", "f(yes|no)r*[a-f]$");
    cmp_ok(3, ">=", 10);

    done_testing();
}
于 2008-09-16T06:32:12.747 に答える
27

cmockaと呼ばれるモックオブジェクトをサポートするC用のエレガントな単体テストフレームワークがあります。標準Cライブラリのみが必要であり、さまざまなコンピューティングプラットフォーム(組み込みを含む)およびさまざまなコンパイラで動作します。

また、Subunit、Test Anything Protocol、jUnitXMLレポートなどのさまざまなメッセージ出力形式もサポートしています。

cmockaは、組み込みプラットフォームでも動作するように作成されており、Windowsもサポートしています。

簡単なテストは次のようになります。

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

APIは完全に文書化されており、いくつかの例がソースコードの一部です。

cmockaの使用を開始するには、LWN.netの記事を読む必要があります。Cでのモックオブジェクトを使用した単体テスト

cmocka1.0は2015年2月にリリースされました。

于 2013-01-20T13:43:02.243 に答える
21

関数をモックする方法を探し始める前に、レガシー C アプリケーションを十分にテストすることはできませんでした。テストしたいCファイルを他のものから分離するために、モックがひどく必要でした。私はcmockを試してみましたが、それを採用すると思います。

Cmock はヘッダー ファイルをスキャンし、見つけたプロトタイプに基づいてモック関数を生成します。モックを使用すると、C ファイルを完全に分離してテストできます。実際のオブジェクト ファイルではなく、テスト ファイルをモックにリンクするだけです。

cmock のもう 1 つの利点は、モック化された関数に渡されるパラメーターを検証し、モックが提供する戻り値を指定できることです。これは、関数のさまざまな実行フローをテストするのに非常に役立ちます。

テストは、典型的な testA()、testB() 関数で構成され、期待値を構築し、関数を呼び出してテストし、アサートをチェックします。

最後のステップは、unity を使用してテスト用のランナーを生成することです。Cmock は、ユニティ テスト フレームワークに関連付けられています。Unity は、他の単体テスト フレームワークと同じくらい簡単に習得できます。

試してみる価値があり、把握するのは非常に簡単です。

http://sourceforge.net/apps/trac/cmock/wiki

更新 1

私が調査している別のフレームワークは Cmockery です。

http://code.google.com/p/cmockery/

これは、単体テストとモックをサポートする純粋な C フレームワークです。Ruby には依存せず (Cmock とは対照的に)、外部ライブラリにはほとんど依存しません。

コード生成を行わないため、モックのセットアップにはもう少し手作業が必要です。プロトタイプはあまり変更されないため、これは既存のプロジェクトの多くの作業を表すものではありません。モックを作成したら、しばらくの間それらを変更する必要はありません (これは私の場合です)。追加の入力により、モックを完全に制御できます。気に入らないものがあれば、モックを変更するだけです。

特別なテスト ランナーは必要ありません。テストの配列を作成し、それを run_tests 関数に渡すだけで済みます。ここでも手作業が少し増えますが、自己完結型の自律型フレームワークのアイデアは間違いなく気に入っています。

さらに、私が知らなかった気の利いた C のトリックがいくつか含まれています。

全体的な Cmockery を始めるには、モックについてもう少し理解する必要があります。例は、これを克服するのに役立つはずです。より単純なメカニズムで仕事をすることができるようです。

于 2010-07-22T13:03:58.620 に答える
18

簡単な操作性と移植性のために、CHEAT (GitHub でホスト) を作成しまし

依存関係がなく、インストールや構成は必要ありません。ヘッダー ファイルとテスト ケースのみが必要です。

#include <cheat.h>

CHEAT_TEST(mathematics_still_work,
    cheat_assert(2 + 2 == 4);
    cheat_assert_not(2 + 2 == 5);
)

テストは、テストの実行と結果の報告を処理する実行可能ファイルにコンパイルされます。

$ gcc -I . tests.c
$ ./a.out
..
---
2 successful of 2 run
SUCCESS

きれいな色もあります。

于 2014-10-03T17:14:06.830 に答える
16

C の初心者として、C でのテスト駆動開発というスライドが非常に役に立ちました。基本的に、外部依存関係なしに、標準assert()を一緒に使用してメッセージを配信します。&&誰かがフルスタックのテストフレームワークに慣れている場合、これはおそらくうまくいきません:)

于 2011-10-08T23:10:25.873 に答える
12

CUnitあり

また、Embedded Unitは、Embedded C System の単体テスト フレームワークです。その設計は、JUnit や CUnit などからコピーされた後、Embedded C System に多少適応されました。Embedded Unit は std C ライブラリを必要としません。すべてのオブジェクトは const 領域に割り当てられます。

また、Tessyは組み込みソフトウェアの単体テストを自動化します。

于 2008-09-15T19:27:28.523 に答える
12

フレームワークは使用せず、autotools の「チェック」ターゲット サポートを使用するだけです。「メイン」を実装し、アサートを使用します。

私のテストディレクトリ Makefile.am(s) は次のようになります:

check_PROGRAMS = test_oe_amqp

test_oe_amqp_SOURCES = test_oe_amqp.c
test_oe_amqp_LDADD = -L$(top_builddir)/components/common -loecommon
test_oe_amqp_CFLAGS = -I$(top_srcdir)/components/common -static

TESTS = test_oe_amqp
于 2008-09-16T13:54:28.893 に答える
7

CppUTest - C コードの単体テストに強く推奨されるフレームワーク.

このスレッドTDD for embedded Cで言及されている書籍の例は、 CppUTest を使用して記述されています。

于 2011-06-07T18:46:48.490 に答える
6

組み込みC/C ++環境(主にC ++) にはCxxTestを使用します。

テストランナーをビルドするためのperl/pythonスクリプトがあるため、CxxTestが好きです。セットアップを行うための小さな傾斜の後(テストランナーを作成する必要がないため、さらに小さくなります)、非常に使いやすくなります(サンプルと有用なドキュメントが含まれています)。最も手間がかかったのは、コードがアクセスする「ハードウェア」を設定して、ユニット/モジュールのテストを効果的に行えるようにすることでした。その後、新しい単体テストケースを簡単に追加できます。

前述のように、これはC /C++ユニットテストフレームワークです。したがって、C++コンパイラが必要になります。

CxxTestユーザーガイド CxxTestWiki

于 2008-09-15T22:47:08.993 に答える
5

other than my obvious bias

http://code.google.com/p/seatest/

is a nice simple way to unit test C code. mimics xUnit

于 2010-07-01T05:09:36.550 に答える
5

Google には優れたテスト フレームワークがあります。https://github.com/google/googletest/blob/master/googletest/docs/primer.md

はい、私が見る限り、プレーン C で動作します。つまり、C++ の機能は必要ありません (C++ コンパイラが必要になる場合がありますが、確かではありません)。

于 2008-09-15T19:14:53.623 に答える
5

Minunit を読んだ後、より良い方法は、防衛プログラム手法のようによく使用する assert マクロのテストに基づいていると思いました。そのため、Minunit と標準の assert を組み合わせた同じアイデアを使用しました。k0ga のブログで私のフレームワーク (良い名前は NoMinunit かもしれません) を見ることができます

于 2011-02-18T20:38:42.097 に答える
4

http://code.google.com/p/cmockery/の cmockery

于 2008-09-15T19:22:11.000 に答える
4

Cmockeryは最近開始されたプロジェクトで、単体テストを作成するための非常に使いやすい C ライブラリで構成されています。

于 2008-09-16T15:40:09.667 に答える
3

まず、こちらをご覧ください: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

私の会社には、顧客が使用する C ライブラリがあります。CxxTest (C++ 単体テスト ライブラリ) を使用してコードをテストします。CppUnit も機能します。C で行き詰まっている場合は、RCUNIT をお勧めします (ただし、CUnit も優れています)。

于 2008-09-15T20:39:24.840 に答える
2

カットしてみてください!- http://code.google.com/p/lcut

于 2010-10-10T01:43:07.320 に答える
2

JUnit に精通している場合は、CppUnit をお勧めします。 http://cppunit.sourceforge.net/cppunit-wiki

これは、単体テストを実行するための C++ コンパイラがあることを前提としています。そうでない場合は、Adam Rosenfield に同意する必要があります。チェックはあなたが望むものです。

于 2008-09-15T19:22:11.903 に答える
2

RCUNITを使用して、ターゲットでテストする前に、PC で組み込みコードの単体テストを行いました。適切なハードウェア インターフェイスの抽象化は重要です。そうしないと、エンディアンとメモリ マップド レジスタがあなたを殺してしまいます。

于 2008-11-25T11:12:08.900 に答える
2

API サニティ チェッカー— C/C++ ライブラリのテスト フレームワーク:

共有 C/C++ ライブラリの基本単体テストの自動ジェネレーター。ヘッダー内の宣言を分析することで、妥当な (残念ながらすべてのケースではありませんが、ほとんどのケースで) パラメータの入力データを生成し、API のすべての関数に対して単純な (「健全性」または「浅い」品質の) テスト ケースを作成できます。ファイル。

生成されたテストの品質により、単純なユースケースで重大なエラーがないことを確認できます。このツールは、生成されたテストをビルドして実行し、クラッシュ (セグメンテーション違反)、アボート、あらゆる種類の発行されたシグナル、ゼロ以外のプログラム リターン コード、およびプログラムのハングを検出できます。

例:

于 2011-01-25T14:57:02.473 に答える
1

使用する手法の 1 つは、ターゲット システムのソースを C モジュールとして維持しながら、C++ xUnit フレームワーク (および C++ コンパイラ) を使用して単体テスト コードを開発することです。

クロスコンパイラで C ソースを定期的にコンパイルし、可能であれば単体テストで自動的にコンパイルしてください。

于 2008-09-15T19:22:34.727 に答える
1

LibU ( http://koanlogic.com/libu ) には、明示的なテスト スイート/ケースの依存関係、テストの分離、並列実行、およびカスタマイズ可能なレポート フォーマッタ (既定の形式は xml および txt) を可能にする単体テスト モジュールがあります。

ライブラリは BSD ライセンスであり、ネットワーク、デバッグ、一般的に使用されるデータ構造、構成など、他の多くの便利なモジュールが含まれています。プロジェクトで必要な場合は...

于 2010-04-16T08:55:58.313 に答える
1

Cutter (http://cutter.sourceforge.net/)について誰も言及していないことに驚いてい ます。C および C++ をテストできます。autotools とシームレスに統合され、非常に優れたチュートリアルが利用可能です。

于 2013-01-22T14:48:20.437 に答える
0

Win32 プラットフォームまたは NT カーネル モードをターゲットにしている場合は、cfixを確認する必要があります。

于 2008-10-11T16:18:50.770 に答える
0

既存の C ユニット テスト ライブラリに対するフラストレーションからLibcut を作成しました。プリミティブの自動型文字列化 (test_eq_int、test_eq_long、test_eq_short などは必要ありません。プリミティブと文字列の 2 つの異なるセットのみ) があり、1 つのヘッダー ファイルで構成されます。以下に短い例を示します。

#include <libcut.h>

LIBCUT_TEST(test_abc) {
    LIBCUT_TEST_EQ(1, 1);
    LIBCUT_TEST_NE(1, 0);
    LIBCUT_TEST_STREQ("abc", "abc");
    LIBCUT_TEST_STRNE("abc", "def");
}

LIBCUT_MAIN(test_abc);

ただし、C11でのみ機能します。

于 2015-01-04T22:33:43.540 に答える
0

まだテスト フレームワークを探しているなら、CUnitWin32は Win32/NT プラットフォーム用のフレームワークです。

これにより、他のテスト フレームワークで直面した 1 つの根本的な問題が解決されます。つまり、各テストは個別のプロセスとして実行されるため、グローバル/静的変数は決定論的な状態にあります。

于 2009-01-12T00:30:39.430 に答える