コード内の計算は十分にテストされていますが、GUIコードが多すぎるため、全体的なコードカバレッジは希望よりも低くなっています。ユニットテストのGUIコードに関するガイドラインはありますか?それは理にかなっていますか?
たとえば、私のアプリにはグラフがあります。グラフのテストを自動化する方法を理解できませんでした。グラフが正しいかどうかを確認するには、人間の目であるAFAIKが必要です。
(私はJava Swingを使用しています)
コード内の計算は十分にテストされていますが、GUIコードが多すぎるため、全体的なコードカバレッジは希望よりも低くなっています。ユニットテストのGUIコードに関するガイドラインはありますか?それは理にかなっていますか?
たとえば、私のアプリにはグラフがあります。グラフのテストを自動化する方法を理解できませんでした。グラフが正しいかどうかを確認するには、人間の目であるAFAIKが必要です。
(私はJava Swingを使用しています)
回答:
MVPやMVCなどのデザインは、通常、実際のGUIからできるだけ多くのロジックを抽象化しようとします。これについて非常に人気のある記事の1つは、Michael Feathersによる「The Humble Dialog Box」です。個人的には、UIからロジックを移動しようとすることについて、さまざまな経験をしました。でも、私の専門分野からは少し外れています。
もちろん、答えはMVCを使用して、できるだけ多くのロジックをGUIから移動することです。
そうは言っても、SGIがOpenGLを新しいハードウェアに移植するときに、一連のプリミティブを画面に描画し、フレームバッファーのMD5合計を計算する一連の単体テストがあったと同僚から聞いたことがあります。次に、この値を既知の適切なハッシュ値と比較して、APIがピクセル単位で正確かどうかをすばやく判断できます。
WebベースのUIのテストを自動化するSelenium RCがあります。アクションを記録して再生します。UIとのやり取りを確認する必要があるため、カバレッジには役立ちませんが、自動ビルドに使用できます。
CucumberとSwingerを使用して、Swing GUIアプリケーションの機能的な受け入れテストをプレーンな英語で記述してみてください。Swingerは、内部でNetbeansのJemmyライブラリを使用してアプリを駆動しています。
Cucumberでは、次のようなテストを記述できます。
Scenario: Dialog manipulation
Given the frame "SwingSet" is visible
When I click the menu "File/About"
Then I should see the dialog "About Swing!"
When I click the button "OK"
Then I should not see the dialog "About Swing!"
このSwingerビデオデモを見て、実際の動作を確認してください。
ここにいくつかのヒントがあります:
GUI(コントローラーとモデルオブジェクトを持っている)からできる限り多くのコードを削除して、GUIなしでそれらをテストできるようにします。
グラフィックについては、グラフィックを生成するコードに提供する値をテストする必要があります。
テストは芸術形式です。ロジックをできる限りGUIから削除する必要があることに同意します。その後、単体テストに集中できます。他のように、テストはリスクを減らすことです。常にすべてをテストする必要はありませんが、多くの場合、さまざまな領域でさまざまなテストを分割することが最善の方法です。
もう1つの質問は、UIレイヤーで実際に何をテストしようとしているのかということです。UIテストは、通常、作成、維持に時間がかかり、最も壊れやすいため、最も費用のかかるテストです。線を描く前に座標が正しいことを確認するためにロジックをテストする場合、具体的に何をテストしていますか?テストしたい場合は赤い線でグラフが描かれます。所定の座標を設定して、特定のピクセルが赤か赤かをテストできますか?上記のビットマップ比較が機能するように、Seleniumは私の主な焦点はGUIの過剰テストではなく、UIの作成に役立つロジックをテストし、UIのどの部分が壊れているか、疑わしい部分に焦点を当て、少数のテストに焦点を当てることですそこ。
JFCUnitを使用してGUIをテストできますが、グラフィックスの方が難しい場合があります。GUIのスナップショットを数回撮り、それを自動的に以前のバージョンと比較しました。これは実際のテストを提供するものではありませんが、自動ビルドが予期した出力を生成できない場合は警告を出します。
私があなたの質問から集めたのは、GUIの動作を詳細にテストする自動化された方法を探しているということです。あなたが与える例は、曲線が実際に正しく描かれているかどうかをテストすることです。
ユニットテストフレームワークは自動テストを実行する方法を提供しますが、実行するテストの種類は、多数のクラスの正しい動作を検証する複雑な統合テストであると思います。テストしたくないはずです。
オプションは、使用するプラットフォーム/ツールキット/フレームワークに大きく依存します。たとえば、GUIフレームワークとしてQtを使用するアプリケーションは、Squishを使用してテストを自動化できます。テストの結果を1回検証し、その後自動的に実行されるテストで、結果を検証済みの結果と比較します。
GUIテストへの私のアプローチは、業界のコンセンサスと同様に進化しています。しかし、いくつかの重要な技術が出現し始めていると思います。
状況に応じて、これらの手法を1つ以上使用します(たとえば、GUIの種類、構築に必要な速さ、エンドユーザーは誰かなど)。
手動テスト。コードの作業中は常にGUIを実行し、コードと同期していることを確認します。作業する部分を手動でテストして再テストし、コードと実行中のアプリケーションを切り替えます。重要な作業を完了するたびに、アプリケーションの画面全体または領域に全体的なテストを行い、リグレッションがないことを確認します。
ユニットテスト。関数またはGUI動作の小さな単位のテストを記述します。たとえば、グラフで「基本」色に基づいて色のさまざまな色合いを計算する必要がある場合があります。この計算を関数に抽出して、単体テストを作成できます。GUIでこのようなロジック(特に再利用可能なロジック)を検索し、それを個別の関数に抽出して、ユニットテストをより簡単に行うことができます。この方法で複雑な動作を抽出してテストすることもできます。たとえば、ウィザードの一連のステップを関数に抽出し、ユニットテストで入力を指定すると、正しいステップが返されることを確認できます。
コンポーネントエクスプローラ。GUIを構成する再利用可能な各コンポーネントを紹介することだけが役割の「エクスプローラ」画面を作成します。この画面では、すべてのコンポーネントが適切なルックアンドフィールであることを視覚的にすばやく簡単に確認できます。コンポーネントエクスプローラーは、手動でアプリケーション全体を実行するよりも効率的です。A)各コンポーネントを1回だけ確認する必要があり、B)コンポーネントを表示するためにアプリケーションの詳細に移動する必要がないため、すぐに確認してください。
自動化テスト。画面またはコンポーネントと対話して、マウスクリックやデータ入力などをシミュレートするテストを作成し、これらの操作が与えられてもアプリケーションが正しく機能することを表明します。これは、他のテストで見逃す可能性のある潜在的なバグをキャプチャするための追加のバックアップテストとして役立ちます。私は、GUIの最も壊れやすい部分や非常に重要な部分の自動テストを予約する傾向があります。何かが壊れた場合、できるだけ早く知りたいパーツ。これには、破損したり重要なメイン画面に対して脆弱な非常に複雑なインタラクティブコンポーネントが含まれる可能性があります。
差分/スナップショットテスト。スクリーンショットまたはHTMLコードとして出力をキャプチャし、前の出力と比較するテストを記述します。これにより、出力が変化するたびに警告が表示されます。差分テストは、GUIの視覚的側面が複雑な場合や変更される可能性がある場合に役立ちます。その場合、特定の変更がGUI全体に与える影響について迅速かつ視覚的なフィードバックが必要です。
可能な限りあらゆる種類のテストを強引に使用するのではなく、自分が取り組んでいる種類のテストに基づいてテスト手法を選択することを好みます。したがって、単純な関数を抽出して単体テストを行う場合もあれば、コンポーネントをコンポーネントエクスプローラーなどに追加する場合もあります。状況によって異なります。
コードカバレッジが非常に有用なメトリックであるとは思いませんでしたが、他の人がその使用法を見つけた可能性があります。
最初の測定はバグの数と重大度だと思います。あなたの最優先事項はおそらく正しく機能するアプリケーションを持っていることです。アプリケーションが正しく機能していれば、バグはほとんどないか、まったくないはずです。多くのまたは重大なバグがある場合は、おそらくテストしていないか、テストが効果的ではありません。
バグを減らす以外にも、パフォーマンス、使いやすさ、アクセシビリティ、保守性、拡張性などの手段があります。これらは、構築しているアプリケーションの種類、ビジネス、エンドユーザーなどによって異なります。
これはすべて、私の個人的な経験と研究、およびHam VockeによるUIテストに関するすばらしい記事に基づいています。
私が知っていることから、これは非常に複雑であり、実際には言語に依存します-多くの言語には独自のGUIテスト方法がありますが、(モデル/ GUIの相互作用ではなく)GUIを実際にテストする必要がある場合は、ユーザーが実際にクリックするボタンをシミュレートします。たとえば、Eclipseで使用されるSWTフレームワークはSWTBotを提供し、JFCUnitはすでに言及されています。MozillaはこれをXULでシミュレートする独自の方法を持っています(そして私が彼らのブログで読んだものから、これらのテストは非常に壊れやすいようです)。
場合によっては、スクリーンショットを撮り、ピクセルパーフェクトレンダリングをテストする必要があります(Mozillaは正しくレンダリングされたページをチェックするためにこれを行うと思います)。これには長い設定が必要ですが、グラフに必要な場合があります。こうすることで、コードを更新してテストブレークを行うときに、障害が実際に発生しているかどうかを手動で確認するか、グラフレンダリングコードを改善してきれいなグラフを生成し、スクリーンショットを更新する必要があります。
Swingを使用している場合、FEST-SwingはGUIの駆動とアサーションのテストに役立ちます。「ボタンAをクリックするとダイアログBが表示される」または「ドロップダウンからオプション2を選択すると、すべてのチェックボックスの選択が解除される」などのテストは非常に簡単になります。
あなたが言及するグラフのシナリオは、テストするのがそれほど簡単ではありません。GUIコンポーネントを作成して表示する(そしておそらくFESTで駆動する)だけで、GUIコンポーネントのコードカバレッジを取得するのは非常に簡単です。ただし、意味のあるアサーションを作成することは難しい部分です(意味のあるアサーションのないコードカバレッジは自己欺瞞の練習です)。グラフが逆さまに描かれていない、または小さすぎないことをどのようにテストしますか?
GUIのいくつかの側面は自動化された単体テストでは効果的にテストできないこと、そして他の方法でそれらをテストする必要があることを受け入れる必要があると思います。
GUIライブラリをテストするのはあなたの仕事ではありません。そのため、実際に画面に何が描画されているかをチェックし、代わりにウィジェットのプロパティをチェックする責任をかわすことができます。ライブラリは、何が描画されているかを正確に表していると信頼できます。