私はすべてユニットテストに熱心ですが、この形式のテストの最初の開発が本当に有益かどうか疑問に思うことがあります...
このような小さくてささいなテストは、コードベースの「炭鉱のカナリア」になり、手遅れになる前に危険を警告することができます。簡単なテストは、正しい相互作用を実現するのに役立つため、このテストを続けるのに役立ちます。
たとえば、慣れていないAPIの使用方法を調べるために用意された簡単なテストについて考えてみます。そのテストが、APIを「実際に」使用するコードで行っていることに関連がある場合は、そのテストを維持することは有用です。APIが新しいバージョンをリリースし、アップグレードする必要がある場合。これで、回帰をキャッチするために使用できる実行可能形式で記録されたAPIの動作をどのように期待するかについての仮定ができました。
... [実際のプロセス]では、コード(ビジネスリクエスト、要件ドキュメント、アーキテクチャドキュメント)の上に3〜4層あり、実際に定義されたビジネスルール(割引価格は価格-割引)が誤って定義されている可能性があります。それが状況である場合、単体テストは何の意味もありません。
テストを書かずに何年もコーディングを続けてきた場合、何かの価値があることはすぐにはわかりません。しかし、作業の最善の方法は、「早くリリースする、頻繁にリリースする」、または「アジャイル」であり、迅速/継続的に展開する機能が必要であるという考え方の場合、テストは間違いなく何かを意味します。これを行う唯一の方法は、テストでコードに加えたすべての変更を正当化することです。テストがどれほど小さくても、グリーンなテストスイートが用意できたら、理論的には問題なく展開できます。「継続的生産」および「永久ベータ」も参照してください。
また、この考え方を身に付けるために「最初にテスト」する必要はありませんが、それは一般的にそこに到達するための最も効率的な方法です。TDDを行うときは、2〜3分の小さなRed Green Refactorサイクルに身を固めます。どの時点でも、立ち止まって離れることができず、デバッグを完了して元に戻すのに1時間かかる完全な混乱が手にあります。
さらに、ユニットテストはもう1つの障害ポイントです...
成功したテストは、システムの障害を示すものです。失敗したテストは、テストのロジックまたはシステムのロジックのエラーを警告します。テストの目的は、コードを壊すか、1つのシナリオが機能することを証明することです。
コードの後にテストを記述している場合、テストが実際に機能していることを確認するには、テストが機能していないことを確認する必要があるため、「悪い」テストを作成するリスクがあります。コードの後にテストを記述している場合、これは「トラップを起動」し、コードにバグを導入してテストが失敗することを確認する必要があることを意味します。ほとんどの開発者はこれに不安を感じるだけでなく、時間の無駄だと主張します。
ここで何を得るのですか?
この方法で物事を行うことには確かにメリットがあります。Michael Feathersは、「レガシーコード」を「テストされていないコード」と定義しています。このアプローチをとると、コードベースに加えるすべての変更を正当化します。テストを使用しない場合よりも厳格ですが、大規模なコードベースを維持することになると、それだけで採算が取れます。
フェザーと言えば、これに関してチェックすべき2つの優れたリソースがあります。
これらはどちらも、「グリーンフィールド」ではないプロジェクトにこれらのタイプの実践と規律を働かせる方法を説明しています。これらは、密結合コンポーネント、ハードワイヤード依存関係、および必ずしも制御する必要のないものに関するテストを作成するための手法を提供します。それはすべて「継ぎ目」を見つけ、それらをテストすることです。
[I]割引価格が間違っている場合でも、テストチームは問題を見つけますが、単体テストはどのように作業を節約しましたか?
このような習慣は投資のようなものです。返品は即時ではありません。彼らは時間の経過とともに蓄積します。テストを行わない代わりに、本質的には、リグレッションをキャッチできない、統合エラーを恐れずにコードを導入できない、または設計上の意思決定を推進できないという責任を負うことになります。美しさは、コードベースに導入されたすべての変更を正当化することです。
ここで何が欠けていますか?今のところ、TDDが便利だと受け入れられないので、TDDを愛するように教えてください。私も進歩したいので欲しいですが、それは私には意味がありません。
私はそれを職業上の責任と見なしています。努力するのが理想です。しかし、それを追跡するのは非常に難しく、退屈です。それを気にし、テストされていないコードを生成するべきではないと感じた場合は、適切なテストの習慣を学ぶ意欲を見つけることができます。私が現在多くのことを行っていることの1つは(他の人と同様に)、自分で1時間のタイムボックスを設定して、テストをまったく行わずにコードを記述し、それを破棄する規律を持っていることです。これは無駄に見えるかもしれませんが、実際にはそうではありません。それはその運動が会社の物理的な材料にコストをかけるようなものではありません。これは、問題を理解するのに役立ち、より高品質でテスト可能なコードを作成する方法を理解するのに役立ちました。
私のアドバイスは、最終的には、あなたが本当にそれを上手にしたいという欲求がない場合は、まったくそれをしないことです。維持されていない、パフォーマンスが悪いなどの貧弱なテストは、テストがないことよりも悪い場合があります。自分で学ぶのは難しいですし、たぶんそれを気に入るはずはありませんが、それをやりたいという願望がないか、十分な価値を見いだせないなら、学ぶのはほぼ不可能です。時間の投資を保証します。
数人の人々は、テストが仕様の実施に役立つと述べ続けています。スペックも間違っているというのが私の経験です。
開発者のキーボードは、ゴムが道に出会うところです。仕様が間違っていて、フラグを立てていない場合は、非難される可能性が非常に高くなります。または、少なくともあなたのコードはそうします。テストに関係する規律と厳格さは、遵守するのが困難です。それはまったく簡単ではありません。それには練習、多くの学習、そして多くの間違いが必要です。しかし、結局それは報われます。ペースの速い、急速に変化するプロジェクトでは、スローダウンしても、夜に眠れる唯一の方法です。
ここで考えるもう1つのことは、テストと基本的に同じ手法が過去に機能することが証明されていることです。「クリーンルーム」と「契約による設計」はどちらも同じタイプの「メタ」コード構成を生成する傾向があります。テストを行い、さまざまなポイントでそれらを実施します。これらの手法はどれも特効薬ではなく、厳密に言えば、市場投入までの時間の面で提供できる機能の範囲で最終的にコストがかかります。しかし、それはそれについてではありません。それはあなたが提供するものを維持できるようにすることです。そして、それはほとんどのプロジェクトにとって非常に重要です。