読者です 読者をやめる 読者になる 読者になる

Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

UnityでC言語でもTDDを試す

奥さん、僕ぁC言語でもTDDしたいんですよ!
……というわけで、Rubyで実現する素敵なC言語TDD環境、Unityです。
3Dゲームを作るアレではなく、TDD用テストフレームワークです。
UnityはRubyistにはお馴染みのRackを使っています。
Ruby&Rack環境が方は先に導入しておいて下さい。

導入が終わりましたら、
"公式様"にとんで頂き、
下の方にある「download unity」から圧縮ファイルを入手します。
これを解凍すると色々と並んでいます……が
今回用があるのはexampleです。
これの中身を詳しく見て行くと

$ ls examples/
helper			rakefile_helper.rb	test
makefile		readme.txt		test1.out
rakefile.rb		src			test2.out

となっています。
テスト対象のファイルはsrc、
テストはtestに突っ込みます。
なお、今回のコードは下記のの記事で書いたコマンド形式のアレをベースにしています
shuzo-kino.hateblo.jp

/*src/wap.c*/
#include "wap.h"
#include <stdio.h>
#include <string.h>

typedef struct
{
  char *cmd;
  void (*func)();
} cmd_t;

static cmd_t cmd_tbl[] = {
  {"rx", wap_rx},
  {"tx", wap_tx},
  {NULL, NULL}  //いわゆる番兵法
};

int wap_init() {
  return 0;
}

int wap_handler(char argc, char *argv[]) {
  int i;

  for (i=0; cmd_tbl[i].cmd != NULL; i++) {
    if (strcmp( argv[0], cmd_tbl[i].cmd) == TRUE) {
      //テーブル中にコマンドがあれば、実行.
      cmd_tbl[i].func();
      return 0;
    }
  }
 
  return -1;
}

int wap_tx() {
  return 0;
}

int wap_rx() {
  return 0;
}
/*src/wap.h*/
int wap_handler(char argc, char *argv[]);
int wap_init();
int wap_tx();
int wap_rx();
/*test/TestWap.c*/

#include "unity.h"
#include "wap.h"

void setUp(void)
{
}

void tearDown(void)
{
}

void test_wap_init(void) {
  TEST_ASSERT_EQUAL(0, wap_init());
}

void test_wap_tx(void) {
  TEST_ASSERT_EQUAL(0, wap_tx());
}

void test_wap_rx(void) {
  TEST_ASSERT_EQUAL(0, wap_rx());
}

void test_rx_wap_handler(void) {
  char argc;
  char *argv[1] = {"rx"};

  TEST_ASSERT_EQUAL(0, wap_handler(argc, argv));
}

void test_tx_wap_handler(void) {
  char argc;
  char *argv[1] = {"tx"};

  TEST_ASSERT_EQUAL(0, wap_handler(argc, argv));
}

これを配置し終わったら、テストコードを置いたディレクトリにてコマンドを入力すれば初回テスト完了です。
お疲れさまでした。

$ rake all
Running system tests...
gcc -DUNITY_INCLUDE_DOUBLE -DUNITY_SUPPORT_TEST_CASES -DTEST -c -m32 -Wall -Wno-address -std=c99 -pedantic -Isrc/ -I../src/ -Itest/ src/ProductionCode.c -obuild/ProductionCode.o

...

gcc -DUNITY_INCLUDE_DOUBLE -DUNITY_SUPPORT_TEST_CASES -DTEST -c -m32 -Wall -Wno-address -std=c99 -pedantic -Isrc/ -I../src/ -Itest/ ../src/unity.c -obuild/unity.o
gcc -DUNITY_INCLUDE_DOUBLE -DUNITY_SUPPORT_TEST_CASES -DTEST -c -m32 -Wall -Wno-address -std=c99 -pedantic -Isrc/ -I../src/ -Itest/ src/wap.c -obuild/wap.o
src/wap.c:14: warning: initialization from incompatible pointer type
src/wap.c:15: warning: initialization from incompatible pointer type
gcc -DUNITY_INCLUDE_DOUBLE -DUNITY_SUPPORT_TEST_CASES -DTEST -c -m32 -Wall -Wno-address -std=c99 -pedantic -Isrc/ -I../src/ -Itest/ build/TestWap_Runner.c -obuild/TestWap_Runner.o
gcc -DUNITY_INCLUDE_DOUBLE -DUNITY_SUPPORT_TEST_CASES -DTEST -c -m32 -Wall -Wno-address -std=c99 -pedantic -Isrc/ -I../src/ -Itest/ test/TestWap.c -obuild/TestWap.o
gcc -lm -m32 build/unity.o build/wap.o build/TestWap_Runner.o build/TestWap.o -o build/TestWap.exe
build/TestWap.exe
test/TestWap.c:13:test_wap_init:PASS
test/TestWap.c:17:test_wap_tx:PASS
test/TestWap.c:22:test_wap_rx:PASS
test/TestWap.c:27:test_rx_wap_handler:PASS
test/TestWap.c:34:test_tx_wap_handler:PASS
-----------------------
5 Tests 0 Failures 0 Ignored
OK
FAIL: There were failures

参考本

目下、この本を参考に勉強しています。
今回のサンプルはマクロ付きのC風な感じでしかありませんでした。
ところが、本文中、特に付録B「Unityクイックリファレンス」ではもっとイケてる書き方を紹介しています。
これについては理解が深まり次第記事にしようと思っています。