先日、Renesasのアプリケーションノートに従い「e2studio(GCC for RX)で、CUnitによる単体テストを試してみた」をやりましたが、今回はテストフレームワーク Unity で同じことを試しました。結果、CUnitと同様にテストできました
1. 環境
- Windows 10 Pro: バージョン 21H2、ビルド 19044.2130
- e2studio: 2022-07 (64bit版)
- コンパイラ: GCC for Renesas RX 8.3.0.202202
- Unity: 2.5.2
- テスト環境:RX Simulator
2. テスト対象プロジェクトを作成する
- ファイル > 新規 > Renesas C/C++ Project > Renesas RX より、プロジェクトを新規作成
- テンプレートは
GCC for Renesas RX C/C++ Executable Project
を選択 - この記事では、プロジェクト名を
SampleUnity
としています
- テンプレートは
Select toolchain, device & debug settings
のダイアログで下記に設定し「次へ」を押下Select Coding Assistant Settings
のダイアログで「終了」をクリック
3. Unityの導入 と 準備
- GitHub - ThrowTheSwitch/Unity: Simple Unit Testing for Cから、ソースをダウンロード
Unityの
/src
フォルダにあるunity_internals.h
、unity.c
、unity.h
を、作成したプロジェクトの/src
フォルダにコピー/generate
フォルダに下記ファイルをsbrk.c
として作成
詳細理解していませんが、putchar や printf を使う場合、この関数が必須のようでした
// 本コードは、Renesasのアプリケーションノートから変更なし // - putchar や printf を使うには、この sbrk 関数が必要なようだ。関数がない場合、次のエラーが出た // collision in (null): pc ffe83663 heap 00001018 stack 0000015c // - Unityはテスト結果の出力に putchar を使うので、この関数定義は必須 void* sbrk(int incr) { extern char end; /* Set by linker. */ static char * heap_end; char * prev_heap_end; if (heap_end == 0) heap_end = &end; prev_heap_end = heap_end; heap_end += incr; return (void *)prev_heap_end; }
3. テスト対象コードの追加
/src
フォルダにテスト対象ソースsource.h
、source.c
を追加
// 本コードは、Renesasのアプリケーションノートから変更なし #ifndef SOURCE_H_ #define SOURCE_H_ int add(int a, int b); int subtract(int a, int b); #endif /* SOURCE_H_ */
// 本コードは、Renesasのアプリケーションノートから変更なし #include "source.h" int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; }
4. テストコードの作成
メインのソースコードを下記のように修正
#include <stdlib.h> // _Exit() #include "unity.h" #include "source.h" // RUN_TEST毎の前後で呼ばれる関数(関数定義は必須、中身は空でも良い) void setUp(void) { } void tearDown(void) { } // 下記テストは、Renesasのアプリケーションノートの内容を、Unity用に書き換えたもの static void test_Add_01(void) { TEST_ASSERT_EQUAL_INT(1, add(1,0)); } static void test_Add_02(void) { TEST_ASSERT_EQUAL_INT(10, add(1,9)); } static void test_Subtract(void) { TEST_ASSERT_EQUAL_INT(0, subtract(1,1)); } void main(void) { // テストケースが失敗した数 int num_of_failures; // テスト開始 UNITY_BEGIN(); // 各テストを実施 RUN_TEST(test_Add_01); RUN_TEST(test_Add_02); RUN_TEST(test_Subtract); // テスト終了 num_of_failures = UNITY_END(); // プログラムを強制終了し、シミュレータを抜ける // - このやり方が正しいか分からないが、Renesasのアプリケーションノートの方法(generate/start.Sにbrkを追加)だと、 // プログラム終了してからコマンドプロンプトに戻るまでに時間が掛かるので、このようにしている _Exit( (num_of_failures == 0) ? EXIT_SUCCESS : EXIT_FAILURE ); }
- ポイント
- テストコード
test_Add_01()
などを記述
※アプリケーションノートだとテストは別ファイルtestsource.c
でしたが、ここでは簡単のためテストを同一ファイルに記述してます - テスト実行コードを main() 内に記述
- テスト完了後、_Exit() でプログラムを強制終了し、シミュレータを抜ける
※このやり方が正しいか分からないですが、アプリケーションノートの方法(generate/start.Sにbrkを追加)だと、コマンドプロンプトに戻るまでに時間が掛かるので、このようにしてます
- テストコード
5. テスト用のバッチファイル作成
/Debug
フォルダに下記ファイルをrun_test.bat
として作成、ビルド後のフェーズでテストを実行する
@echo off REM シミュレータでテストを実行する REM ★GCC for RX のバージョン・インストール先に合わせて rx-elf-run.exe のパスを変更 REM ★プロジェクトの設定に合わせて *.elf のファイル名を変更 echo ******************** test phase ******************** "C:\ProgramData\GCC for Renesas RX 8.3.0.202202-GNURX-ELF\rx-elf\rx-elf\bin\rx-elf-run.exe" SampleUnity.elf echo ****************************************************
6. 確認
この手順まで進めると、下記のフォルダ構成になります(水色が追加・修正したファイル)
7. プロジェクトのプロパティ設定
プロジェクトのプロパティを開いて、下記を設定
8. Unityを使用した単体テストを実行する
プロジェクトをビルドすると、ビルドに続いて、テストが実行される
※先日の記事と同様、設定すればVS Code上でも実行可能です