テスト駆動開発を使用する必要があるのはなぜですか? [複製]
-
03-07-2019 - |
質問
複製:
テスト駆動開発について知らない開発者にとって、TDDを採用することでどのような問題が解決されますか?
[編集]開発者が既に(ab)単体テストフレームワークを使用していると仮定しましょう。
解決
TDDが開発者/チームに役立つ3つの理由:
- これから書く内容をよりよく理解する
- テストの作成ポリシーをもう少し強化する
- 開発のスピードアップ
最初にテストを記述する理由の1つは、実際のコードを記述する前に理解を深めることです。私にとって、これはテスト駆動開発の主な利点です。最初にテストケースを作成するとき、コーナーケースについてより批判的に考えます。これにより、コードを記述するときにそれらに対処し、正確であることを確認しやすくなります。
別の理由は、テストの作成を実際に強制することです。多くの場合、TDDを使用せずに単体テストを行う場合、テストフレームワークがセットアップされ、新しいコードを作成して終了します。彼らは、コードがすでにうまく機能していると考えているのに、なぜテストを書くのですか?それは壊れないほど簡単ですよね?しかし、最初は単体テストを行う利点を失いました(まったく異なる議論)。最初にそれらを書いてください、そして、彼らはすでにそこにいます。
これらのテストを最初に記述することは、いくつかの小さな問題が機能するかどうかをテストするために、デバッグ環境でプログラムを起動する必要がないことを意味する可能性があります(特に大規模なプロジェクトの場合)もちろん、変更をコミットする前にそうしないことの言い訳はありません。
自分自身や他の人に最初にテストを書くよう説得するのは難しいかもしれません。両方を同時に作成できるようになると幸運になるかもしれません。これは同じくらい有益な場合があります。
他のヒント
おそらく、リポジトリにコミットする前に、作成したコードをテストします。
そうでない場合、対処すべき他の問題があります。
trueの場合、フレームワークを使用してテストを記述し、現在作成しているメインルーチンまたはドライバーを自動化して、ボタンを押すだけですべてを自動的に実行できるようにすることができます。テストに合格したか失敗したかを判断するために、出力を調べなくてはなりません。コードにテストの成功または失敗を埋め込み、すぐにいいか悪いかの決定を下します。すべてのテストを一度に実行すると、「モグラを打つ」機会が減ります。あるクラスで何かを修正し、別のクラスを壊す状況。すべてのテストに合格する必要があります。
これまでのところいいですね、
TDDの人々は、クラスを書く前に最初にテストを書くことを要求することで、さらに一歩前進します。もちろん、クラスを作成していないため失敗します。テストクラスを記述することを保証する方法です。
既にテストフレームワークを使用していて、作成したテストから良い値を取得し、約70%の有意なコードカバレッジを達成している場合は、うまくいっていると思います。 TDDがより多くの価値をもたらすかどうかはわかりません。それ以上の距離を行くかどうかはあなた次第です。個人的に、私はそれをしません。クラスの後にテストを作成し、必要に応じてリファクタリングします。一部の人々は、テストが失敗することを知って最初にテストを書くことが役立つと思うかもしれませんが、私はしません。
(これは、独自の回答というよりもduffymoの回答に同意するコメントです。)
duffymoの回答:
TDDの人々は、クラスを書く前に最初にテストを書くことを要求することで、さらに一歩前進します。もちろん、クラスを作成していないため失敗します。テストクラスを記述することを保証する方法です。
実際には、コードが何をしているのかをコーダーに考えさせることだと思います。テストについて考えることは、コードが何をすべきかを考えさせます:事前条件と事後条件は何か、どの関数はプリミティブで、プリミティブ関数で構成されているか、最低限必要なパブリックインターフェイスは何か、そして何が実装の詳細。
これらは私が日常的に考えているすべてのことなので、あなたと同じように、「最初にテスト」してください。大量に追加するわけではありません、私にとって。そして率直に言って(これは一部のサークルでは異端であることがわかっています)、「アンカー」したいのです。最初にパブリックインターフェイスをスケッチすることによるクラスのコアアイデア。そのようにして、私はそれを見て、精神的に使用し、それが思ったほどきれいかどうかを見ることができます。 (クラスまたはライブラリは、クライアントプログラマが使用するために簡単で直感的でなければなりません。)
言い換えれば、TDDが最初にテストを作成することで保証しようとすることを行いますが、duffymoのように、別の方法で到達します。
そして、「最初のテスト」の本当のポイントコーダーに一時停止してデザイナーのように考えさせるプログラマーがどのようにしてその状態に入るかをフェチするのはばかげています。自然にそれをしない人のために、「最初にテスト」それらをそこに到達させる儀式として機能します。そうする人のために、「最初にテストする」あまり追加されません-そして、プログラマーが習慣的にその状態に入る方法を妨げる可能性があります。
繰り返しますが、儀式ではなく、結果を見たいと思います。後輩が儀式を必要とする場合、「十字架の駅」または「ロザリオ*」を「溝に入れる」、「最初にテストする」、その目的を果たします。誰かが独自の方法でそこにたどり着くなら、それも素晴らしいことです。
コードをテストすべきではないと言っているわけではないことに注意してください。そうすべき。これにより、セーフティネットが得られます。これにより、エラーをキャッチするためにネットが存在することがわかっているため、大胆なコードであっても、良いコードを書くことに集中できます。
私が言っているのは、「最初のテスト」に対するフェティッシュな主張です。 method (多くの1つ)と goal を混同して、プログラマに自分がコーディングしていることを考えさせます。
*エキュメニカルであるために、カトリック教徒とイスラム教徒の両方がロザリオを使用していることに注意します。繰り返しますが、それは機械的、特定の心の枠組みに身を置く筋肉記憶の方法です。それはフェチ(「性的なフェチ」の意味ではなく、魔法のオブジェクトの本来の意味で)または幸運の魅力です。 「Om mani padme hum」と言ったり、座禅をしたり、「幸運」をなでたり、ウサギの足(ウサギにとってそれほど幸運ではありません。)哲学者ジェリー・フォダーは、難しい問題について考えるとき、似たような儀式を持っています。 (私も試してみましたが、私の名前はジェリーではないので、うまくいきませんでした。;))
理想的:
不要な機能を書くのに時間を浪費することはありません。リファクタリングのセーフティネットとして機能する包括的な単体テストスイートがあります。コードがどのように使用されるかについての実行可能な例があります。開発フローはよりスムーズで高速になります。デバッガーで過ごす時間が少なくなります。
しかし、何よりも、デザインは良くなります。あなたのコードはより良くファクタリングされます-疎結合で、非常にまとまりがあり-より良く形成されました-より小さく、より良い名前のメソッド&クラス。
現在のプロジェクト(比較的ヘビーなプロセスで実行される)では、要件ドキュメントとGUIモックアップに基づいたスケルトンテストケースの記述で構成される、TDDの特異な形式を採用しています。何かを実装する前に、数十、時には数百を記述します(これは、「純粋な」TDDに対して完全に実行されます。
これは、要件文書を確認する優れた方法であることがわかりました。それらで記述された振る舞いを、私がそれらを読むだけであった場合よりもずっと集中的に考えなければなりません。その結果、実装中にしか発見できなかった不整合やギャップがさらに多く見つかりました。この方法で、私はより早く明確化を求めることができ、実装を開始するときにより良い要件を持つことができます。
それから、実装中に、テストは私がまだ行っていないことを測定する方法です。そして、彼らは私が何かを忘れることを防ぎます(大規模なユースケースで作業するとき、それは本当の問題です、笑ってはいけません)。
モラルは次のとおりです。開発プロセスがTDDを実際にサポートしていない場合でも、ある方法で実行でき、品質と生産性を向上させることができます。
私は個人的にTDDを使用していませんが、方法論で見ることができる最大のプロの1つは、顧客満足度保証です。基本的には、開発プロセスの手順は次のとおりです。
1)アプリケーションが何をすべきか、さまざまな状況にどのように反応するかについて顧客に話します。
2)1)の結果をユニットテストに変換し、各テストで1つの機能またはシナリオをテストします。
3)シンプルで「ずさんな」文章を書く(ほとんど)テストに合格しないコード。これが完了すると、顧客の期待に応えました。
4)可能な限り最も効果的な方法でコードを作成したと思うまで、3)で作成したコードをリファクタリングします。
これが完了すると、顧客のニーズを満たす高品質のコードを作成できたことを願っています。お客様が新しい機能を必要とする場合、サイクルを最初からやり直します。機能について話し合い、機能することを確認するテストを作成し、テストに合格するコードを作成して、リファクタリングします。
他の人が言ったように、テストを実行するたびに、古いコードが引き続き機能し、古いコードを壊すことなく新しい機能を追加できることを確認します。
私が話したほとんどの人は、完全なTDDモデルを使用していません。彼らは通常、自分に合った最適なテストモデルを見つけます。 TDDでプレイしているものを見つけ、最も生産性の高い場所を見つけます。
Ruby on Rails開発用のTDDを学ぶために多大な努力をしました。本当にそれとそれに入るまでに数日かかりました。私は非常に懐疑的でしたが、私が尊敬するプログラマーがそれをサポートしているので努力しました。
この時点で、間違いなく努力する価値があると感じました。いくつかの利点がありますが、他の人が喜んでリストしてくれるでしょう。私にとって最も重要な利点は、明白な理由もなく突然何かが壊れて、デバッガーで1日半を費やしているようなプロジェクトの終わりの悪夢のような状況を回避するのに役立つことです。ロジックを追加するにつれてコードベースが劣化するのを防ぐのに役立ちます。
TDD(テスト駆動開発/設計)には次の利点があります
- 開始する前に、ストーリーカードの受け入れ基準を確認します
- コーディングをいつ停止するかを確実に確認します(つまり、受け入れ基準が満たされたときに金メッキが防止されます)
その結果、次のようなコードになります
- テスト可能
- クリーンなデザイン
- 自信を持ってリファクタリング可能
- ストーリーカードを満たすために必要な最小限のコード
- コードの動作の生きた仕様
- 持続的なペースの新機能をサポートできる
テストを作成し、多数の自動化されたテストを行うことは良いことであることは一般的な知識です。
ただし、TDDがないと、しばしば退屈になります。人々はテストを作成し、それを終了します。テストは必要に応じて更新されず、新機能も必要な頻度でテストされません。
これの大きな部分は、コードがテストするのが面倒になったためです。TDDはデザインに影響を与えるため、テストがはるかに簡単になります。 TDDを使用したため、多数のテストが用意されており、コードまたは要件が変更されるたびに回帰を見つけやすくなり、劇的にデバッグが簡素化され、優れたTDDが評価され、変更時により多くのテストが記述されます必要-サイクルの開始に戻りました。
多くの利点があります:
- より高いコード品質
- バグの減少
- 無駄な時間の削減
これらのどれでも、TDDを実装するのに十分な正当性があります。