ユニットテストとはどういう意味ですか?

技術的な観点から見ると、ユニットテストは、(1)テストクラス、(2)特定のクラスにラップされたテストメソッドのセット、および(3)検証できるメソッドのセットに基づいた、非常にシンプルなツールです。テストクラスの状態が何らかの値に対応する(または対応しない)こと。



これは非常に単純な仕掛けであり、開発プロセス全体に劇的な影響を与える可能性があります。 一方では、TDD(「テストファーストアプローチ」)があり、コーディングプロセスだけでなく、設計プロセス(つまり、システム設計)も「駆動」します。ユニットテストはユーザーに価値をもたらさないため、時間の無駄です。





私は個人的にテストファーストのアプローチは日常の活動に適用するほど便利ではありませんが、私は開発者の最初のカテゴリーを尊重し理解しています。 私は鉛筆を手に持ってサブシステムの設計を考えるのに慣れていて、テストを追加して初めて新しいメソッドを追加するのは面倒です。 しかし、ここでは、実際には、ユニットテストを作成することを好むのではなく、これらのテストが私にとって意味するものです。



単体テストについて一般に受け入れられている意見は、まず第一に、コードの品質を改善することを目的としているという事実に基づいています。 別の便利な機能は、テストにより元の動作が変更されていないことを確認するため、コードを簡単にリファクタリングできることです。



これらの議論を議論することは困難ですが、これらは単体テストの唯一の(そして私の観点からは、メインからはほど遠い)利点からはほど遠いものです。



私にとって、ユニットテストはまず第一に、優れたデザインの「リトマステスト」です。 優れた設計には、接続性の悪さ、クラスとクライアント間の明確な関係などの優れた機能があります。 単体テストの作成が困難、不可能、または大きすぎてわかりにくい場合、これは多くの場合、テスト自体ではなく、テストされたコードの設計に問題があることを示しています。



プロパティ1.ユニットテストは、システムのモジュール性と設計にプラスの影響を与えます。



システムを設計するとき、「OK、これは素晴らしいアイデアですが、このビジネスをどのようにテストしますか?」という質問をよくします。 クラスが他の多くのクラスに依存している場合、外部リソースを直接使用する場合、または責任を取りすぎる場合、そのようなクラスのテストは非常に困難になります。 私は、デザインのためのデザインやテスト容易性のためのデザインの大ファンではありません。 しかし、実践は、そこまで行く必要がないことを示しています。優れたシステム設計は、システムの主要部分のほとんどをテストでカバーするのに十分に弱く接続されています(設計とアーキテクチャに対する単体テストの影響については、記事「理想的なアーキテクチャ」を参照してください)。



最も興味深いのは、ユニットテストがクラスの設計だけでなく、メソッドの実装にも影響することです。 曖昧なまたは複雑な責任を持つメソッドは、読みにくいだけでなく、テストするのも困難です。 純粋なメソッド(つまり、副作用のないメソッド)は、単体テストの観点からは理想的です。なぜなら、それらは引数以外に依存せず、結果を返す以外に何もしないからです。



しかし、「機能的」な状況に陥らなくても、ユニットテストの必要性は、たとえば、例外を処理するための「戦術」を決定するのに役立ちます。メソッドが例外をスローするか、その場で「キャッチ」できるか。 メソッドがジョブを実行できず、同時に呼び出しコードに何も言わない場合、ユニットテストを使用してその動作を検証することは困難になります。つまり、このメソッドは何らかの方法でクライアントに失敗を通知する必要があります。



プロパティ2.ユニットテストは、システム仕様の優れたソースです。



ポッドキャストの1つで、JUnit、TDD、およびエクストリームプログラミングの父であるKent Beckは、ユニットテストの次の特徴を示しました。各ユニットテストは、テスト対象のクラスに関するストーリーを伝える必要があります。 単体テストは、Assertの単なるコレクションではなく、仕様の有用なソース(公式または非公式)です。 多くの場合、単体テストを読むと、クラスまたはサブシステムに適用される境界条件とビジネスルールを理解するのに役立ちます。

ユニットテストのこの特性から、不快な結果が1つ発生します。テストの品質には、製品コードよりも注意を払う必要があります。 これは、テストが読みやすく、保守が容易でなければならないことを意味します。そうでない場合、彼の人生は最初の落下後に終了します。 このテストを修正しなければならないプログラマーは、この奇跡がどのように機能するかを理解する代わりに、完全に破壊する方が簡単であることに気付くでしょう。 また、テストは、ビジネスロジックコードと比較して「高度な抽象化」を表す場合にのみ、仕様として使用できます。 コード自体の理解が単体テストよりも簡単であれば、誰もテストを仕様として使用しません。



プロパティ3.ユニットテストを使用すると、プログラマが費やした労力を再利用できます。



私たちは皆、喜びに満ちた最愛の開発段階が、システムから始まる暗闇よりもはるかに短いことを知っています。 これはボタンアコーディオンですが、誰もがそれを知っているという事実は、コードの保守を容易にするものではありません。 単体テストは設計にプラスの影響を与え、仕様のソースであるという事実に加えて、開発者が何らかの可能性を実現するために費やした経験も含まれています。



第一に、単体テストにより、プログラマが何を考えていたのか、どの境界条件をチェックし、どの境界条件をチェックしなかったのかをよりよく理解することができます。 第二に、実装中に、プログラマーは、テスト中の追加のコメントで表現できる、解決される問題のコンテキストをより深く掘り下げ、彼の努力を再利用できます(結局、各後続のプログラマーは、すべての深さの深さを評価するのに時間がかかりません)。



プロパティ4.ユニットテストは時間を節約します。



テストの開発には有用な機能の開発に費やすことができる追加の時間を必要とするため、一見したところ、単体テストのこの特性は完全に馬鹿げているように見えるかもしれません。



もちろん、特にテストがテストのために書かれている場合や、システムの保守コストが3倍になるほど悲惨な場合には、これには妥当なコンポーネントがあります。 悪いテストは良いことよりも害が多いことに同意しますが、コードの残りの部分と同じ責任と合理的なプラグマティズムでテストを書くことに近づくと、利益は具体的になります。



長期的には明らかな利点(通常のテストでコードを維持する方が簡単です)に加えて、「近視眼的」な利点もあります。 大規模なシステムでは、作業環境を上げ、5つのサービス、クライアントアプリケーションを起動し、10個の画面をクリックして、追加したばかりのテキストボックスが正しく動作していないことを理解するだけで、新しい機会をテストするのに時間がかかる場合があります。 信じられないように聞こえますが、それはあなたがあなたのプロジェクトで幸運だったか、逆に、私は私の幸運ではなかったことを意味します。 とにかく、ほとんどの単体テストは、特定のクラスの動作を実行またはデバッグするための最速の方法です。



おわりに



私は単体テストの熱心なファンではなく、TDDのファンでもありません。また、100%のカバー率も推奨しません。 著者だけがテストを理解でき、まともな報道を得るために、悪魔が彼の足を骨折するほど多くの抽象化が刺されたなら、あなたと私は途中にいません。 私にとって、テストとは何よりもまず、システムのモジュール性を異なる角度から見、入力と出力の観点からクラスを検討し、境界条件を分析し、クラスがすべきこととすべきでないことを理解する機会です。 他のツールと同様に、誤って使用する方が簡単です。適切に使用するには、経験と常識が必要です。 テストは良いことです、あなたはそれらを調理する方法を学ぶ必要があります。



サイトリンク



1. SERadioエピソード167:JUnitの歴史とKent Beckによるテストの未来



2. ケントベック。 開発テスト



これらは、Kent Beckをフィーチャーした2つの素晴らしいポッドキャストです。彼は、開発テスト文化、JUnit、Continuous Testingなどについて語っています。 私はそれを強くお勧めします!



All Articles