UnityとCMockはC言語のためのxUnitとMockフレームワーク。UnityとCMockの使い方について、電子書籍とペーパーブックが出ている。6ドルくらいなので、購入して読んでみた。


Embedded Testing with Unity and CMock by Mark VanderVoord (eBook) - Lulu


内容はとても異色だ。まず、ページが正方形なのが、なんかおかしい。物語形式で話が進んでいく。途中に可愛い?!マンガチックなイラストがたくさんでてくる。文学表現が初めの方はおおくて、知らない単語が多かったりした。

前半がUnityの話、後半がCMockの話。全部で40ページくらいなので、あまり内容は深くない。使い方が説明されている。ツールについてくるドキュメントよりは詳しくツールが解説されている。特に、オプション周り。

この本、手順はしょりすぎ。。。けっこう苦労したので、補う意味で手順をメモしておく。

なお、UnityとCMock利用するためには、Rubyが必須ツール。Rubyスクリプトをガンガン使うため。事前にインストールすること。

CMockのダウンロード

githubからダウンロードします。unityやceelingというプロジェクトも必要になります。サブモジュール扱いされているので、それらも取得します。

#CMockをcloneする
$ git clone git://github.com/ThrowTheSwitch/CMock.git
# Unityとceelingをcloneする
$ git submodule init
$ git submodule update

CMockをcloneする

$ git clone git://github.com/ThrowTheSwitch/CMock.git

Unityとceelingをcloneする

$ git submodule init
$ git submodule update

Unityはどんなコンパイラだって、コンパイルできるらしい(と書いてあった)。まずは、自分が使う予定のコンパイラでUnityが動作するかチェックする。

Cygwinだと、どうもWindowsに解釈されるので、makefileをチョット修正。

$ cd CMock/vendor/unity
$ emacs makefile
$ make

こんな感じに修正。

#ifeq ($(OS),Windows_NT)    
# TARGET_EXTENSION=.exe
#else
TARGET_EXTENSION=.out
#endif

—————–

#ifeq ($(OS),Windows_NT)
# CLEANUP = del /F /Q build\* && del /F /Q $(TARGET1) && del /F /Q $(TARGET2)
#else
CLEANUP = rm -f build/*.o ; rm -f $(TARGET1) ; rm -f $(TARGET2)
#endif

—————-

./$(TARGET1)

これで174のテストが走る。Great! v(o´∀`o)v

別のコンパイラを試すには、makefileの先頭にC_COMPILER=gccという部分を修正する。

C_COMPILER=g++
C_COMPILER=gcc-3

CMockはデフォルトコンパイラがgccのようだが、他のコンパイラでのテスト方法がかワカラなかった。gccでのテスト方法は、以下を実行する。

$ cd CMock
$ rake

Unity編(p3~)

以下のようにコマンドを実行することで、MenacingLED.c/MenacingLED.h/TestMenacingLED.cができる。

$ ruby auto/generate_module.rb MenacingLED
File /home/TSUNEMICHI/src/unity/book/auto/../src//MenacingLED.c created    
File /home/TSUNEMICHI/src/unity/book/auto/../src//MenacingLED.h created
File /home/TSUNEMICHI/src/unity/book/auto/../test//TestMenacingLED.c created
Generate Complete

次に以下のコマンドでTestMenacingLED_Runner.cができる。

$ ruby auto/generate_test_runner.rb test/TestMenacingLED.c

makefileを編集する。以下の4つを追加する。作成された4つのファイルをコンパイルしてリンクし、実行ファイルを生成。実行する。

# Unity File
SRC_FILES = src/unity.c

# Source Files
SRC_FILES += src/MenacingLED.c
SRC_FILES += test/TestMenacingLED.c
SRC_FILES += test/TestMenacingLED_Runner.c

$ make
rm -f build/*.o ; rm -f book.exe ; mkdir -p build
gcc -Isrc -DTEST -DUNITY_SUPPORT_64 src/unity.c src/MenacingLED.c test/TestMenacingLED.c test/TestMenacingLED_Runner.c -o book.exe

./book.exe
test/TestMenacingLED.c:14:test_MenacingLED_NeedToImplement:IGNORE
-----------------------
1 Tests 0 Failures 1 Ignored
OK

CMock編(p14~)

S5モジュールを生成。

$ ruby auto/generate_module.rb S5    
File /home/TSUNEMICHI/src/unity/book/auto/../src//S5.c created
File /home/TSUNEMICHI/src/unity/book/auto/../src//S5.h created
File /home/TSUNEMICHI/src/unity/book/auto/../test//TestS5.c created
Generate Complete

S5_Exec()をS5.hとS5.cに空実装する。

同様にして、ButtonsとS5モジュールを生成する。

$ ruby auto/generate_module.rb Buttons    
$ ruby auto/generate_module.rb S5Ctrl

Buttons_CheckS5Switch と S5Ctrl_Silenceをヘッダに宣言する。

ここからが書いていないのだが、モックオブジェクトを生成する。以下をカレントディレクトリにコピーしてくる。

  • cmock/lib
  • cmock/config/
  • cmock/src(cmock.cとcmock.hが欲しい)

mocksディレクトリを作成して、cmock生成用のスクリプトを実行する。

$mkdir mocks
$ ruby lib/cmock.rb src/Buttons.h src/S5Ctrl.h
Creating mock for Buttons...
Creating mock for S5Ctrl...

Makefileを編集する。インクルードファイルにもmocksディレクトリを追加。

cmockを利用するためには、unity.cとcmock.cも同時にコンパイルしてやる。最終的なMakefileはこんな感じ

C_COMPILER=gcc 
TARGET_BASE = MenacingLED 
TARGET_BASE2 = S5 
TARGET_EXTENSION=.exe 
TARGET = $(TARGET_BASE)$(TARGET_EXTENSION) 
TARGET2 = $(TARGET_BASE2)$(TARGET_EXTENSION)

# Unity Files 
SRC_FILES   = src/unity.c 
SRC_FILES2  = src/unity.c

# CMock Files 
SRC_FILES  += src/cmock.c 
SRC_FILES2 += src/cmock.c

# Source Files 
SRC_FILES += src/MenacingLED.c 
SRC_FILES += test/TestMenacingLED.c 
SRC_FILES += build/TestMenacingLED_Runner.c

SRC_FILES2 += src/S5.c 
SRC_FILES2 += test/TestS5.c 
SRC_FILES2 += build/TestS5_Runner.c

SRC_FILES2 += mocks/MockButtons.c 
SRC_FILES2 += mocks/MockS5Ctrl.c

INC_DIRS  =-Isrc 
INC_DIRS +=-Imocks 
SYMBOLS=-DTEST -DUNITY_SUPPORT_64

CLEANUP = rm -f build/*.o ; rm -f $(TARGET); rm -f $(TARGET2) ; mkdir -p build

all: clean default

default: 
        ruby auto/generate_test_runner.rb test/TestMenacingLED.c build/TestMenacingLED_Runner.c 
        ruby auto/generate_test_runner.rb test/TestS5.c build/TestS5_Runner.c 
        ruby lib/cmock.rb src/S5Ctrl.h 
        ruby lib/cmock.rb src/Buttons.h 
        $(C_COMPILER) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES) -o $(TARGET) 
        $(C_COMPILER) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES2) -o $(TARGET2) 
        ./$(TARGET) 
        ./$(TARGET2)

clean: 
        $(CLEANUP)