• 締切済み

C言語での単体テストの作成について質問です。

C言語での単体テストの作成方法がわからずに困っています。 以下のようなA.cの中のFuncA関数のテストを作成しています。 /*** A.c ********************/ #include "B.h" int FuncA (int n) { int temp; if (FuncB() == true) temp = n * 2; else temp = n / 2; return temp; } /****************************/ FuncA関数は中でB.c内のFuncB関数を読んでいますが、 これは、B.h、B.cに定義されている関数です。 このFuncB関数は本物のソースを使用せず、スタブを使用してテストを作成しています。 FuncB関数のスタブは以下のように考えています。 /*** BStub.h ********************/ extern bool retVal extern bool FuncB_Stub(void); /******************************/ /*** BStub.c ********************/ #include "BStub.h" bool retVal; bool FuncB_Stub(void) { return retVal; } /******************************/ できる限り、A.cに単体テスト用のコードを埋め込まずにテストを作成したいのですが、 FuncA関数がFuncB関数ではなく、BStubのFuncB_Stub関数を呼び出すようにするには どのようにしたらよろしいでしょうか?

  • llew
  • お礼率0% (0/3)

みんなの回答

noname#208507
noname#208507
回答No.3

リンクするとき、Bのオブジェクトコードを入れ替えればよいと思います。 テストするなら BStub.o を、そうでなければ B.o をリンクするように Makefile を書いて、makeのコマンドライン引数で簡単に切り替えられるようにするのがよいかと。(LinuxなのかWindowsなのかよく分かりませんが) もちろん、スタブの関数名はFuncB_SubではなくFuncBにして。

回答No.2

LD_PRELOADに近いですが、テストをリンクするときにstubとリンクするという方法もあるかもしれません。 よく使われる手にはfuncBの関数ポインターをfuncAに何らかの方法で渡し、それを実行するという方法もありますが、これはfuncAのファイルを書き換えるのでNGですよね。

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.1

プラットホーム依存になりますがOSがlinuxやunix系OSの一部(HP-UX,FreeBSDなど)なら環境変数LD_PRELOADを調べてみるといいかもです。

関連するQ&A

  • 単体テスト スタブ作成に関して

    同一ファイル内にテストする関数とその関数から呼び出される関数があった場合、どのようにスタブは作成すればいいのでしょうか? test.c ------------------------------ funcA(){ //funcA()のテスト funcB(); } funcB(){ } //funcB()のスタブを作りたいが同じファイルにあるため自動的に本物の関数がリンクされてしまう。 ----------------

  • C言語で、記憶クラス指定子extern・staticを関数に指定

    C言語の本に、「関数の定義と呼び出す側が別ソースファイルの場合、プロトタイプはヘッダーファイルに書き、定義側と呼び出し側の両方でインクルードしましょう」ということが書かれていました。 例えば、 ===code1a.c=== extern void funcB(int); static void funcA() { funcB(1); } ===code1b.c=== void funcB(int a) { printf("%d\n",a); } このような場合には、もしcode1b.cの中の関数funcBに引数を追加した場合、再コンパイルしても気づかないのでよくない。 そこで、次のようにヘッダーファイルを作り、プロトタイプはそこに書くべきだ。 ***code2b.h*** extern void funcB(int); ***code2a.c*** #include "code2b.h" static void funcA() { funcB(1); } ******code2b.c**** #include "code2b.h" void funcB(int a) { printf("%d\n",a); } 記述は以上のようなことです。 #include "code2b.h" とは、 extern void funcB(int); が書いてあるのと同じだと思います。 私が思ったのは、本の勧める方法では、 funcBを定義しているcode2b.cで、プロトタイプの記憶クラス指定子が、externになっているが良いのか(externとは、別のソースファイルで定義されているという意味ではないか)ということです。 extern, staticは、プロトタイプに書くべきなのか、関数の定義に書くべきなのか、も両方に書くべきなのでしょうか。 私の処理系では、 ・プロトタイプ宣言でexternを付けて関数定義でstaticを付ける、 ・staticを付けた関数を他のソースファイルで呼ぶ、 などの明らかに矛盾する場合は、コンパイルエラーになります。 でも、extern単独での役割はなさそうです。 他の処理系でも同じでしょうか。 (main等省略)

  • CからC++の関数呼び出し

    CからC++の関数を呼び出して値を取得したいのですが、コンパイルエラーになってしまいます。 呼び出す関数内でさらに同じクラスの関数を呼び出して値をreturnしたいだけなのですが、 ご教示願います。 ソースは下記のような感じです。 Cソース(AAA.c) main(){ ・・・・・ if ( funcA() ){ ・・・・ } } C++ソース(BBB.cpp) int clsB::funcB { return iflg; } extern "C" { int funcA() { return funcB(); } } ※上記externは特に何かの関数内に書いているわけではありません。 C++ヘッダ(BBB.hpp) class clsB : public XXX { private: int iflg; ・・・・ public: int funcB(); ・・・・ } 上記にコンパイルすると、 externしている箇所でfuncBはスコープにありません?のようなエラーが出てしまいます。 ラッパ関数を使って使用するなどと聞いたのですが、やり方がいまいちわかりません。 どうか教えていただけますでしょうか。 また、他にやり方があるかと思いますが、いいやり方があれば教えていただけると幸いです。 以上です、よろしくお願いいたします。 不足内容あれば指定願います。

  • C/C++ return文で関数の返却値を返却

    まず、処理がエラーだと-1を返し、正常だと0を返す関数が2つあり、それぞれint funcA()、int funcB()とします。 この時、それらとは別の関数で以下のようにreturn文を書くとどのように値を返しますか? return funcA() || funcB(); 共に0を返す時、どちらかが0を返し他方は-1を返す時、共に-1を返す時についてご教示願います。 またあえてこのように記述するくらいならノーマルに以下の記述の方が良いですか? if (funcA() != 0 || funcB() != 0 ) { return -1; } else { return 0; } (インデントしていないので読みづらかったらすみません)

  • [単体テスト] static関数のstub

    以下の構成の関数Bをテストしようとしています。 [xxx.c]--------- A() { B(); } ---------------- [yyy.c]--------- B() { C(); } static C() { } ---------------- テスト対象がBのため、driverAとstubCを作成しました。 また、本体xxx.c, yyy.cは共有ライブラリにしているため、A関数・C関数とも名前衝突は起きません。 期待するコールとしては、A(driver)→B(ライブラリ)→C(stub)です。 しかし現状A(driver)→B(ライブラリ)→C(ライブラリ)となってしまいます。 これは、C関数がstaticな為、ビルド時にstubではなくライブラリを優先してリンクしてしまうからだと思います。(そもそもライブラリしか探索しないのか。。。) 本体のソースコードに手を加えず、A(driver)→B(ライブラリ)→C(stub)のテストを行う方法はありますでしょうか。 ※環境 linuxのgcc ご教授宜しくお願いいたします。

  • C言語 ソートについて

    #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { } bool is_at(char c) { } void justify(char line[], int n) { } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; } 上の雛形を使って文字列lineに含まれる@以外の文字を文字列の前の方に詰めていくプログラミングを作るという問題を解いていたのですが下のプログラミングまでは出来たのですが最後のjustifyの部分がわかりません 良ければ解答をお願いします #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } bool is_at(char c) { if(c == '@') { return true; } else { return false; } } void justify(char line[], int n) { for(int i=0;i<n-1;i++) { } } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; }

  • 単体テストのやり方

    単体テストってどうやってするのですか?教えてください。 例えば、この関数だったらどういうテストコードを書けばいいですか? bool isStart(char c){ if(c == 'Y'){ return true; } else if(c == 'N'){ return false; } }

  • C言語について

    C言語初心者です。 今、プログラミングをしていてわからない箇所があるので質問させていただきます。 自作の関数へ配列を送る際、多重配列の途中の配列の値を関数に送りたい場合どのようにすれば よいのでしょうか? 文ではわかりづらいと思うので、例を書きます。↓ /* 関数 */ int sum(int data[],int N){ int i,temp=0; for(i=0;i<N;i++){ temp=temp+data[i]; } return(temp); } /* 本文 */ int output; int a[10][20][30]={適当な数字が入ってるとします。} // この時、配列の左と右に値を指定して、真ん中の配列を関数に送りたいです。 output=sum(???,20); //ちなみに現在はもう一つ1次元配列を作り、そこに一旦コピーしてから関数に送っています。 //なにか良い方法があればご教授ください。

  • C言語:引数の型だけ異なる関数を一つにまとめる方法

    以下の引数の型だけ異なる関数を、どうにかして一つにまとめたいのですが、 何か良い方法はないでしょうか? void funcA(_MNGR_TAG mngr){ 処理X; } void funcB(_COPY_MNGR_TAG mngr){ 処理X; } 補足: ・_NODE_TAGと_COPY_NODE_TAGは構造体です。ただし中身は異なります。 ・(引数名が同じため)funcAとfuncBで行っている処理は全く同じです。 注意事項: 関数テーブルやC++言語を使用する方法は除いて下さい

  • DLLでLIBファイルが作成されない

    DLLを作るプログラムをしているのですが、どうしてもコンパイル時にLIBファイルが作成されません。 1>warning C4091: '__declspec(dllexport)' : 変数が何も宣言されていないときは、'DDDClass' の左辺を無視します。 と警告が出てしまいます。 私が書いたソースは以下の通りで、クラスとそのメンバをEXPORTしたいのです。ここで、最後のコメントを外して有効にするとLIBファイルが作成されることはわかっています。また、クラスのメンバにEXPORTをつけてもオーバーライトだと怒られてしまいます。 どのようにしたらLIBファイルが作成されるようになるのでしょうか? ■■■stub.h■■■ #ifdef __cplusplus #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif typedef int (*HOGEHOGE)(int i); EXPORT class DDDClass{ private: int num; HOGEHOGE c; public: DDDClass(); int CALLBACK counter(); int CALLBACK touroku(int (*b)(int i)); }; ■■■stub.cpp■■■ #include <windows.h> #include "Stub1.h" int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved){ return true; } EXPORT class DDDClass; DDDClass::DDDClass(){ num =0; c = NULL; } int CALLBACK DDDClass::touroku(int (*b)(int i)){ c = b; return 0; } int CALLBACK DDDClass::counter(){ //c = b; c(num); num++; return 0; } /* EXPORT bool CALLBACK aaaaa(){ return true; } */

専門家に質問してみよう