25

テスト駆動開発の定義原則の 1 つは、最初に単体テストを作成し、次にそれらの単体テストに合格するコードを作成することであることは知っていますが、このようにする必要はありますか?

主に、私が取り組んできた過去のいくつかのプロジェクトは、設計されたものではなく、概念実証から進化したものであるため、それを書くまで何をテストしているのかわからないことがよくあります。

以前に単体テストを書こうとしたことがありますが、それは役に立つかもしれませんが、私には自然に思えません。

4

20 に答える 20

39

ここにはいくつかの良いコメントがありますが、1 つのことが無視されていると思います。

最初にテストを書くことが設計を推進します。これは重要なステップです。テストを「同時に」または「直後」に記述すると、TDD をマイクロステップで実行する設計上の利点が失われる可能性があります。

最初は安っぽい感じですが、目の前で思いもよらなかったデザインが展開されていくのがすごいです。私はそれが起こるのを見てきました。

TDD は難しく、万人向けではありません。しかし、すでに単体テストを採用している場合は、1 か月間試してみて、設計と生産性にどのような影響があるかを確認してください。

デバッガーに費やす時間が減り、アウトサイドイン設計について考える時間が増えます。これらは、私の本の中で 2 つの大きなプラスです。

于 2008-10-29T15:08:11.270 に答える
9

コードが書かれた後に書かれた単体テストはより良いテストであることを示す研究があります。ただし注意すべき点は、人々はイベントの後にそれらを書きたがらないということです。したがって、少なくともテストが作成されるため、TDD は適切な妥協案です。

したがって、コードを記述した後にテストを記述する場合は、それでよいので、そのままにしておくことをお勧めします。

私は混合物を作る傾向があります。要件を理解すればするほど、より多くのテストを前もって書くことができます。要件 (または問題に対する私の理解) が不十分な場合、後でテストを作成する傾向があります。

于 2008-10-29T14:56:35.927 に答える
7

TDD はテストに関するものではなく、テストがコードをどのように駆動するかです。したがって、基本的には、アーキテクチャを自然に進化させるためのテストを書いています (そして、リファクタリングを忘れないでください!!! そうしないと、そこから多くの利益を得ることはできません)。後で回帰テストと実行可能なドキュメントの武器を手に入れることは良い副作用ですが、TDD の背後にある主な理由ではありません。

したがって、私の投票は次のとおりです。最初にテストします

PS: いいえ、それは、事前にアーキテクチャを計画する必要がないという意味ではありません。

于 2008-10-29T15:32:02.563 に答える
6

私は過去 6 ~ 7 年間、開発チームを率いてきました。私が確かに言えることは、開発者として、また私が一緒に働いた開発者として、コードが全体像のどこに適合するかを知っていれば、コードの品質に驚異的な違いが生じるということです。

テスト駆動開発 (TDD) は、「何?」に答えるのに役立ちます。「どうやって?」と答える前に。そしてそれは大きな違いを生みます。

PoCタイプの開発/アーキテクト作業でそれに従わないことに不安があるかもしれない理由を理解しています. そして、このプロセスに従うことは完全に意味がないかもしれません。同時に、TDD は開発段階に入るプロセスであることを強調したいと思います (時代遅れに聞こえることは承知していますが、要点はわかります :) 低レベルの仕様が明確な場合。

于 2008-10-29T15:48:45.993 に答える
3

最初にテストを書くことは、コードが実際に何をすべきかを定義するのに役立つと思います。コードが何をすべきか、またはどのように動作するべきかについて、適切な定義を持っていない人が多すぎます。彼らは単に書き始め、進行するにつれてそれを作り上げます。最初にテストを作成すると、コードが何をするかに集中できます。

于 2008-10-29T15:10:51.407 に答える
2

ディレクティブは、最終製品の全体的な品質や生産性、さらにはその両方を改善するためにできることについての提案です。適切なコーディングの実践の神に一瞬で打たれない限り、それらは決して従うべき法律ではありません。

これが私の妥協点であり、非常に便利で生産的であることがわかりました。

通常、正しく理解するのが最も難しい部分は要件であり、その背後にはクラス、API、パッケージの使いやすさがあります。次に、実際の実装です。

  1. インターフェイスを記述します (インターフェイスは変更されますが、何をしなければならないかを知るのに大いに役立ちます)
  2. インターフェイスを使用する簡単なプログラムを作成します (それらは愚かなメインです)。これは、どのように使用されるかを決定するのに大いに役立ちます (必要に応じて 1 に戻ります)。
  3. インターフェイスにテストを書き込みます (TDD から統合したビットは、必要に応じて何度でも 1 に戻ります)
  4. インターフェイスの背後にある実際のコードを書く
  5. クラスと実際の実装でテストを作成し、カバレッジ ツールを使用して、実行パスを忘れないようにします。

ですから、コーディングの前にテストを書きますが、特定のレベルの詳細で何をする必要があるかを理解する前には決して書きません。これらは通常、高レベルのテストであり、全体をブラック ボックスとしてのみ扱います。通常は統合テストとして残り、インターフェイスが安定した後はあまり変更されません。

次に、その背後にある実装に対して一連のテスト (単体テスト) を作成します。これらはより詳細になり、最適化および拡張されるにつれて、実装が進化するにつれて頻繁に変更されます。

これは厳密に言えばTDDですか?過激 ?アジャイル…?なんでもいい... ?わかりません、率直に言って、気にしません。それはのために働く。必要に応じて、またソフトウェア開発の実践に対する私の理解が進化するにつれて、それを調整します。

私の2セント

于 2008-10-29T15:38:36.840 に答える
2

私は 20 年間プログラミングをしてきましたが、なんらかの単体テストを実行していないコード行を書いたことはほとんどありません。ある種のテストが実行されていないコード行は、私には理解できません。

多くの場合、テスト フレームワークが適切に配置されていない場合は、作成する各クラスに main() を書き込むだけです。それはあなたのアプリに少し厄介なものを追加しますが、誰かがいつでもそれを削除 (またはコメントアウト) することができます。リリース ビルド用に自動的にコンパイルされる te​​st() メソッドがクラスにあればいいのにと思います。テスト メソッドがコードと同じファイルにあるのが気に入っています...

だから私はテスト駆動開発とテスト開発の両方を行ってきました。TDD は、プログラマーの初心者にとって非常に役立つと言えます。プログラマーが学べる最も重要な教訓の 1 つである「外部から」コードを表示することを学ぶのに役立ちます。

また、TDD は、行き詰まったときに作業を進めるのにも役立ちます。コードで実行する必要があることがわかっている非常に小さな部分を記述し、それを実行して修正するだけで、病みつきになります。

一方、既存のコードに追加するときに、必要なものがほぼ正確にわかっている場合、それは大したことではありません。「その他のコード」では、新しいコードを適所でテストすることがよくあります。各パスを確実にテストする必要がありますが、フロントエンドからテストを実行するだけで十分なカバレッジが得られます (動的言語を除きます。動的言語は例外です。動的言語については、何があってもすべてのユニット テストを実行する必要があります)。

ところで、私がかなり大規模な Ruby/Rails プロジェクトに参加していたとき、テスト カバレッジの割合は非常に高かったです。主要な中央モデル クラスを 2 つのクラスにリファクタリングしました。2 日かかるはずでしたが、すべてのテストをリファクタリングする必要があったため、最終的には 2 週間近くかかりました。テストは完全に無料ではありません。

于 2008-10-29T16:19:45.993 に答える
2

「ユニット」をどのように呼び出してコンパイルするかから始めます。お気に入り:

picker = Pick.new
item=picker.pick('a')
assert item

それから私は作成します

class Pick
 def pick(something)
 return nil
 end
end

次に、「テスト」ケースで Pick を使用し続けて、どのように呼び出したいか、さまざまな種類の動作をどのように処理するかを確認できました。いくつかの境界またはある種のエラー/例外で問題が発生する可能性があることに気付いたときはいつでも、それを起動して新しいテスト ケースを取得しようとします。

つまり、要するに。はい。事前にテストを行っている割合は、行っていない場合よりもはるかに高くなっています。

于 2008-10-29T14:57:16.113 に答える
2

現在、非常に多くの答えがあり、それらはすべて異なります。これは現実に完全に似ています。誰もが違う方法でやっています。単体テストについては大きな誤解があると思います。人々がTDDについて聞いて、それは良いことだと言ったように私には思えます。その後、彼らは TDD が実際に何であるかをよく理解せずに単体テストを書き始めました。彼らは「そうそう、テストを書かなければならない」という部分を手に入れただけで、それに同意しました。彼らはまた、「最初にテストを書くべきだ」ということも聞いていましたが、彼らはこれを真剣に受け止めていません。

それは彼らがテストファーストの利点を理解していないからだと思います。そして彼らは、最初にテストを書くのを好まない理由を常に 1.000.000 の言い訳を見つけているようです。すべてがどのように適合するかを理解するのは難しすぎるからです。私の意見では、一度自分自身を訓練し、テストファーストのアプローチを試してみて、利点を見始めることができないことを隠しているのは、すべて言い訳です。

彼らが「私はこのテストファーストのことについて確信が持てませんが、このようにしたことは一度もありません」と主張し始めた場合、最もばかげたこと...素晴らしい...

単体テストはもともとどこから来たのだろうか。コンセプトが本当に TDD に由来する場合、人々がそれを誤解するのはばかげているからです。

于 2010-12-01T21:06:52.657 に答える
2

よくわかりませんが、あなたの説明から、テストファーストが実際に何を意味するのかについて誤解があるかもしれないと感じています。すべてのテストを最初に書くという意味ではありません。それはあなたが非常にタイトなサイクルを持っていることを意味します

  1. 単一の最小限のテストを書く
  2. 必要最小限の本番コードを記述してテストに合格する
  3. 失敗する次のテストを書く
  4. 最も簡単な方法で既存の本番コードを変更することにより、既存のすべてのテストに合格する
  5. 重複を含まず表現力豊かになるようにコードをリファクタリングします (テストと本番の両方で!)。
  6. 別の賢明なテストが思いつかなくなるまで、3. を続けます。

通常、1 サイクル (3 ~ 5) には数分しかかかりません。この手法を使用すると、テストと製品コードを並行して記述しながら、実際に設計を進化させることができます。事前の設計はあまり関係ありません。

それが「必要」であるかどうかについては、いいえ、明らかにそうではありません。TDDを行わずに成功したプロジェクトは数え切れないほどあります。しかし、TDD を使用すると、通常、生産性に悪影響を与えることなく、品質が大幅に向上するという強力な証拠がいくつかあります。そして、それも楽しいです!

ああ、それが「自然」ではないということに関しては、それはあなたが慣れているかの問題です. 数分ごとに緑色のバー (「すべてのテストが合格」を示す典型的な xUnit サイン) を取得することに夢中になっている人を知っています。

于 2008-11-01T20:59:42.350 に答える
2

いつもではありませんが、私がそうするとき、それは本当に役立つことがわかりました.

于 2008-10-29T14:50:47.093 に答える
2

私は自分のコードを書くときにそれらを書く傾向があります。せいぜい、書く前にクラス/モジュールが存在するかどうかのテストを書くだけです。

私は、テストするコードよりも前にテストを書くほど詳細に計画を立てていません。

これが私の考え方や方法の欠陥なのか、それとも単に TIMTOWTDI なのかはわかりません。

于 2008-10-29T14:55:33.887 に答える
1

個人的には、コードを書く前に単体テストを行わないと、その効果の多くが失われると思います。

テストに関する古くからの問題は、それについてどれほど懸命に考えても、カバーするテストを作成するためのすべての可能なシナリオを思い付くことは決してないということです。

ユニットテスト自体は、このコードと他のすべてとの間の相互作用をカバーしていないコードの1つのユニットのみを調べる制限的なテストであるため、これを完全に防ぐことはできませんが、最初にクリーンなコードを作成するための優れた基盤を提供します。少なくとも、モジュール間の相互作用の問題の可能性を制限します。私は常に、コードを可能な限りシンプルに保つという原則に取り組んできました。実際、これはTDDの重要な原則の1つであると信じています。

したがって、基本的にこのタイプのクラスを作成して構築できるというテストから始めます。理論的には、コードのすべての行に対してテストを作成するか、少なくとも特定のコードのすべてのルートをカバーします。あなたが行くように設計する!明らかに、最初に作成された大まかな設計に基づいており、作業するためのフレームワークを提供します。

あなたが言うように、最初は非常に不自然で時間の無駄に思えるかもしれませんが、欠陥の統計が届き、TDDを使用して完全に記述されたモジュールを表示すると、長期的に見ればそれが報われることを私は直接目にしました時間の経過とともに、他の欠陥よりもはるかに少ない欠陥があります。

于 2008-10-29T15:54:48.727 に答える
1

前、中、後。beforeは仕様、契約、作業の定義の一部です。期間中は、実装中に特殊なケース、不良データ、例外が明らかになる場合です。その後、メンテナンス、進化、変更、新しい要件があります。

于 2008-10-29T22:23:45.213 に答える
1

最初にテストを作成すると、コードがどのように見えるかが定義されます。つまり、コードをよりモジュール化してテストしやすくする傾向があるため、非常に複雑で重複する機能を持つ「肥大化」したメソッドを作成しません。これは、テストを容易にするために、すべてのコア機能を別々の方法に分離するのにも役立ちます。

于 2008-10-29T15:22:45.033 に答える
0

あなたが書くことに慣れている何かを書いているとき、最初にあなたが定期的にチェックするすべてのものを書き、次にそれらの機能を書くのに役立ちます。多くの場合、これらの機能は、作成しているソフトウェアにとって最も重要ではありません。さて、反対側には銀の弾丸はなく、手紙に従わないでください。開発者の判断は、テスト駆動開発とテスト後者の開発のどちらを使用するかを決定する上で大きな役割を果たします。

于 2008-10-29T22:12:52.240 に答える
0

エクストリーム プログラミングを使用すると、テストが効果的に文書化されることを忘れないでください。何をテストしているのかわからなければ、アプリケーションに何をさせたいのかわからないということでしょうか?

次のような「ストーリー」から始めることができます

「ユーザーは質問のリストを取得できます」

次に、単体テストを解決するためのコードを書き始めます。上記を解決するには、少なくとも User と question クラスが必要です。次に、フィールドについて考え始めることができます。

「ユーザー クラスには名前、DOB アドレス、TelNo ロックされたフィールドがあります」

など。お役に立てば幸いです。

狡猾

于 2008-10-29T15:00:27.667 に答える
0

はい、真の TDD 原則を使用している場合。それ以外の場合は、単体テストを書いている限り、他の人よりもうまくやっています。

私の経験では、通常はコードの前にテストを書く方が簡単です。そのようにすることで、コードを書くときに使用する簡単なデバッグ ツールを自分で用意できるからです。

于 2008-10-29T15:00:48.307 に答える
0

同時に書きます。新しいクラスとテスト クラスのスケルトン コードを作成し、いくつかの機能のテストを作成して (新しいオブジェクトをどのように呼び出すかを確認するのに役立ちます)、それをコードに実装します。

通常、私は最初からエレガントなコードにはなりません。通常は非常にハックです。しかし、すべてのテストが機能するようになったら、非常にきちんと整頓されていて、堅実であることが証明できるものになるまで、リファクタリングを行うことができます。

于 2008-10-29T15:01:06.637 に答える
0

最初に実際の単体テストを作成するわけではありませんが、コーディングを開始する前にテスト マトリックスを作成し、テストする必要がある可能性のあるすべてのシナリオをリストします。また、アプリケーションの基本的なシナリオのほとんどをカバーする回帰テストの一環として、プログラムの任意の部分に変更が加えられたときにテストする必要があるケースのリストを作成し、コードの一部を完全にテストします。かわった。

于 2008-10-29T14:56:21.373 に答える