視覚化ソフトウェアにとって意味のあるテストを作成するにはどうすればよいですか?


8

特定の種類のファイルを取得して視覚化したり、プロットされた画像を操作するためのボタンのホストを作成したりする、かなり大きなソフトウェアがあります。週に一度は機能しないバグ/コードの断片を見つけているように感じますが、このソフトウェアのテストを作成する方法を理解するのに苦労していますか?

ライブラリやAPIなどのプロジェクトにとってテストがどのように重要であるかを理解しています。これらの関数を使用するテストを作成するだけです。

しかし、視覚化ソフトウェアはどうですか?関連する視覚要素のため、別のアプローチが必要なようです。

データで使用できるすべての操作を実行して手動で呼び出すテストプログラムまたはテストハーネスを作成する必要がありますか?

バグを修正したことを検証し、コードが再度壊れた場合に警告するために、テストの作成を開始するにはどのアプローチを使用すればよいですか?


ユニットテストをいつ行うべきに関して、関連するが重複していない質問があります。私はバグを発見しているので、ソフトウェアが再び後退するのを防ぐためのテストを作成したいと思います。

回答:


8

このようなソフトウェアのテストを簡単にするためにできることがいくつかあります。最初に、視覚的ではないレイヤーにできるだけ抽象化してください。これにより、それらの下位層で標準の単体テストを作成できます。たとえば、特定の計算を実行するボタンがある場合は、通常の関数呼び出しを使用した単体テストでその計算を実行する方法があることを確認してください。

グラフィックスが多いプログラムをテストするための他の提案は、テスターが手動で簡単に確認できる出力を作成することです。Minecraftの例は次のとおりです。

minecraftテスト出力

また、画面に何かをレンダリングする一連のテストがあり、テスターが説明と一致することを手動で確認するように要求するプロジェクトにも取り組みました。これにより、後でテストケースを忘れないようにできます。

最初にテストを念頭に置いて設計していない場合、テストは非常に困難なことがよくあります。最も脆弱なコードを最初にテストすることに取り組みます。バグを見つけたら、それが再び発生した場合にそのバグをキャッチするテストを作成します。それはしばしば、あなたがそれに向かっている間に関連するテストを書くことを促します。


2
+1とテストデータが静的なビジュアルをレンダリングする場合は、最初に手動で結果を確認し、その後、スクリーンショットを保存してプログラムによる比較を行います
Steven A. Lowe

6

すべてにインターフェースがあります。テスト用の帽子をかぶるとき、私は特定の世界観を使ってテストを書きます。

  • 何かが存在する場合、それを測定することができます。
  • 測定できない場合は問題ありません。それが重要なのなら、私はまだそれを測定する方法を見つけていません。
  • 要件は測定可能なプロパティを規定しているか、またはそれらは役に立たない。
  • システムは、予期しない状態から、要件によって規定されている期待される状態に移行するときに、要件を満たします。
  • システムは、サブシステムである可能性のある相互作用するコンポーネントで構成されます。すべてのコンポーネントが正しく、コンポーネント間の相互作用が正しい場合、システムは正しいです。

あなたの場合、あなたのシステムには3つの主要な部分があります:

  • ファイルから初期化できるある種のデータまたは画像
  • データを表示するメカニズム
  • データを変更するメカニズム

ちなみに、これは元のModel-View-Controllerアーキテクチャとよく似ています。理想的には、これらの3つの要素は疎結合を示します。つまり、明確に定義された(したがって十分にテスト可能な)インターフェイスを使用して、これらの要素間に明確な境界を定義します。

ソフトウェアとの複雑な相互作用は、テストするシステムの要素の観点から表現できる小さなステップに変換できます。例えば:

データを含むファイルをロードします。グラフを表示します。UIでスライダーをドラッグすると、グラフがぐらつきます。

これは手動で簡単にテストでき、自動でテストするのは難しいようです。しかし、その話を私たちのシステムに翻訳しましょう:

  • UIはファイルを開くメカニズムを提供します。コントローラーは正しいです。
  • ファイルを開くと、コントローラーはモデルに適切なコマンドを発行します。コントローラーとモデルの相互作用は正しいです。
  • テストファイルが与えられると、モデルはこれを予想されるデータ構造に解析します。モデルは正しいです。
  • テストデータ構造が与えられると、ビューは予想される出力をレンダリングします。ビューは正しいです。一部のテストデータ構造は通常のグラフになりますが、他のグラフはぐらつきのあるグラフになります。
  • インタラクションビューモデルが正しい
  • UIには、グラフをぐらつくためのスライダーがあります。コントローラーは正しいです。
  • スライダーを特定の値に設定すると、コントローラーは予想されるコマンドをモデルに発行します。コントローラーとモデルの相互作用は正しいです。
  • ぐらつきに関するテストコマンドを受け取ると、モデルはテストデータ構造を期待される結果データ構造に変換します。

コンポーネントごとにグループ化すると、テストする次のプロパティが作成されます。

  • モデル:
    • ファイルを解析します
    • ファイルを開くコマンドに応答する
    • データへのアクセスを提供します
    • make-wobblyコマンドに応答します
  • 見る:
    • データをレンダリングする
  • コントローラ:
    • ファイルを開くワークフローを提供します
    • ファイルを開くコマンドを発行する
    • ぐらつくワークフローを提供します
    • make-wobblyコマンドの発行
  • システム全体:
    • コンポーネント間の接続は正しいです。

テストの問題を小さなサブテストに分解しないと、テストは非常に困難になり、非常に脆弱になります。上記のストーリーは、「特定のファイルをロードしてスライダーを特定の値に設定すると、特定の画像がレンダリングされる」として実装することもできます。これは、システム内の要素が変更されると壊れるため、壊れやすいものです。

  • ぐらつきのコントロールを変更すると壊れます(たとえば、コントロールパネルのスライダーではなく、グラフのハンドル)。
  • 出力フォーマットを変更すると壊れます(たとえば、グラフのデフォルトの色を変更したため、またはグラフをより滑らかに見せるためにアンチエイリアスを追加したため、レンダリングされたビットマップが異なります。どちらの場合でも注意してください)。

詳細なテストには、機能を壊すことを恐れずにシステムを進化させることができるという非常に大きな利点もあります。必要なすべての動作は完全なテストスイートによって測定されるため、何かが壊れた場合、テストによって通知されます。細かいので、問題のある領域を指摘します。たとえば、コンポーネントのインターフェイスを誤って変更した場合、そのインターフェイスのテストのみが失敗し、そのインターフェイスを間接的に使用する他のテストは失敗しません。

テストが簡単だと思われる場合は、適切な設計が必要です。たとえば、システム内のコンポーネントをハードワイヤードすると問題が発生します。コンポーネントとシステム内の他のコンポーネントとの相互作用をテストする場合、それらの他のコンポーネントをログに記録して確認できるテストスタブに置き換える必要があります。その相互作用を振り付けます。つまり、依存性注入メカニズムが必要であり、静的な依存関係は回避する必要があります。UIをテストする場合、このUIがスクリプト可能であると非常に役立ちます。


もちろん、そのほとんどは、すべてが切り離されて簡単にテスト可能で、飛んでいるユニコーンが愛と平和を広める理想的な世界の幻想にすぎません;-)根本的にテスト可能であるものはありますが、そうすることは非常に難しいことが多く、あなたの時間の使い方。ただし、システムはテストしやすいように設計できます。通常、テストに依存しないシステムでも、テストできる内部APIまたはコントラクトを備えています(そうでない場合は、アーキテクチャがおかしくて、大きな泥の玉を書いたと思います)。私の経験では、少量の(自動化された)テストでも、品質の顕著な向上に影響します。


2

予想されるイメージを生成する既知のファイルから始めます。すべてのピクセルを確認してください。それぞれに、既知の手作りのテストファイルの期待値が必要です。予想される出力イメージと比較してください。「オフ」になっているものはすべて、コードのバグを示します。

テストファイルを拡張して、出力イメージが変更され、ソフトウェアのすべての機能にヒットするようにします。

スクリプトは、この種のブラックボックステストに便利です。既知の入力と予想される出力に対してソフトウェアの最新ビルドを実行する単純なスクリプト。

一方、ユニットテストは、ソフトウェアの最小のチャンク(通常は関数など)を使用して、期待どおりに動作するかどうかを確認するホワイトボックステストである必要があります。どのピクセルカラーが返されるかなどがわかります。この場合、コードはライブラリのように動作し、コードの他のすべてのセクションへのAPIが提供されます。

すべてが1つの.cファイルに組み込まれmain()、すべての機能がに押し込まれている場合は、テスト方法よりも大きな問題が発生しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.