2.4K Views
February 16, 23
スライド概要
2023/2/16(木)Twitterスペースの連続イベント(https://twitter.com/i/spaces/1dRKZMXygnQxB)の説明資料です。
前々回の【ホスト編】ではLEDドライバをテーマにホストPCでテスト駆動開発(以降TDD)した際の概要を話しました。
前回の【ターゲット編】ではマイコンでTDDを試した話をしました。
今回は【実装編】としてホスト編・ターゲット編でテストコードを書いたときの話です。
組込みソフトウェアエンジニア。 技術バックボーンはC言語・ベアメタル。 CQ EVカートのオーナーで、ハード・ソフトウェアの改造を通じて自身のスキルアップを日々考え中・・・。 LAPRASポートフォリオ: https://lapras.com/public/k-abe GitHub: http://github.com/grace2riku Qiita: https://qiita.com/juraruming Zenn: https://zenn.dev/k_abe よろしくね。
組込みソフトウェア基礎 現場ノウハウを知ろう テスト駆動開発の魅力を語る 〜実装編〜 2023/2/16(木) 19:30〜20:15 Twitterスペース: https://twitter.com/i/spaces/1dRKZMXygnQxB
自己紹介 1 ▪パーソルクロステクノロジー株式会社 第1技術開発本部・東日本開発部 首都圏2G 阿部 耕二(あべ こうじ) ▪医療機器開発 ・組込みソフトウェア開発。 ・C言語、ベアメタルの開発業務経験がほとんど。 2
自己紹介 2 ▪技術書を書いて技術書典13に参加したり、 ▪マイコンのコンテスト(※)に参加したり、 ※SPRESENSE™ 活用コンテスト 組込みソフトウェア開発が好きなおじさんです。 よろしくお願いします。 ▪LAPRASポートフォリオ:https://lapras.com/public/k-abe 3 ▪twitter: @juraruming
【テスト駆動開発(以降TDD) とは何?】 ・文字通りテストでソフトウェ ア開発を駆動(進めていく)こと。 テストファーストでより良い設計 を導く。 4
【TDD学習メリット】 1.楽しい 2.不安が減る 3.良い設計を導く 4.ハードウェアがなくてもテスト を進める方法論が学べる 5
ホスト・ターゲットとは? ▪ ホストでTDDする特徴 ・ホストとは? ホストPC → ホスト 組み込み装置 → ターゲット ・組み込み装置にテストプログラムをダウ ンロードしなくて良いので早くテストでき る。 ・ハードウェアを制御しない。ハードウェ アを仮想的に扱う。 ・テストフレームワークに自由度がある。 GoogleTest, CppUTest, Unity, その他 LED ▪ ターゲット ・ホストに比べてテストを回す【スピー TDDを実行する環境で、 ド】が遅い(ホスト→ターゲットへのプロ グラムのダウンロードなど)。 ホスト → ホストPCでTDDする。 ・ハードウェアを制御する。ハードウェア を絡めたテストができる。 ターゲット→組み込み装置でTDDする。 ・使えるテストフレームワークに制限がで てくる。マイコンはRAMが少ないため。 CppUTest, Unity, その他 6
【今回の環境について】 【ホスト】 ▪ ホストPC: macOS Monterey バージョン 12.6 ▪ テストフレームワーク: CppUTest 4.0 ▪ コンパイラ: Apple clang version 11.0.0 (clang-1100.0.33.8) ▪ テスト対象プログラミング言語: C ▪ ビルドシステム: cmake 3.21.1 【ターゲット】 ※ターゲットは動作確認できませんでした。構想のみ。 ・STM32CubeIDE Version: 1.11.0 ・テストフレームワーク: CppUTest 4.0(ホストと同じ) 7
【ホスト編のテストコード実装】 ホスト編の一連の手順は次の資料に書きました。 よければ参照してください。 ホスト編資料: 組み込みソフトウェア基礎_【連続講座 #6】TDD#2 LED ライ (ホ ストPC編)_slide https://www.docswell.com/s/juraruming/ 5G31LZ-2022-10-31-220730 ソースコードはこちら。 https://github.com/grace2riku/evkart_tdd/tree/LedDriver_221031 バ ド 8
【ホスト編のテストコード実装】 やること ・テストリスト作成 ・テスト環境つくる ・テストを書く 9
【ホスト編のテストコード実装】 ▪テストリスト作成 ・テストすることをリスト化する。組込みTDD本の手順を真似した。 例) LedDriverテストリスト https://github.com/grace2riku/evkart_tdd/tree/LedDriver_221031 10
【ホスト編のテストコード実装】 ▪ テスト環境をつくる CppUTestの場合、次のスクリプト実行でTDD環境の雛形がつくれる。 $ NewPackageDirs HallSensorLedDriver creating src/HallSensorLedDriver creating include/HallSensorLedDriver creating tests/HallSensorLedDriver $ NewCModule.sh HallSensorLedDriver HallSensorLedDriver creating include/HallSensorLedDriver/HallSensorLedDriver.h creating src/HallSensorLedDriver/HallSensorLedDriver.c creating tests/HallSensorLedDriver/HallSensorLedDriverTest.cpp 雛形のソースコードをビルド対象に追加し、テストを書いていく。 ホスト編資料のp28を参照。 11
【ホスト編のテストコード実装】 ▪テストを書く テストコード: // ドライバを初期化したら、すべてのLEDが消灯している TEST(HallSensorLedDriver, LedsOffAfterCreate) { unsigned char virtualLeds = 0xff; // 消灯確認のためにLEDオンに初期化 HallSensorLedDriver_Create(&virtualLeds); // ドライバ初期化 BYTES_EQUAL(0, virtualLeds); // 初期化後に0(LEDオフ)か確認 } ソースコード: https://github.com/grace2riku/evkart_tdd/blob/LedDriver_221031/tests/ HallSensorLedDriver/HallSensorLedDriverTest.cpp 12
【ホスト編のテストコード実装】 ▪テストを書く プロダクトコード: ドライバを初期化(すべてのLEDをOFFする) static unsigned char* hallSensorLedsAddress; void HallSensorLedDriver_Create(unsigned char* address) { hallSensorLedsAddress = address; *hallSensorLedsAddress = 0; } ソースコード: https://github.com/grace2riku/evkart_tdd/blob/LedDriver_221031/ src/HallSensorLedDriver/HallSensorLedDriver.c 13
【ターゲット編のテストコード実装】 ・LedDriverのTDDは動作確認に至りませんでした。 ※LedDriverのベースにしようとした後述のお試しコードが動かなくなり原因調査中・・・(ホス トPCのOSもしくはSTM32CubeIDEのバージョンアップが原因かと推測)。 実装の構想はこちらの資料にまとめました。 https://www.docswell.com/s/juraruming/KN4MW5-2022-12-15-210619 ・以前、簡単なお試しコードでSTM32マイコンでTDDした時の話をしたいと思います。 Qiita記事はこちらです。 STM32CubeIDEにCppUTestを環境構築し、STM32マイコンでTDDする https://qiita.com/juraruming/items/1f91db17ba93b40d3730 ソースコードはこちらです。 https://github.com/grace2riku/hello_stm32_cpputest 14
【ターゲット編のテストコード実装】
テストコードはこちら(テスト自体に意味はないです)
https://github.com/grace2riku/hello_stm32_cpputest/blob/main/446re_test/Core/Src/
test_src.cpp
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTestGroup)
{
};
TEST(FirstTestGroup, FirstTest) // 必ず失敗するテスト
{
FAIL("FAIL: FirstTestGroup, FirstTest\n");
}
TEST(FirstTestGroup, SecondTest) // 必ず成功するテスト 引数に0を与えているから
{
CHECK_EQUAL_ZERO(0);
}
TEST(FirstTestGroup, IntSize) // 成功するテスト STM32マイコンは32bitでintは4byteのため
{
LONGS_EQUAL(4, sizeof(int));
}
15
【ターゲット編のテストコード実装】
main関数からテスト実行します。
https://github.com/grace2riku/hello_stm32_cpputest/blob/main/446re_test/Core/Src/main.cpp
int main(void) {
const char* empty[] = {};
const char* command_v[] = {"cpputest", "-v"};
printf("\n----- RunAllTests(0, empty) -----\n");
CommandLineTestRunner::RunAllTests(0, empty);
printf("\n----- RunAllTests(2, command_v) -----\n");
CommandLineTestRunner::RunAllTests(2, command_v);
while (1)
{
}
}
16
【ターゲット編のテストコード実装】
テストの実行結果
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTestGroup)
{
};
TEST(FirstTestGroup, FirstTest) // 必ず失敗するテスト
{
FAIL("FAIL: FirstTestGroup, FirstTest\n");
}
TEST(FirstTestGroup, SecondTest) // 必ず成功するテスト 引数に0を与えているから
{
CHECK_EQUAL_ZERO(0);
}
TEST(FirstTestGroup, IntSize) // 成功するテスト STM32マイコンは32bitでintは4byteのため
{
LONGS_EQUAL(4, sizeof(int));
}
動画はこちら→https://youtu.be/8rb3picKkjw
17
【ホスト編・ターゲット編の実装ポイント】 ▪テストは資産。わかりやすい命名を ▪ターゲットでTDDする際は必要リソース を把握する。 18
【ホスト編・ターゲット編の実装ポイント】 ▪テストは資産。わかりやすい命名を ●テストは繰り返し使うことになると思う。後 で使うときにわかりやすいテスト名にしてお く。 ●テスト名とテスト内容が不一致、テストの中 で何項目もテストしているなど、テストの品 質・わかりやすさも重要だと思う。 19
【ホスト編・ターゲット編の実装ポイント】 ▪ターゲットでTDDする際は必要リソースを把握する。 制約の厳しい組込みでTDDする場合、テストフレームワークがどれく らいRAMを消費するか把握しておく。 テストできました、しかしアプリケーション組み込めません、ではお 話しにならない・・・。 ※STM32マイコンにCppUTestを組み込んだときのメモリ使用量はこ ちらです。参考までに。 STM32CubeIDEにCppUTestを環境構築し、STM32マイコンでTDDする -> メモリ使用量 https://qiita.com/juraruming/items/1f91db17ba93b40d3730 20
終わり ご静聴ありがとう ございました。 21