ノイズの多い単体テストスイートに対処する

(この記事は、開発元Parasoft社 Blog 「Handling Noisy Unit Test Suites2017年7月21日の翻訳記事です。)

ソフトウェア開発者が単体テストに不平を言う理由は数多くありますが、その最たるものは、ノイズの多いテストスイートへの対処です。そして、コードが長く存在しているほど、ノイズも増えます。ところで、ここで言う「ノイズ」とは、常に失敗するが、とりあえず大丈夫だとわかっている (と考えている) ため、ただ放っておかれるようなテストを意味します。または、時には失敗し、時にはうまくいくが、誰もそれを調べたり修正したりする手間をかけないテストです。それから、コードが変更され、テストを更新する必要があるため、正当に失敗したテストがあります。これらのノイズはすべて私たちの注意を求めて叫んでいますが、ここでジレンマとなるのは、ノイズが多くなればなるほど、有効な対処はされにくいということです。

ここで問題です。この「失敗したけれどOK」なテストのノイズのどこかに、あなたが知りたがっている本物の問題がいくつかあります。これをスペルチェッカーを使用しようとするようなものだと考えてください。ツールをきちんと調整していないなら、実際はスペルの問題ではない、特殊な業界用語や名前など、目当てではないありとあらゆる指摘がレポートされます。しかし、その混乱のどこかに隠れているのは、あなたが実際に犯した恥ずかしい間違い、見つけ出したい間抜けなスペルミスです。そしてもちろん、世界中にスペルの誤りは山ほどあります-しかし、ソフトウェアとは違って、伴うリスクはそれほど多くなく、せいぜい少し恥ずかしい思いをする程度です。

ともかく、単体テストスイートは一般にこれと 同じ状態にあります。不幸なことに、いつも表示され、無視するのに慣れてしまったノイズの多い結果によって、把握したい本当の結果が隠されてしまっています。多くの組織では、これを解決するために、ときおり(数か月に1回から、ときには数年に1回まで)誰かがテストスイートをクリーンアップするためのスプリントをスケジュールします。スイートを人手で可能な限りクリーンなものにするために多大な時間が費やされますが、必ず問題は戻ってきます-それも思ったよりもすぐに。こうして負のフィードバックループが形成されます。次回にまたノイズが出ると思えば、誰もテストをきれいにしたくはなりません。

解決策は、より機能的なアプローチを取ること、つまり、面倒で無駄なクリーンアップスプリントを除去し、最初からノイズの多いテストスイートを避けられるアプローチを採用することです。

ノイズの多いテストスイートの最小化

そのためには、単体テストの失敗が何を意味するかを理解するのが重要です。まとめれば3つの理由があり、それぞれ明快な解決策があります。

  1. コードが壊れている。の場合、コードを修正します(理想的には、クリーンなテストスイートはこのような失敗だけをレポートします)。
  2. コードが適切に変更され、テストが壊れた。の場合、新しいコードと一致するようにテストを修正します(コードを変更している場合は、これが理由だと考えられます。コードを変更するときはテストも変更するべき有力な理由の1つです)。
  3. テストが間違っており、コードは問題ない。 この場合、テストを修正します(または、テストを削除することもできます。ただし、重要な点は- テストを無視しないことです)。

さて。あなたは考えているかもしれません- もし私のテストケースが大量に第3のカテゴリに当てはまっていたら?いったいどうしろというのか?では、もっと詳しく説明しましょう。

ノイズの理由は、通常、いくつかの基本的な問題に還元されます。すなわち、不適切なテスト、脆弱なテスト、または貧弱なアサーションです。不適切なテストは、適切に仕事をしていないテストです。必要以上にテストしているか、外部条件に基づいて変更されるか、または一貫性のないデータに依存しています。

ノイズを最小限に抑えるには、問題となっているテスト(または、できればすべてのテスト)を確認するために、次の2つの簡単な質問に答えてください。

  1. テストが合格する場合、何を意味するか?
  2. テストが失敗する場合、何を意味するか?

両方の質問に合理的に答えられないテストは、改善が必要です。

脆弱なテストの改善

脆弱なテストとは、簡単に壊れるテストです。これは、しばしば不精なアサーションの症状でもあります。何かをチェックできるからというだけでチェックしているのは、チェックするべきであることを意味しません。各アサーションは、テスト対象のコードが実現する要件に関して、実際的な意味を持つ必要があります。テストが壊れる原因としてよくあるものは、日付/時間に左右されるアサーション、OSへの依存、ファイル名/パスへの依存、サードパーティのソフトウェア、パートナーAPIなどです。適切なテストを行うために、最小限に必要なものだけアサーションを行っていることを確認してください。また、テストに必要なものはすべてソース管理とビルドシステムに含まれていることを確認してください。

その他の不適切なアサーションとは、常に失敗した状態にあるが、リリース時に問題にされないもの(「あ、それなら大丈夫、気にしなくていいよ」)、または絶えず状態が変化するもの(「前は大丈夫だったけど、昨日は失敗して、でも今日は大丈夫です!! 」)です 。コードが流動的である場合は、短期的には結果が常に変化していても問題ではないかもしれませんが、長期的には許容されるべきではありません。なぜテストの結果が毎回違うのか、あるいは、なぜテストが失敗しているのにリリースしても構わないと考えられるのかを理解する必要があります。アサーションを含めた単体テストを対象としたピアレビューを行うことは、この問題を永続的に解決するうえで大いに役立ちます(ピアレビューのその他の利点?テストが監視の一環として義務付けられているコンプライアンス環境にいれば、生き残るのがだいぶ楽になります)。

壊れたテストを評価することは、クリーンアップをはかどらせるには実によい方法です。何ヶ月、あるいは何年も失敗し続けているテストをじっくり見るようおすすめしたいと思います。それらのテストが本当に価値を追加しているかどうか自問してください。考えてもみてください、どのみち結果を無視しているのです。それなら、正直なところ、何の役に立つというのでしょう? 無視しているテストを削除することで、重要なテストに集中して、実際に全体の品質を向上させることができます。

すると、ものごとがかなりシンプルになります(たとえ最初は時間がかかったとしても)。クリーンアップを行うには、以下のベストプラクティスに従ってください。

  • 定期的にテストを実行し、テストが期限切れにならないようにする。コードと一緒に変更すること。
  • 常に失敗するテストを削除するか、修正する。
  • 常に状態が変わる(合格/不合格)テストを削除するか、あるいは整理する。
  • 単体テストのピアレビューを行う。

そしてもちろん、単純作業を自動化することを忘れないでください。テストを書く時間がより生産的になり、ノイズの少ないテストを作成するのに役立ちます。

テスト自動化の使用

自動化されたソフトウェアテストを利用することで、単体テスト作業のわずらわしさを軽減できます。自動化された仕組みに単純で退屈な部分(コンピュータが得意な作業)をさせることができれば、本当に人間の知性を必要とすること(あなたが得意な作業)を行う余裕ができます。たとえば、xUnitテストケースの初期コード(非常に作成が面倒な単純なコード)は、作成を自動化します。ツールにゲッター/セッターテストメソッドを自動生成させると、他のより有意義なことに時間を使用できます。

テストの自動化によって、洗練された方法を実現したら、スタブやモックの作成や設定など、単体テストのより厄介な作業にもツールを利用できます。自動化の利点を活用するほど、単体テストに時間がかからなくなります-と同時に、単体テストの単調さも軽減されます。javaを使用している場合は、 Parasoft Jtestに統合された新しい単体テストアシスタントをご覧ください。単体テストアシスタントは、上記で述べたすべてに加えて、より多くの処理を行い、単体テストを容易にするだけでなく、楽しいものにします。

 

Parasoft Jtestについて

Java対応静的解析・単体テストツール Parasoft Jtest

Jtestは、テスト工数の大幅削減とセキュアで高品質なJavaシステムの開発を強力にサポートするJava対応テストツールです。1,000個以上のコーディング規約をもとにソースコードを静的に解析し、プログラムの問題点や処理フローに潜む検出困難なエラーを検出します。さらに、JUnitを用いた単体テストについて、作成、実行、テストカバレッジ分析、テスト資産の管理といった単体テストに係る作業をサポートし、単体テストの効率化を促進します。

Top