「テスト駆動開発による組み込みプログラミング」のサンプルコードをCppUTestで実行する
Table of Contents
「テスト駆動開発による組み込みプログラミング」のサンプルコードをCppUTestで実行する :CPPUTEST:
前回の記事で、CppUTest を導入しました。今回は、TDD本 (「James W. Grenning (蛸島昭之監訳). テスト駆動開発による組み込みプログラミング.オライリー・ジャパン」)で使われているサンプルコードをWEBより入手して実行してみます。使うのは MSYS2環境です。
とりあえず実行はできましたが、ダウンロードしてきたビルド環境はそのままでは使わず、サンプルコードだけをコピーしてシンプルな環境を自分で作って勉強した方がよいという印象を持ちました。
サンプルコードの入手先
上述の本で使われているサンプルコードは、オライリーの本の紹介ページからジャンプした以下のURLからダウンロード可能です(2022.6.18時点)。
参考: https://pragprog.com/titles/jgade/test-driven-development-for-embedded-c/
ビルド
上記の入手先で jgade-code.zip というzipファイルが入手できますので、これを解凍します(次のようなファイル構成になっています)。
# # ls
.cdtproject .cproject .gdb_history .project .settings/ BookCode.dsw docs/ include/ lib/
Makefile MakefileCppUTest.mk MakefileUnity.mk mocks/ README.txt SandBox/ scripts/ src/ t0/ t1/
t2/ t3/ tests/ unity/ unity.framework/
このディレクトリ中にある、README.txt を見ると、最初はt0(ディレクトリ)から始めるのがいいよ、って書いてあります。とりあえず t0 ディレクトリに行ってビルドを試してみます。
Build all examples
cd <BookCodeParent>/code
make everything
If there are problems, you will probably want to build only
one directory at at time. code/t0 is a good place to start.
t0 ディレクトリに行くと、次のようなファイルがあります。Makefile が用 意されているのでビルドできそうです。また、srcディレクトリ以下には、 LightScheduler.c や RandomMinute.c といった本を持っている人なら、あー あれね、ってわかるファイルがおいてあります。
# # ls
.cproject .project include/ lib/ Makefile mocks/ objs/ src/ t0.dsw tests/ unity/
早速、makeを実行してみます。残念ながらエラーが出ました。
※ CppUTest を使うために、CPPUTEST_HOME を環境変数に設定しておきます。
# # make
compiling AllTests.cpp
compiling LightSchedulerRandomizeTest.cpp
compiling LightSchedulerTest.cpp
compiling RandomMinuteTest.cpp
compiling FakeTimeServiceTest.cpp
compiling LightControllerTestSpy.cpp
compiling FakeRandomMinute.c
In file included from C:/home/share/cpputest/cpputest-latest/include/CppUTest/MemoryLeakDetectorMallocMacros.h:12,
from <command-line>:
C:/home/share/cpputest/cpputest-latest/include/CppUTest/CppUTestConfig.h:264:14: error: ISO C90 does not support 'long long' [-Werror=long-long]
264 | typedef long long cpputest_longlong;
| ^~~~
C:/home/share/cpputest/cpputest-latest/include/CppUTest/CppUTestConfig.h:265:23: error: ISO C90 does not support 'long long' [-Werror=long-long]
265 | typedef unsigned long long cpputest_ulonglong;
| ^~~~
cc1.exe: all warnings being treated as errors
make: *** [/c/home/share/cpputest/cpputest-latest/build/MakefileWorker.mk:525: objs/mocks/FakeRandomMinute.o] エラー 1
C90 にかかわるエラーらしいです。Makefile の中をみると、コンパイルする ときの引数が, ”-std=c89” となっているのでこれが原因と思われます。
そこで、次のように Makefile を書き換えます。
#CPPUTEST_CFLAGS += -std=c89
CPPUTEST_CFLAGS += -std=c11
※gcc の -std オプションで規格を選択できます。
※CppUTest をソースコードからビルドしたときに作られる、 "(インストール先ディレクトリ)/build/MakefileWorker.mk" の中に,CPPUTEST_USE_LONG_LONGというマクロがあります。このマクロを設定すればこの変更は不要かもしれません(未調査)。
修正した後に再度 make を再実行してみます。C90 にかかわるエラーは抜けたのですが、今度は以下のようにとなり、ターゲットを make するルールがない、というエラーが発生しました。
# # make
compiling AllTests.cpp
compiling LightSchedulerRandomizeTest.cpp
compiling LightSchedulerTest.cpp
compiling RandomMinuteTest.cpp
compiling FakeTimeServiceTest.cpp
compiling LightControllerTestSpy.cpp
compiling FakeRandomMinute.c
compiling FakeTimeService.c
compiling LightControllerSpy.c
compiling LightScheduler.c
compiling RandomMinute.c
Building archive lib/libt0.a
a - objs/src/HomeAutomation/LightScheduler.o
a - objs/src/HomeAutomation/RandomMinute.o
make: *** 't0_tests' に必要なターゲット '/c/home/share/cpputest/cpputest-latest/lib/libCppUTest.a' を make するルールがありません. 中止.
CppUTest のライブラリである libCppUTest.a は make する必要がないので普通ならターゲットファイルにしないはずなのになんで?、って感じです。
※著者は CppUTest の開発者の一人みたいなのでこの本のサンプルコードを著者が作るときに、CppUTest そのものをビルドする環境で作成したのではないか、なんて気がしています。
仕方がないので、Makefile に空のターゲットファイルを追記します。
$(CPPUTEST_LIB):
# ←ここはTAB
これでようやくビルドが通るようになり、テスト実行ファイル(t0_tests.exe)が作成されました。
実行結果
makeすると、次のような結果が出力されます。
※OK、のところが t0_tests.exe の実行結果。
compiling AllTests.cpp
compiling LightSchedulerRandomizeTest.cpp
compiling LightSchedulerTest.cpp
compiling RandomMinuteTest.cpp
compiling FakeTimeServiceTest.cpp
compiling LightControllerTestSpy.cpp
compiling FakeRandomMinute.c
compiling FakeTimeService.c
compiling LightControllerSpy.c
compiling LightScheduler.c
compiling RandomMinute.c
Building archive lib/libt0.a
a - objs/src/HomeAutomation/LightScheduler.o
a - objs/src/HomeAutomation/RandomMinute.o
Linking t0_tests
Running t0_tests
.............................................
OK (45 tests, 45 ran, 407 checks, 0 ignored, 0 filtered out, 1 ms)
その後とまとめ
同様にして t1, t2, t3ディレクトリのコンパイルをしたのですが、同様のエラーの他、サンプルコードも、”;がない”、といった単純なエラーが出ました(まじか・・・)。
ダウンロードしてきたサンプルコードおよび実行環境はすぐにビルドできると思ったのですが、それなりにエラーに対処しなければいけないようです。
単体テストのお勉強がやりたいことであって、サンプルコードのビルドを通すのが目的ではないのでダウンロードした環境を使ったビルド作業は中断することにしました。
もちろん環境そのもの作り方は大変参考になりますし、コード中のバグも軽微なものなので役には立つと思います。とはいうものの、お勉強がしたい人は単純化した makefile を自分で作り直した方がよいかもしれません。