単体テストが嫌われる理由と愛を取り戻す方法

(この記事は、開発元Parasoft社 Blog 「Why People Hate Unit Testing and How To Bring Back the Love」2017年9月22日の翻訳記事です。)

率直に認めましょう。単体テストが好きな人はいません。私はカンファレンスで話しかけてくださる方たちから、どれだけ単体テストを憎んでいるかという話をさんざんお聞きしてきました。たしかに単体テストを苦にしない人もいますが、私たちの大多数にとっては、単体テストとは、どれほど巧みに不満を訴えたところで、かならずしなければならない苦行でしかありません。今日は、単体テストが嫌われる理由のいくつか、そしてソフトウェア自動化でそれらの障害を乗り越える方法を見ていきたいと思います。


 

結局のところ、なぜ単体テストを行うのか?

ほとんどの開発チームは、単体テストが好きではないものの、実際には価値があることに同意するでしょう。単体テストは、開発者が開発中のコードを真に理解するのを助け、また右の図に示すように、継続的なテストピラミッドの堅固な基盤を提供することで、チームがアジャイル開発を加速し、欠陥がパイプラインの後の段階に紛れ込むリスクを軽減できるようにします。

私はさらに踏み込んで、単体テストを作成するプロセスは、開発者が異なるレンズを通してコードを見るのに役立ち、実質的にコードレビューを重ねて行うのと同じであり、それ自体が有益なアクティビティであると主張したいと思います。

単体テストでは、外部の視点から機能のインタフェースを見直すことになります。そのとき、 「このコードはどのように使用されるか?」 (インターフェイスの簡略化と保守コストの低減に役立つ疑問)、 あるいは 「不正なデータを受け取ったらどうなるか?」 (より堅牢で再利用性の高いコードにつながる疑問) といった疑問に答えることが役に立つでしょう。

単体テストの試みが挫折する原因

一般的に、開発チームは最小限のテストしか行わないか、単体テストを完全に省いてしまう傾向があります。その理由は、(1)より多くの機能を提供しなければならないというプレッシャーがある(そしてそれに時間を取られる)、および(2)意義のある単体テストを作成するのは複雑かつ時間のかかる作業であること、が入り混じっています。

これをより細かく分類すると、中核となる開発プラクティスとして単体テストを採用するのを妨げる原因として、よく開発者が挙げる以下のような理由になります。

  • テスト対象ユニットの依存関係を理解、初期化、および/または分離するのが困難である。
  • 検証するべき対象を決定し、適切なアサーションを定義することは時間がかかり、高度な「あて推量」を必要とすることがある。
  • 多量の手動でのコーディングを伴う。特定の機能や拡張を実装するのに必要なコーディング量よりも多くの作業が必要な場合も少なくない。
  • 単純に、面白い作業ではない…開発者は自分がテスターになったよう感じるのが好きではなく、より多くの機能を提供することに時間を費やしたい。

このような制限への対処を助けるために、単体テストに役立つ既存のツールを利用することができます。単体テストおよびアサーションフレームワークは、標準化された実行フォーマット(Junitなど)を提供し、CIインフラストラクチャ(Jenkins、Bamboo、TeamCityなど)とのシームレスな統合を可能にします。IDE(Eclipse、IntelliJなど)はテストコードの作成に役立ちます。Mockingフレームワーク(Mockito、PowerMockなど)は、コードを依存関係から分離します。コードカバレッジツール(例えば、Emma、Cobertura、Clover)は、実行されたコードに対する可視性を提供します。デバッガーを使用すると、開発者は個々のテストの実行をステップごとに監視および検査できます。

しかし、残念なことに、これらのツールにはすべて制約があり、開発者は依然として次のようにさまざまな短所に悩まされています。

  • IDEは単体テスト用のスケルトンを作成するのに役立ちますが、「中身」は作成しません。開発者は実際的なテストを作成するために多くのコードを追加する必要があります。
  • アサーションは手動で定義する必要があり、正しい値がアサーションされているかどうかを確認するためにテストを実行する必要があります。
  • モックフレームワークでは、インスタンス化と構成を行うのに膨大な手作業によるコーディングと、それらを正しく使用する方法の知識が必要です。
  • カバレッジツールは、実行されたテストでカバーしたコードを明らかにしますが、テストの実行時の動作を明らかにすることはできません。
    デバッガーは個々のテストには使用できますが、テスト実行全体を監視する方法としては使えません。

要約すると、単体テストを作成する際、テストにビジネスロジックを追加する前に、時間がかかり、非常に退屈でもある手作業が必要です。

ソリューション?アシスタントを作りました!

これらの問題点の回避に役立つツールを作り上げるため、Parasoftは(当然ながら)ソフトウェアテストの自動化に取り組みました。Parasoft Jtestの単体テストアシスタントは、ワンクリックでフル機能の単体テストを作成するのに役立ちます。

UTAで作成されたテストは通常のJUnitテストですが、すべての面倒な作業が完了しています。UTAは、テストフレームワークを設定し、オブジェクトをインスタンス化し、テスト対象メソッドによって使用される適切なオブジェクトとメソッド呼び出しのモックを設定します。

これらのJUnitテストは、既存のテストと同じように標準のCIワークフローの一部として実行できます。ただし、既存のテストを含め、UTAでJUnitを実行すると、テストが監視され、コードカバレッジだけでなく、その他の分析も提供されます。

実行時にテストを分析することで、UTAは推奨事項を提示できます。多くの場合、ワンクリックで対応するための即時修正があります。

  • 変更されたため、アサートする必要があるオブジェクト値を強調表示
  • テスト対象コードの分離を推進するためにモックすべきメソッド呼び出しを特定
  • 実行後に「クリーンアップ」を実行せず、不安定なテスト環境(スレッド、外部ファイル、静的フィールドまたはシステムプロパティの使用など)の原因になっているテストを発見

Parasoftは単体テストの負担を軽減するためにUTAを開発しました。それは、ソフトウェアの品質向上を専門とする企業として、単体テストが安全で、セキュアで、信頼性が高く、高品質のソフトウェアを作成するために不可欠なステップだと知っているからです。今後カンファレンスやイベントでお会いしたときは、どれほど単体テストを憎んでいるかではなく、UTAのおかげで単体テストへの愛を取り戻したという経験をお話しいただけるよう願っています。

 

Parasoft Jtestについて

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

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

Top