組み込みソフトウェアのテストに関する 10 のヒント

組み込みソフトウェア開発では、一般的に、テストとコーディングに費やす時間の比率は 3:1 です (実際にはそれ以上の場合もあります)。プログラミングとテストのレベルが上がるにつれて、この比率は低下し続けますが、何はともあれ、ソフトウェア テストは平均的な人にとって非常に重要です。

何年も前、組み込みをより深く理解するために、ある開発者が Oracle に次のような質問をしました: 「システムが何を行っているかを知り、理解するにはどうすればよいですか?」Oracle はこの質問に少し驚きました。当時、現代の組み込み開発者のほとんどは、「どうすればプログラムをより速く実行できるか」や「どのコンパイラが最適か」などの表面的な質問をしていました。

したがって、この珍しいが成熟した質問に直面したオラクルは、喜んで真剣に答えました。「あなたの質問は非常に深く、成熟しています。なぜなら、常に理解を深めていくことによってのみ、継続的にレベルを向上させることができるからです。」そして、この粘り強いプログラマーを励ますために、Oracle は組み込みソフトウェアの開発とテストに関する 10 のヒントを彼に伝えました。

1 道具の使い方を知っている

通常、組み込みシステムには信頼性に関してより高い要件が求められます。組み込みシステムの安全性が損なわれると、壊滅的な結果を招く可能性があり、安全性以外のシステムであっても、大量生産により重大な経済的損失が発生します。これには、組み込みソフトウェアを含む組み込みシステムの厳密なテスト、検証、検証が必要です。さまざまな組み込みデバイスを制御するためにソフトウェアとマイクロプロセッサを使用する分野がますます増えており、複雑な組み込みソフトウェアを迅速かつ効率的にテストすることがますます重要になっています。

車の修理に工具が必要なように、優れたプログラマーはさまざまなソフトウェア ツールを上手に使用できる必要があります。ツールが異なれば、使用範囲や機能も異なります。これらのツールを使用すると、システムが何をしているのか、どのようなリソースを消費しているのか、どのような外部のものを処理しているのかを確認できます。あなたを数日間イライラさせている問題は、特定のツールで簡単に解決できるかもしれませんが、それはあなたがそれを知らないだけです。では、なぜこれほど多くの人が、半死半生を投げた後、いつもテストツールの使用を考えるのでしょうか?理由はたくさんありますが、主に 2 つあります。1つは恐怖、もう1つは惰性です。恐れているのは、テスト ツールやテスト モジュールをコードに追加するにはスキルが必要で、新たなバグが発生する可能性があるため、常にコードを変更して再コンパイルすることでバグを除去できることを期待したいと考えていますが、結果は役に立ちません。彼らは printf のような単純なテスト手段を使用することに慣れているため、怠惰です。一般的に使用される組み込みテスト ツールをいくつか紹介しましょう。

  1. ソースレベルデバッガ [ソースレベルデバッガ]

この種のデバッガは通常、シングルステップまたはマルチステップのデバッグ、ブレークポイントの設定、メモリ検出、変数の表示などの機能を提供し、組み込みデバッグの最も基本的かつ効果的なデバッグ方法です。例えば、VxWorks TornadoII が提供する gdb がこれに属します。

  1. シンプルで実用的な印刷物表示ツール [printf]

printf または他の同様の印刷および表示ツールは、最も柔軟で簡単なデバッグ ツールであると考えられます。コードの実行中にさまざまな変数を出力すると、コードの実行ステータスを知ることができます。ただし、printf は通常のコードの実行に多大な影響を与えるため (一般に、printf は CPU に長時間かかる)、使用には注意が必要で、印刷を制御するには print スイッチを設定することをお勧めします。

  1. ICEまたはJTAGデバッガ[インサーキットエミュレータ]

ICEはCPUコアをシミュレートするためのデバイスで、演算装置の正常な動作を妨げることなく、CPUの内部動作状態をリアルタイムに検出することができます。また、デスクトップ デバッグ ソフトウェアが提供する、複雑な条件付きブレークポイント、高度なリアルタイム トレース、パフォーマンス分析、ポート分析も提供します。ICE には通常、ボンドアウト CPU と呼ばれる比較的特殊な CPU が搭載されています。これはオープン パッケージ化された CPU であり、特殊な接続を介して CPU の内部信号にアクセスできますが、CPU がパッケージ化されているときにはこれらの信号を「見る」ことはできません。ワークステーション上の強力なデバッグ ソフトウェアと組み合わせると、ICE は最も包括的なデバッグ機能を提供します。ただし、ICE にはいくつかの欠点もあります: 高価であること、フル スピードで動作できないこと、同様に、すべての CPU を外部 CPU として使用できるわけではないこと、別の観点から見ると、これらの外部 CPU が適時に新しい CPU に置き換えられる可能性は低いです。JTAG (Joint Test Action Group) このシリアル インターフェイスは、元々は IC と回路の接続を監視するために開発されましたが、デバッグのサポートを含むように用途が拡張されました。AD Company が Blackfin 用に設計した Visual Dsp++ は、高速 JTAG デバッグをサポートします。

  1. ROMモニタ [ROMモニタ]

ROM モニタは、組み込みシステム ROM に常駐する小さなプログラムで、シリアルまたはネットワーク接続を通じてワークステーション上で実行されているデバッグ ソフトウェアと通信します。これは安価な方法であり、間違いなくローエンドのテクノロジーです。通信ポートと少量のメモリ空間以外に特別なハードウェアは必要ありません。コードのダウンロード、制御の実行、ブレークポイント、シングル ステップ、レジスタとメモリの観察、変更といった機能を提供します。ROM モニタはオペレーティング ソフトウェアの一部であるため、アプリケーションの実行中にのみ機能します。CPU とアプリケーションのステータスを確認したい場合は、アプリケーションを停止し、再度 ROM モニタに入る必要があります。

  1. データモニター [データモニター]

このようなモニタは、CPUを停止することなく指定した変数の内容を表示できるだけでなく、各変数の変化過程を収集してグラフィカルに表示することができます。

  1. OSモニター [オペレーティングシステムモニター]

オペレーティング システム モニターは、タスクの切り替え、セマフォの送受信、割り込みなどのイベントを表示できます。これらのモニターは、イベント間の関係や時間的なつながりを表示できる一方で、セマフォの優先順位の逆転、デッドロック、割り込み遅延などの問題の診断も提供します。

  1. 性能解析ツール「プロファイラー」

CPU がどこで消費されているかをテストするために使用できます。プロファイラー ツールを使用すると、システムのボトルネックがどこにあるのか、CPU 使用率、最適化が必要な場所を知ることができます。

8. メモリテストツール「Memory Teseter」

メモリ リーク、メモリの断片化、メモリ クラッシュなどのメモリ使用の問題を見つけることができます。システムに予期せぬ問題や断続的な問題があることがわかった場合は、メモリ テスト ツールを使用してテストする必要があります。

9. トラッカーを実行する [実行トレーサー]

どの関数が CPU によって実行されているか、誰が呼び出しているか、パラメータは何か、いつ呼び出されたかなどを表示できます。このツールは主に、多数のイベントの異常を検出できるコード ロジックをテストするために使用されます。

10. カバレッジツール「カバレッジテスター」

これは主に、どのコードが CPU によって具体的に実行されたかを示し、どのコード分岐が実行されていないかを知ることができます。これにより、コードの品質が向上し、デッドコードが排除されます。

11. GUIテストツール「GUI Tester」

多くの組み込みアプリケーションは何らかの形式のグラフィカル ユーザー インターフェイスと対話し、一部のシステム パフォーマンス テストはユーザー入力の応答時間に基づいています。GUI テスト ツールは、開発環境でテスト ケースを実行するためのスクリプト ツールとして使用でき、操作の記録と再生、後の分析と比較のための画面表示のキャプチャ、テスト プロセス (Rational のロボットや Mercury の Loadrunner) の設定と管理などの機能を備えています。ツールは優れた代表です)。多くの組み込みデバイスには GUI がありませんが、GUI テスト スクリプトを実行するように組み込みデバイスをインストルメント化することは多くの場合可能です。この方法では、テスト対象のコードへの変更が必要になる場合がありますが、機能テストと回帰テストの時間を節約できます。

  1. 自作ツール【自作テスター】

組み込みアプリケーションでは、特定の目的のために、特定のテスト目的を達成するためにいくつかのツールを作成する必要がある場合があります。私がかつて作成したビデオ ストリームの記録および表示ツールは、ビデオ会議データのフローと変更をテストするのに非常に役立ち、会社がいくつかの深く隠れたバグを発見するのに役立ちました。

2 記憶障害を早期に発見する

メモリの問題は非常に有害であり、トラブルシューティングが容易ではありません。メモリ リーク、メモリ フラグメント、メモリ クラッシュの 3 つの主なタイプがあります。記憶障害に対する態度は明確でなければなりません。つまり、早期発見と早期「治療」です。ソフトウェア設計では、メモリ リークが最も「有名」です。主な理由は、継続的に割り当てられたメモリを時間内に解放できず、時間の経過とともにシステムのメモリが枯渇してしまうためです。注意深いプログラミングのベテランでもメモリ リークに遭遇することがあります。メモリ リークをテストした友人は、おそらく深い経験をしているでしょう。つまり、メモリ リークは一般に深く隠されており、コードを読んで見つけるのは難しいということです。一部のメモリ リークはライブラリでも発生する可能性があります。これはライブラリ自体のバグである可能性があります。あるいは、プログラマがインターフェイスのドキュメントを正しく理解しておらず、誤用を引き起こした可能性があります。

ほとんどの場合、メモリ リークは検出されませんが、ランダムな障害として現れる場合があります。プログラマーは、この現象をハードウェアの問題のせいにする傾向があります。ユーザーのシステムの安定性がそれほど高くない場合、システムの再起動は大きな問題にはなりませんが、ユーザーのシステムの安定性が非常に高い場合、この種の障害はユーザーの製品に対する信頼を失う可能性があり、また、あなたのプロジェクトには問題があるということです。プロジェクトが失敗しました。メモリ リークは非常に有害であるため、この問題を解決するツールは数多くあります。これらのツールは、参照されていないコード ブロックや再利用されたコード ブロック、ガベージ コレクション、ライブラリ トレース、その他の手法を検出することにより、メモリ リークを検出します。各ツールには長所と短所がありますが、一般的には使用しないよりは使用した方が良いでしょう。つまり、責任ある開発者はメモリ リークをテストして、問題が発生する前に防止する必要があります。

メモリの断片化は、メモリ リークよりもさらに深く隠蔽されています。メモリの割り当てと解放が継続的に行われると、大きなメモリ ブロックが小さなメモリ ブロックに継続的に分解され、フラグメントが形成されます。時間が経つと、大きなメモリ ブロックを適用する必要がある場合に失敗する可能性があります。システム メモリが十分に大きい場合、永続時間は長くなりますが、最終的には割り当ての失敗から逃れることはできません。動的割り当てを使用するシステムでは、メモリの断片化が頻繁に発生します。現時点でこの問題を解決する最も効果的な方法は、ツールを使用してシステム内のメモリ使用量を表示することでメモリ断片化の原因を特定し、該当する部分を改善することです。

動的メモリ管理にはさまざまな問題があるため、組み込みアプリケーションでは、多くの企業が将来の問題を回避するために単純に malloc/free を無効にしています。

メモリ クラッシュはメモリ使用量の最も深刻な結果であり、主な原因は、範囲外の配列アクセス、解放されたメモリへの書き込み、ポインタ計算エラー、範囲外のスタック アドレスへのアクセスなどです。メモリ破損によるシステム障害はランダムに発生するため、発見するのが難しく、現在、トラブルシューティングのためのツールはほとんどありません。

つまり、メモリ管理ユニットを使用する場合は、誰が割り当て、誰が解放するかなど、その使用規則に注意して厳密に従う必要があります。

3 コードの最適化についての深い理解

システムの安定性に関しては、コード効率が組み込みシステムにとって非常に重要であるため、人々はリアルタイムと速度をより重視します。コードを最適化する方法を知ることは、すべての組み込みソフトウェア開発者にとって必須のスキルです。女の子が体重を減らすのと同じように、少なくともどこを最も減らす必要があるかを知っているので、減量薬や器具を購入して減量することができます。コードの最適化の前提は、本当に最適化する必要がある箇所を見つけて、コードの対応する部分を最適化するための適切な薬を処方することであることがわかります。前述のプロファイル(パフォーマンス分析ツール、一部のフル機能の IDE にはこの組み込みツールが提供されています)は、各タスクの CPU 使用率、各タスクの優先度が適切に割り当てられているかどうか、特定のデータがコピーされているかどうかなど、さまざまな状況を記録できます。 . ディスクに何回アクセスしたか、ネットワークと送受信するプログラムを呼び出したか、テストコードを閉じたかなど。

ただし、リアルタイムのシステム パフォーマンスを分析するには、プロファイル ツールだけでは十分ではありません。一方で、システムに問題が発生した後、つまり CPU が枯渇した後にプロファイル ツールを使用することがよくありますが、プロファイル ツール自体が大量の CPU を占有するため、この場合にはプロファイルが機能しない可能性があります。ハイゼンベルク効果によれば、どのテスト方法でも多かれ少なかれシステムの動作が変化します。これはプロファイラーにも当てはまります。

つまり、動作効率を向上させるための前提条件は、CPU が何をどのように実行しているかを知る必要があるということです。

4. 干し草の山から針を見つけようとしないでください

干し草の山から針を見つけるのは、デバッグの鮮やかな比喩にすぎません。

グループの人々が自分たちがデバッグしているコードをクソだと言うのをよく聞きます! それは当然です、そのコードは彼が書いたものではないし、彼にはこれを書かない限り、バグだらけのコードをクソにする十分な理由があるからです。そうしないと、いつか同じグループの他の人も彼が書いたコードをクソにするかもしれません。なぜ干し草の山に針があるのでしょうか? 誰かが針を海に落としたに違いありません、なぜ針が海に落ちたのでしょうか? 誰かが不注意だったか、ずさんだったのでしょう。それで、針が見つけにくいと文句を言っているときに、急いで針を捨ててしまったと思ったことはありますか? 同様に、中途半端なデバッグをしているときに、近道を探すために、適切なコーディング設計仕様に厳密に従っていなかったり、いくつかの仮定やアルゴリズムの正しさをテストしていなかったりする可能性があるという事実を反省する必要があると考えたことはありますか? 、存在する可能性のあるものは含まれていませんでした? 問題のあるコードにマークを付けてはどうでしょうか? 高品質のコードの書き方については、Lin Rui の『高品質 C++/C プログラミング ガイド』または『0x8 "Books" About C』を参照してください。

針を海に落としてしまった場合は、発見される前に針を刺さないように安全手袋を着用するなどの予防策を講じる必要があります。同様に、問題の原因を可能な限り明らかにして捕捉するために、より包括的なエラー追跡コードを設計できます。どのようにするかというと、各関数呼び出しの失敗を可能な限り処理し、ポインタを含む各パラメータの入出力の妥当性を可能な限りチェックし、特定のプロセスの呼び出しが多すぎるか少なすぎるかを検出します。エラー追跡により、針を落とした場所を大まかに知ることができます。

5 問題を再現して切り分ける

針を海ではなく干し草の山に落とした場合、それについて書くのは簡単です。なぜなら、少なくとも干し草の山を多くの部分に分割し、それらを 1 つずつ見つけることができるからです。独立したモジュールを含む大規模なプロジェクトの場合、多くの場合、分離手法の使用は、隠れた深刻なバグに対処する最後の方法となります。問題が断続的に発生する場合は、次回問題を再現するためにこれらの条件を使用できるように、問題の再現を試み、再現するプロセス全体を記録する必要があります。文書化された条件を使用して問題を再現できると確信できる場合は、問題の切り分けに進むことができます。切り分け方法は? #ifdef を使用して、問題に関係のないコードを閉じ、問題が再現できる程度までシステムを最小限に抑えることができます。それでも問題が見つからない場合は、「ツールボックス」を開く必要があります。ICE またはデータ モニターを使用して疑わしい変数の変更を確認したり、トレース ツールを使用してパラメータの受け渡しを含む関数呼び出しを取得したり、メモリの破損やスタック オーバーフローが発生していないかを確認したりできます。

6 前進のための後退

森の中で迷子にならないように、ハンターは木にいくつかのマークを残し、将来迷子になったときにそのマークに従って出口を見つけることができます。過去のコード変更を追跡すると、将来の問題をデバッグするのに役立ちます。ある日、最後に変更したプログラムが長時間実行された後に突然終了した場合、そのときの最初の反応は、最後の変更前は良かったのに、何を変更したのかということです。では、前回と比較してこの変更を検出するにはどうすればよいでしょうか? はい、コード管理システム SCS またはバージョン管理システム VCS (同時バージョン管理、CVS は VCS の進化版です) です。以前のバージョンをチェックインし、現在のテスト バージョンと比較します。比較ツールには、SCS/VCS/CVS に付属する diff ツール、または BeyondCompare や ExamDiff などの他のより強力な比較ツールを使用できます。それに比べて、変更されたコードをすべて記録し、問題を引き起こす可能性のある疑わしいコードをすべて分析します。

7 テストの完全性を判断する

テストがどれほど包括的であるかをどうやって知ることができますか? カバレッジ テストでこの質問に答えることができます。カバレッジ テスト ツールを使用すると、CPU が実際にどのようなコードを実行するかを知ることができます。優れたカバレッジ ツールを使用すると、通常、コードの約 20% ~ 40% が正しいが、残りにはバグが含まれている可能性があることがわかります。カバレッジツールにはさまざまなテストレベルがあり、ユーザーはニーズに応じて特定のレベルを選択できます。単体テストが包括的でデッドコードが含まれていないと確信している場合でも、カバレッジ ツールによって潜在的な問題が指摘されることがあります。次のコードを参照してください。

if (i >= 0 && (almostAlwaysZero == 0 || (last = i)))

mostAlwaysZero がゼロ以外の場合、last=i の割り当てはスキップされますが、これは期待どおりではない可能性があります。このような問題は、カバレッジツールの条件テスト機能を利用することで簡単に発見できます。

つまり、カバレッジ テストはコードの品質を向上させるのに非常に役立ちます。

8 コードの品質を向上させ、時間を節約する

調査によると、ソフトウェア開発時間の 80% 以上が次の側面に費やされています。

  • 独自のコードをデバッグする (単体テスト)

  • 自分自身と他の関連コードをデバッグする (モジュール間テスト)

  • システム全体をテストする(システムテスト)

さらに悪いことに、最初は簡単に見つかるかもしれないバグを見つけるのに、10 ~ 200 倍の時間を費やす必要があるかもしれないということです。小さなバグが多大な損害をもたらす可能性があり、たとえそのバグがシステム全体のパフォーマンスに大きな影響を与えなかったとしても、目に見える部分に影響を与える可能性があります。したがって、デバッグ用のコードを短縮するために、コードの品質を高めるための優れたコーディングおよびテスト方法を開発する必要があります。

9 発見、分析、修正

この世に万能薬はありません。どんなに強力なプロファイルでも無力であること、どんなに優れたメモリモニターであっても見つからないことがある、どんなに使いやすいオーバーレイツールでも上書きできない場所があること。深く隠れた問題の中には、あらゆるツールを駆使しても根本原因を突き止めることができない場合もありますが、その際にできることは、その問題の外部現象や何らかのデータ出力から規則性や異常性を見つけることです。異常が見つかったら、それを深く理解し、解決されるまでその根本原因を追跡することが重要です。

10 初心者の考え方を活用する

ある人はこう言いました。「初心者の頭の中では、さまざまな状況が考えられるものもありますが、専門家の頭の中では、それらは非常に単一である可能性があります。」「専門家の考え」のせいで、単純な問題が非常に複雑であると考えられたり、単純なシステムがそれほど複雑になるように設計されていないことがあります。問題に困ったときは、コンピューターの電源を切り、散歩に出かけ、友達や子犬にその問題について話してみると、予期せぬインスピレーションを与えてくれるかもしれません。

概要: 組み込みデバッグも芸術です。他の芸術と同様、成功したいのであれば、知性、経験、ツールの使い方の知識が必要です。Oracle の 10 の秘密をしっかり理解できれば、組み込みテストは成功できると思います。

最後に: 以下の完全なソフトウェア テスト ビデオ学習チュートリアルが整理されてアップロードされており、必要な場合は友人が無料で入手できます。【保证100%免费】

ここに画像の説明を挿入

 これらの資料は、[ソフトウェア テスト] の友人にとって、最も包括的かつ完全な準備倉庫となるはずです。この倉庫は、最も困難な旅を乗り越える何万人ものテスト エンジニアにも同行してきました。そして、あなたにも役立つことを願っています。

おすすめ

転載: blog.csdn.net/m0_75277660/article/details/130589351