組み込み開発の単体テスト時のベストプラクティス


45

組み込みシステム用に記述されたユニットテストコードのベストプラクティス戦略を探しています。組み込みシステムとは、デバイスドライバー、ISRハンドラーなどのコード、つまり金属に非常に近いものを意味します。

ICEを使用してハードウェアでテストしないと、ほとんどのユニットテストは不可能です。組み込みユニットは、機械式スイッチ、ステッピングモーター、電球などの他の刺激にも接続する必要がある場合があります。これは通常、手動で行われます。自動化は優れていますが、達成するのは難しく、費用がかかります。

更新

組み込みプロジェクトのテストで非常に成功していると思われるCテストフレームワークに出会いました。ハードウェアをモックするというアイデアを使用します。チェックアウトユニティCMockを、そしておそらくceedlingが

2016年7月6日更新

出くわしたcmocka -より積極的に取り組んでいるように見えます。


1
同様の状況で、Cmocka
Mawg

:私は、トピックに関する非常に徹底したチュートリアル書きましたがceedlingとのユニットテスト組み込みCアプリケーションを
ドミトリー・フランク

回答:


28

できるだけ早い段階でハードウェアの依存関係を抽象化し、ソフトウェアエミュレーション/テストハーネスでシステムを構築し、あらゆる種類のテストフレームワークを有効にします。多くの場合、開発用PCを使用して、システム全体の95%以上をテストしました。余分なオーバーヘッド(抽象化の別のレイヤー)のコストは、その抽象化の結果として生成されるクリーンなコードによって簡単に取り戻されました。

組み込みシステムの真のベアメタル部分のテストは、通常、アプリケーションが達成することさえ期待できるものをはるかに超えてファームウェアを破壊する別個のアプリケーション(ユニットテスト?)です。自動化は可能ですが、費用はかかりますが、一般的ではありません。

つまり、フルICEを含む単体テストハードウェアハーネスを構築する予算がある場合を除きます。一般に機能テストは小さいため、これはまったく問題ありません。


これとジョナサンクラインイーイーの答えを組み合わせることは、成功する戦略です。抽象化を使用して、ほとんどのコードをテスト可能にし、単純なテストフレームワークを使用して、実際のハードウェア上の抽象化できないビットをテストします。私は個人的にこの作品を複数のプラットフォームで見ました。
ティムウィリスクロフト

3
当社が製造するすべての製品には、ターゲットプラットフォームおよびPC用のドライバーを実装したハードウェアアブストラクションレイヤーがあります。これにより、ユニットテストを簡単に実行できます。他の利点:高速システムテストを実行し、ハードウェアなしでほとんどのソフトウェアを開発できます(後で利用可能になります)。
MaR

15

開発に必要なツールはシグナルインジェクタです。組み込みシステムには、ホストシステムとのインターフェイスがいくつかあります(通常、デバッグ用に予約されたシリアルポート経由)。これを使用してテストデータを送信します(最適なオプションは簡潔なASCII形式であるため、人間でも簡単にシミュレートできます)。

私はあなたの質問のこの部分に完全に同意しません:「自動化は素晴らしいことですが、達成するのは難しくて高価です。」

TeraTermをシリアルポート信号インジェクターとして使用し、TeraTermマクロを作成する(約20分かかります)ため、組み込みシステムの任意の部分(ドライバーレイヤー、O / S、レイヤー4-5などTeraTerm:http : //en.sourceforge.jp/projects/ttssh2/

組み込みシステムでシリアルポートを使用できない場合は、ハードウェアツールを使用してUSB /シリアルポートデータをデジタル信号に変換します(安価で簡単に実現できます)。これを読んで、30ドルのマイクロコントローラーボード(UBW:http ://www.schmalzhaus.com/UBW32/ )を使用して、USB /シリアル経由で送信されるTeraTermマクロを介して刺激を注入することにより、実動用の組み込みシステムをテストしています。マイクロコントローラ。ターゲットの組み込みシステムのデジタル入力を実行し、デジタル出力を監視する修正されたファームウェアを実行しています。これに関連して、データインジェクションとデータ検証を自動化するPythonスクリプト(pyserialとpexpectを使用)を開発しました。どれも硬くなく高価でもありません。私の経験では、テストチームが経験が浅く、これらの簡単なソリューションを思いつかない場合、マネージャーは大金(30,000ドルのテスト機器など)を費やします-残念ながら、汎用の大型鉄製機器にはテストケースが含まれないことがよくありますターゲットシステムの最悪のタイミングなどをキャッチします。 そのため、テストカバレッジには安価な方法の方が適しています。 信じようと信じまいと。


1
私は自動車業界で働いているときに高価な声明を出しましたが、すべてが決定論的で再現可能である必要があり、通常、開発には数人のエンジニアが必要です。また、テストチェーンで使用されるアイテムが増えると、メンテナンスも問題になります。UBWについて教えてくれてありがとう、それは良い選択肢のようです。
-tehnyit

2
ただ、LabViewを始めさせないでください。それは通常恐ろしいことです。
ジョナサンクラインIEEE

1
私たちのテストエンジニアはLabViewを愛しています。
tehnyit

これは私がさまざまなテストのために行うことと非常に近いもので、Pythonとそのシリアルライブラリのみを使用しています。その後、低レベルのテストをFlask / Qtのようなものと一緒にPythonのユニットテスターに​​プラグインして、使いやすいフロントエンドを提供することもできます。
radix07

5

これは非常に難しい問題です。

私は実際に組み込みシステム用のユニットテストハーネスを設計しました。これにより、ハードウェアイベント/割り込みをシミュレートし、実行のタイミングを制御できます(同時実行による可能性のあるすべてのインターリーブを確実にカバーするため)。プログラマーが実際に実装して機能させるまでに2年以上かかります。このプロジェクトはプロプライエタリな開発ですが、同様の(設計が簡単な)プロジェクトがこちらから入手できます

はい、自動化は素晴らしいことです。はい、達成するのは非常に難しく、高価です。はい、時々あなたはそれをしなければなりません。まれに、ほとんどの場合、私の経験では、ステッピングモーターと電球を使用してすべてを手動で動作させる方が高速で安価です。


通常、刺激の生成または結果の測定のいずれかにおいて、手動でエラーが発生しやすいことがわかりました。単体テストが複雑な場合は特にそうです。ユニットテストを再度やり直す必要がある場合、エラーが発生しやすくなります。
-tehnyit

@tehnyit-はい、それが自動化システムを開発することにした理由です。手動ですべてを実行できない場合もありますが、単体テストは包括的でタイミングの問題をカバーする必要があります。そのため、あまり選択肢はありませんが、このレベルでの自動化非常に高価です。
-littleadv

4

編集:私の答えはマッツンツに近いと思います...


この問題を他の人、コードの外部の何かに依存するすべてのテスト(システムクロック、永続的なファイルシステム、データベース、外部Webサービスに接続するなど)に関連付けたいと思います。それらすべてに対して同じポリシーを提案し、2つのコード層で2つのレベル分離します。

単一の外部操作のテスト

各操作を物理的にテストすることもできます。システムクロックが正しい時間を提供していることを確認し、ファイルが実際に書き込まれたことを記憶していることを確認し、デバイスが単一の操作を受信することを確認します...

これらのテスト:

  • 可能な限りシンプルにする必要があります:アルゴリズムは一切使用せず、条件もループも使用しません
  • 順序に依存し、マシンに依存する場合があります。したがって、厳密な順序に従って、各ハードウェアで繰り返す必要があります。
  • プロジェクトの過程でほとんど安定しているので、頻繁に実行する必要はありません
  • そのため、それらを手動で実行することはオプションです。過度に複雑でなければ、自動化はさらに優れている
  • テストされているのはあなたのコードはなく、あなたのコードに必要なツールであることに注意してください...

外部操作を結び付けるロジック(コード、アルゴリズム)のテスト

実際の外部操作を行うためのコード層を持ち、それらを簡単にモックできるインターフェースに隠れることで、ロジックは実際の物理デバイスに依存しなくなります...

通常のプロジェクトと同じように、テストが困難な埋め込みコードではもう簡単にテストできます


3

通常、組み込みCPUシミュレータは、ハードウェアもシミュレートするようにプログラムできます。Xen以外のすべての仮想化テクノロジーがこれを実行します。ただし、物理アドレスまたはx86のI / Oバスのアドレスにレジスタがあるふりをするコードを記述する必要があり、ソフトウェアが物理アドレスであるかのようにこれらのアドレスへの読み取りと書き込みに応答する必要があります制御およびステータスレジスタがアクセスされていたチップ。

これを行うには、QEMUを変更することをお勧めします。しかし、それは簡単ではありません。通常、この種のことは、マイクロコントローラとI / O用の他のコアを使用してカスタムチップを設計する場合にのみ行われます。

ARM Holdingsが販売する開発システムはこれを提供し、QEMUをハッキングするよりも簡単に操作できますが、非常に高価です。

単一のサブルーチンを実行する複数のオープンソースARMエミュレータがあり、それ自体が他のサブルーチンを呼び出すことができ、ハードウェアアクセスに依存しないサブルーチンのパフォーマンスのチューニングをデバッグするために使用できます。これらのいずれかを使用して、ARM7TDMIのAES暗号化を最適化することに成功しました。

CまたはC ++で単純な単体テストハーネスを作成し、テスト対象のクラスまたはサブルーチンをリンクして、シミュレータで実行できます。

LinuxまたはMac OS Xカーネルコードの単体テストの方法について、私は長年同様の問題を熟考してきました。それは可能であるはずですが、私は実際に試したことはありません。1つは、ユニットテストフレームワークをカーネルに直接リンクして、コードを単独でテストするのではなく、完全なカーネルを構築することです。次に、何らかの外部インターフェイスからユニットテストを実行します。

コードカバレッジツールを使用して、外部インターフェイスを介して完全なパッケージとしてファームウェアをテストする方が生産性が高い場合があります。カバレッジツールは、まだテストされていないコードパスを検出するため、さらにカバレッジを取得するために外部テストを追加できます。


3

非埋め込みTDDと同様に、モックオブジェクトは間違いなくあなたの友人です。

基盤となるハードウェアへのインターフェイスをクリーンでシンプルな状態に保ち、最低レベル以上のすべてをモックアウトできるようにし、テストの時間をずっと楽にします-テスト容易性を念頭に置いて組み込みアプリケーションを設計すると、テストは常によりスムーズになります。

また、プロジェクトのかなり遅くまでオンラインでテストできない可能性があるからといって、オンラインテストのスイートも準備してはいけないという意味ではありません。

これらは(最初に)オフラインでテストできなかったビットのみをテストする必要があります。もちろん、それはTDDではありません(事前にテストを作成しているため)が、オフラインTDDの開発により、ハードウェアインターフェイスの外観がどのようなものであるか、したがってどのオンラインテストを実行する必要があるかがわかります。

また、オンライン開発がオフライン開発よりもはるかにコストがかかる場合(私が働いている場所での場合)、実行するテストのセットが十分に理解されているため、オンラインでの時間を大幅に節約できます。


モックオブジェクトをプレートに持ってくるための+ 1、@マーク。問題の1つは、モックオブジェクトの精度を確保することです。つまり、モック対象のオブジェクトを理解することは非常に深いはずです。これは、開発者がインターフェイスしている外部オブジェクトの動作を理解するように強制するため、優れています。
-tehnyit

1

組み込み開発では、境界スキャンを実行して、アプリケーション全体(ハードウェアを含む)が機能することを確認することがよくあります。システムデバッグ用のJTAGも参照してください。

ハードウェアにリンクしない純粋なソフトウェアルーチンのテストは、Checkなどの標準Cユニットテストフレームワークによって実行できます。ただし、メモリの制限に注意してください(特に小さなデバイスのスタックスペースなど)。契約を知ってください!また、ハードウェアからソフトウェアルーチンを抽象化して、より大きなテストカバレッジを取得することもできますが、これは通常、小型PICやAVRなどの組み込みデバイスのパフォーマンスの点でコストがかかります。ただし、ハードウェアポートをモックして、より大きなカバレッジを実現できます(もちろん、モックをテストすることもできます)。

チップまたは回路シミュレータ用のエミュレータを使用することもできますが、これらの種類のツールは高価で(特に組み合わせで)複雑です。


バウンダリスキャンとJTAGには同意しますが、ハードウェアの設計により、常に可能または利用できるとは限りません。
-tehnyit
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.