web-dev-qa-db-ja.com

TDD-TDDを本当に考え始める方法は?

私はアジャイル、XP方法論とTDDについて読んでいます。

私はTDDを実行する必要があると述べているプロジェクトに参加していますが、ほとんどのテストは何らかの形で統合テストであるか、プロジェクトの過程でTDDはコードをより速く完成させるために忘れられています。

ですから、私の場合に関しては、単体テストを作成しましたが、テストを作成するのではなく、最初にコードを作成し始めることになります。考え/デザイン/パラダイムの変化が実際には巨大だと感じています。したがって、TDDを本当に信じていますが、時間のプレッシャー/プロジェクトの成果物のために、実際には古いスタイルに戻ることになります。

純粋な単体テストされたコードを持っているクラスはほとんどありませんが、モックが思い浮かぶと、プロセスを続行できないようです。また、「テストを書くのは簡単ではないか」という症候群も時々見られます。

どうやって私がこれを処理すべきだと思いますか?

73
bkhanal

これまでの回答のいずれも、現代の開発慣行に対する基本的な洞察であると私が考えるものに触れていないこと、つまり、要件を収集し、分析を行い、必要なモデルを作成することによってソフトウェアを作成する「昔ながらの」方法に触れていないことは興味深いと思います。コードを書く前のシステムは、実際には多くのことを行っていました。

TDDは実際にこれを具体化していますある程度

テストを作成するには、最初に知っておく必要があります-非常に簡単に言えば-入力がどうなるか、期待される出力がどうなるかです。

その知識が得られたら、そのコード自体を記述したり、それらのアーティファクトを作成したりする前に、神話上のコードの一部を実行するためのテストを作成し、ある程度、そのコードが相互作用する他のアーティファクトを作成できます。

これは、以前は「ウォーターフォール」方式で「要件エンジニアリング」および「システム分析」と呼んでいたものです。

さらに、このレベルで要件を把握すると、ライティングテストが自然に行われることがわかります(結局のところ、これらの要件で具体化された機能ステートメントのコードでの表現にすぎません)。

また、要件をテストの形で表現するコードを作成する際には、実行可能コードの形でプロジェクトにギャップや誤解をコミットする前に、要件のギャップや誤解を特定します。

現代の「アジャイル」手法の実践者が一連の「滝」に従事していることを認めるのは恥ずかしいことだと思うので、要件エンジニアリングと理解のこの必要性は、これらのことに対処する必要性について話している言葉の背後にあります。 「アジャイル」(一般的に理解されている、またはおそらく誤解されている)がお風呂の水をたくさん使って赤ちゃんを捨てたことを認めないように必死に努力している間。

48
Deltics

ですから、私の場合に関しては、単体テストを作成しましたが、テストを作成するのではなく、最初にコードを作成し始めることになります。考え/デザイン/パラダイムの変化が実際には巨大だと感じています。したがって、TDDを本当に信じていますが、時間のプレッシャー/プロジェクトの成果物のために、実際には古いスタイルに戻ることになります。

一定期間、たとえば数週間または1か月間、TDDについて完全に懲戒処分を受けることをお勧めします。テストの前にコードを書いていることに気付いたら、それを削除して最初からやり直し、テストに失敗します。できることがわかるまで、それがどのように感じられるかがわかるまでこれを行います-そして、それを行う能力と、情報に基づいた選択を行う自由が得られます-そして、その選択が時々最初にコーディングすることである場合は問題ないことを理解します。しかし、習慣があなたを良い習慣から遠ざけさせてはいけません。最初にグッドプラクティスを理解し、次にそれらをいつ適用するかを選択します(もちろん、その答えは「常に」であることがわかるかもしれません)。

純粋な単体テストコードを使用しているクラスはほとんどありませんが、モックが登場すると、プロセスを続行できないようです。また、「テストを書くのは簡単ではないか」という症候群も時々見られます。

モックは1つです-あなたはまだそれらが得意ですか?モックに慣れておらず、モックが適切な状況にある場合は、TDDのようにモックがうまくいくまで練習してください。

「些細な」問題に関しては、最初の数週間はそうではありません。常にTDDだけです。そして、TDDがあなたをより良い設計へと駆り立てていることに気づいたら、たとえ「些細な」コードであっても、それに注意してください。それがないとコードがどのようになるかを考えてください。また、TDDにとって些細なコードはないことに気付くかもしれません。か否か。しかし、私のポイントは、かなりの期間、真剣に試してみてください。そうすれば、より良い選択をすることができます。それに慣れて、評価してください。

24
Carl Manaster

簡単だ:

By learning to think about the "What" __before__ you think about the "How"

言い換えれば、あなたがhowであるのではなく、want(インターフェース)を正確に考えてください。やる(実装)

私の経験に基づく設計ツールとしてのTDDは、コーダーの観点よりもユーザーの観点から物事を見るのに本当に役立ちます。さらに、TDDはあなたの心を助けると思います本当にあなたが何をしようとしているのか、期待される結果は何かなどについて考えます。

したがって、次に「TDD」を試すときは、何をしようとしているのかを自問し、意図を表すコードを書き始めてください。

例:

たとえば、誰かがあなたに整数加算器を書いてほしいと言っています。

TDDのマインドを持たない人は、単に次のことを行います。

int add(int a, int b)
{
  return a + b;
}

上記のコードは正しいですか?もちろんそうだ。しかし、私の経験に基づくこのアプローチは、複雑なコンポーネントを作成する場合は失敗します。 (それがあなたが最初にこの質問をした理由です;私は知っています、私は以前にそこにいました(おそらくまだ?笑))

TDDの優れている点は、実装(方法)をすぐに求めずに、システムのインターフェイス(何)に何よりも注意を向けることを強制することです。

言い換えれば、誰かが私に加算器を書くように頼んだ場合、私は次のようなものを持っているでしょう:

void assertOnePlusTwoEqualThree()
{
  assert( add(1,2) == 3 );
}

Add()がどのように機能するかを考える前でさえ、私はすでにいくつかのことを解決していることに注意してください。つまり、私はすでに理解しました:

  • 入力と出力の両方の加算器のインターフェース
  • 最初のtrivialテストケース(ユニットテストは無料です!!)

次にadd()を実装します。

ここで説明するロジックの実装が非常に簡単であるかどうかは、しない問題です。 TDDの考え方を持つことは、例外なく常にそれを適用することです。あなたはそれを何度もしなければならないので、もうそれについて考えることさえありません。それはあなたがデザインする方法のほんの一部です。私はそれが私に専門的に起こったのを見たのでこれを言うことができます(それは約1年の忍耐を要しました)。

手元の複雑さに関係なく、プログラミングで常に良い仕事をしている場合と同じように、sameの方法で仕事に取り組みます。

最後に、TDDは「コードスケッチ」に匹敵すると思います。つまり、各シナリオ(テストケース)でインターフェイスが適切に機能するかどうかを確認するための試行を開始します。つまり、インターフェースや名前などを変更することになった場合は、okayになります。私が学んだことは、多くの場合、デザインは単に理解することであるということです。問題を徹底的に。 TDDは、それを可能にする1つのツールです。

人間の心であるIMOは、抽象的な思考(何かを実装する方法)よりも具体的な例(テストケース/シナリオ)の方が簡単に機能します。テストケースを持つことで、あなたの心はあなたが目前に解決しようとしている問題について徐々に学ぶことができます。

知らなくても大丈夫です(「伝統的な」方法に戻って...リラックスして、心を調整させてください)。それが完璧でなくても大丈夫です(いくつかの実装コードを書くことは完全に大丈夫です...あなたの脳はただ物事を理解しようとしているだけです)。ただ試して、読み続け、コーディングを続けてください、しかしneverあきらめてください! =)

15
sivabudh

「つまり、TDDを本当に信じているのに、時間のプレッシャーやプロジェクトの成果物のために、実際には古いスタイルに戻ることになります。」

実際、これはおそらく真実ではないと思います。

「古いスタイルに戻る」場合、のみの理由は、TDDがより良いコードをより迅速に生成するとは思わないためである可能性があります。

誰かがTDDの使用をやめたのは、コードをより早く作成したほうがよいと感じたからだと思いますpoor

7
S.Lott

練習してみてください コード型

型は暗記するためのものです。型の生徒は、結論としてではなく、形としてそれを研究します。重要なのは型の結論ではなく、結論に至るステップです。私が考える方法を考え、私が設計する方法を設計することに傾倒したいのであれば、私が反応する方法で細目に反応することを学ぶ必要があります。このフォームに従うと、それを行うのに役立ちます。フォームを学び、それを繰り返し、それを繰り返すと、デザインの決定につながる微細な要因に私が対応する方法に対応するように心と体を調整します。

コードカタは、TDDがどのように感じられるべきかを私に感じさせてくれました。私はリズムを失い始めたとき早く、古い習慣に戻ってしまうことを知っています。その時点で、小さな手順を実行したり、テストをより頻繁に実行したり、赤でリファクタリングしようとしていないことを確認したりする必要があることがわかりました。

5

些細なコードはバグが隠れているところです。主に、そこにあるものではなく、そこにあることを意図したものを読むのは人間の本性だからだと思いますisそこに。

私はすべての新しいプロジェクトでTDDに従うように自分自身を訓練しようとしてきました。古い習慣を打ち破るのは難しいですが、それだけの価値があると思います。事前のコーディングが多いほど時間がかかるように見えますが、デバッグ時間はwayダウンしています。

コードを書いている間、どのようにコードをテストするかについて考えないでください。コードがどのように機能するかを実行するテストを作成してから、テストに合格する最も簡単なものを作成します。泡立てて、すすぎ、繰り返します。あなたのコードはおそらくあなたが想像したようなものではなくなるでしょうが、間違いなくもっとうまくいくでしょう。

また、重要なのは、失敗するテストを作成することです。合格したテストを作成しても、欠陥を見つけるのに役立ちません。そして、これは最初にテストを書くもう1つの非常に良い理由です-最初にコードを書き、次にテストを書くと、テストはコードに合格するように書かれ、(意図せずに)望ましい結果ではなくコードをテストするように偏ります。そして、正しいコードがないとテストが失敗することをどうやって知ることができますか?テストは単なるコードであるため、バグの影響も受けやすくなっています。

したがって、最初にテストを記述し、次にコードを少しずつ並列に記述します。テストを使用してコードが正しいことを表明し、コードを使用してテストが正しいことを表明します(はい、アルゴリズムが完璧であると確信しているにもかかわらず、テストが失敗している可能性があります。これはすべて、愚かなタイプミスをしたためです。テストで。私は今朝それをしました)。

4
Duncan

規律。

TDDを使用することを決定し、それに固執します。プロセスにコミットし、それを結論に導くのは、完全にあなた自身の能力の問題です。

4
Fraser Graham

KentBeckによる " Test Driven Development:By Example "を購入し、それを読んでください。

次に、失敗した単体テストを記述します。

3
John Saunders

どうやって私がこれを処理すべきだと思いますか?

ユニットテストをオブジェクトとのダイアログとして考えることをお勧めします(Java、C#、Ruby、PHPなどのOO対応言語)でプログラミングしていると仮定します)。

テストケースクラスを作成し、テストメソッドでオブジェクトとの相互作用について考えます。オブジェクトに動詞として渡すメソッドを使用してインテリジェントマシンと話していると想像してください。次に、Assertsを使用して、オブジェクトが希望どおりに反応したことを確認します。

しばらくすると、このスタイルのプログラミングをとても楽しんで、それなしではプログラミングできないと思うかもしれません;-)

2

TDDを行うペアプログラム(理想的にはあなたよりも優れた誰かと)、

暇な時でも

TDDは、少なくとも私にとっては、私が思っているよりも悪くなりやすいスキルの1つです。私がTDDプロジェクトに参加しているとき、私のTDDスキルは常に向上し、TDDをより良くできるときに私に指摘できる誰かとプログラミングをペアリングします。私よりもよく知らない人とのペアプログラミングでさえ、一人で作業するよりも自分のアイデアを具体化するのに役立ちます。

ペアプログラミングとTDDに特に焦点を当てて、 Code Retreat または coding dojo を検索(または開始)します。

会社で許可されている場合は、週に1時間しかない場合でも、昼食時にでも、会社の時間に、または少なくとも会社のオンサイトで1つを整理します。

2
JeffH

TDDとは、自分が何をしているのか、何をしたのかを知ることです。 TDDが適切に設定されている場合は、おそらく不要なコード行をコメントアウトして、すぐにテストを実行し、テストを中断することによって本当に必要かどうかを確認できます。これらの破壊テストには、このコード行が必要な理由を理解できる十分な説明が含まれている必要があります。

コードを変更したときに何が壊れているかをTDDが特定しないと、何かが壊れていないことを確認する前に、潜在的に大規模な人間の回帰テストが必要になります。総合品質管理のすべての部分と同様に、TDDの目標は、製品ラインの最後で高価な手動テストの必要性をすべてではないにしてもほとんど取り除くことです。どうやって?あなたが何をしているのかを知ることによって。どうやって?あなたがしていることを測定し、それを改善する方法を研究することによって。

コードにバグを発見して修正した場合。質問は次のようになります:それはどのように起こったのですか?今後これを防ぐことはできますか?どうやって?

これは、要件が不十分なためかもしれません。これは、あなたが制御できない要因によるものかもしれません。重要なのは、カーペットの下の問題をブラッシングするだけでなく、その方法についての知識を理解して引き出し、それをプロセスに組み込むことです。

TDDはこの一部にすぎず、互換性のある有望な環境がなければうまく機能しません。

この管理を行うには、アジャイル手法が長期的に変更をより安価にするという基本原則を受け入れる必要があります。アジャイルメソッドを使用すると、変更のコストが対数的に増加しますが、アジャイルメソッドを使用しない開発では、時間の経過とともに変更のコストが指数関数的に増加します。

これについて読むべきことはもっとたくさんあります。次の「ウィリアム・エドワーズ・デミング」、「総合的品質管理」、「変更コスト曲線」をグーグルで検索します。

1
Lamaan Ball

あなたがレガシーコードの大きな混乱に陥っているとき、私は レガシーコードで効果的に働く 非常に便利だと思いました。古いレガシーコードに変更を加える前に単体テストを作成することですが、TDD割り当てのモチベーションは向上すると思います。そして、あなたの質問の基調から、これはあなたがいた立場であるように思われます。

そしてもちろん、他の多くの人が指摘したように規律。しばらくすると、自分自身を強制することで、なぜ別の方法でそれをしたのかを忘れてしまいます。

1

その日のTDDマントラ...

TDDのTはTODOまたはタスク駆動です

TDDはタスク(別名、テスト、または仕様)の設定に関するものであると人々に考えてもらいたいと思います。 (完了していないタスクは赤、完了したタスクは緑です。)

テスト/仕様の結果を表示する継続的なテストランナーを持つことは、テストの習慣を身に付ける上で大きな助けになります。個人的には、TDDをすぐに生産的/励みにさせるのは、この重要なフィードバックループだと思います。

もちろん、コードベースのリファクタリングと変更を開始すると、回帰エラーについても即座にフィードバックが得られます。これはすべてメリットの一部です。

1
ocodo

多くのコーディングプラクティスには...プラクティスが必要です。

  • OOプログラミングの概念を数時間で学び、理解することができます。しかし、多くのプログラマーは、OOプログラミングを約2年間練習した後でないと、認めるでしょう。彼らが突然「流暢」に感じたこと。

  • C++プログラマーは、数日で簡単に「C#を学ぶ」ことができます。しかし、彼らが「流暢」になり、(構文をC#に変換するC++プログラマーではなく)彼らが書いているすべての意味を完全に理解するまでには、まだ多くの使用が必要です。

  • 私はもともと「2本指」でタイプすることを学びました。これは、この方法でかなり速く入力できるところまで進んでいましたが、タッチタイピングを学ぶことにしました。数週間、私はすべてをタイプしなければならないという苦痛と欲求不満を自分自身に強いました本当にゆっくりタッチタイピングを使用しました。入力するすべての行で、私がすでに知っている方法、つまり迅速な結果が得られる方法でそれを打ち破りたかったので、それは困難であり、真のコミットメントが必要でした。しかし、最終的にはタッチタイピングの速度が2本指のタイピングと一致しました。

  • 最初にMFCを使い始めたとき、MFCプレフィックス規則(「m_」や「p」プレフィックスなど)に抵抗しました。それは醜く、ばかげていて、無意味な余分なタイピングのようでした。その後、このシステムを1か月間使用することを余儀なくされましたが、この後、この命名規則なしでコードを記述した方法を理解できませんでした。これにより、コードをよりよく、より速く理解し、ばかげたバグの数を減らすことができました。

では、TDDを行うための規律をどのように開発しますか? 1か月間TDDを行うことに専念してください。遅くなります。大変です。 「昔ながらの方法」で数行を叩きのめしたくなるでしょう。しかし、しばらくすると、経験とスピードが蓄積され、この方法で作業することがはるかに簡単で自然になります。次に、TDDと非TDDを評価し、どちらのアプローチが最適かを判断できます。あなたはおそらく振り返らないでしょう。

1
Jason Williams

TDDは本当に良い習慣です(しかし同時に、100%のコードカバレッジを達成しようとすべきではないと思います)。

その主な利点は次のとおりです。

  1. 開発者は、最初にそのAPIを使用してテストを作成する必要があるため、APIについて考えるようになります。このステップでは、APIに何か問題があると感じるのは非常に簡単です(ほとんどの一般的な操作には多くの行に悪いメソッドの名前が必要です。奇数のチェック例外が多すぎるか、逆にユーザーが推定される例外を処理する可能性がありません)。そして、まだ誰も使っていないので、好きなように改善したり変更したりできます。

  2. あなたはあなたの方法がどのように機能するべきかについて考えます。これにより、初期段階でいくつかの暗黙の問題や誤解が生じることがよくあります。

  3. テストがある場合、完了した作業の割合を測定するための優れた方法があります(つまり、20のテストがあり、そのうちの15が合格した場合、作業の75%が終了します)。チームやプロセスよりも、開発者としての方が重要です。タスク全体を多くの小さなタスク(例:20)に分割するだけで、次々に競争することができます。全部を引き受けるよりずっと楽しいです。

  4. テストを使用すると、コードを試すことができます。リファクタリングを行うことができ、パフォーマンスを向上させることができます。また、とにかくそれを行わなくても、それを行う可能性があることを理解することは非常に素晴らしいことです。すべてが順調であるというのはちょっと自信です。

TDDを自分でやらせる方法は?あなたは必要ありません!記載されているすべてのメリットを享受したい場合は、自分自身を作ることはできません。TDDを喜んで、自由意志で行うだけです。それらを取得する必要がない/欲しい/できない場合は、今は実行しないでください。

1
Roman

TDDは、最初にテストを作成することではありません。最初にテストを作成するだけの場合は、テストファーストテクニックが必要です。問題は、真空(TDDなし)でのテストファースト手法が、テストをまったく行わない場合よりもほとんど悪いものに崩壊してしまうことです。

あなたはあなたの問題が何であったかを言いましたあなた自身

またはプロジェクトの過程で、コードをより早く完成させるためにTDDが忘れられている

それでも、TDDを実行していて、TDDが提供するすべての価値を認識している場合、チームは、コードをより速く実行することは不可能であることを理解しますなしTDDは、そもそもプログラミングのプロセスを高速化するものです。

私の提案は、goodテストで置き換えることができるアーティファクトの種類を認識することによって、それが与えることができる値を理解するために時間を費やすことです。真のTDDを使用すると、1つのドキュメントで次のすべての役割/ニーズが満たされます。

  1. テスト(これは機能しますか?)
  2. 分析(私たちは何を達成しようとしていますか?)
  3. デザイン(どのようにそれを達成するつもりですか?)
  4. 仕様(完了したことをどのようにして知ることができますか?)
  5. フィニッシュライン(ねえ、完了です!)
  6. 進捗レポート(ねえ、まだ終わった?)
  7. プロセス制御(次に何をしますか?)

...など。難しい分野であり、習得するには多くの練習が必要なTDDの学習に取り組むには、トレイルの終わりにある本当の賞を明確に理解する必要があると私は考えています。

これらのことをはっきりと頭に入れたら、TDDを行う方法について心配し始めることができます。

1
MaxGuernseyIII

私のチームは、TDDアプローチに従うことを上手にしようとしています。これは、大規模な開発チームにとって最も簡単なことではないと言わざるを得ません。

チームの全員が、製品コードを作成する前に、テストファーストの帽子をかぶって考える必要があります。これは難しい場合があります。人々がそうすると言うかもしれませんが、キーボードに到達した後の保証はありません。

一部のマネージャーにとって、TDDは何かをコーディングするのに少し時間がかかると思うので(そしてそれはBeanカウンターが見るものです)、高価なアプローチであるように見えるかもしれませんが、それは長期的な利益のための短期的な「苦痛」です。これで、(うまくいけば)十分に記述された実証済みのコードが作成され、将来、状況が変化したときにエラーを検出するメカニズムが導入されます。

確信が持てない人のために、例としてTDDを読んで、ソフトウェアのイテレーションを試してみてください。

0
Michael

TDDを開始するのは非常に困難であり、チームの他の人がTDDにリップサービスを支払っているだけの場合はほとんど不可能です。私のアドバイスは、自分でプログラムすることも、熱心な友人や同僚と一緒にプログラムすることもできる場所(仕事の内外)を見つけて、例外なく常にそれを開始することです。

TDD(そしてそのことについてはアジャイル)は、あなたとあなたのチームがすべてその背後にいて、それを機能させることにコミットしたときにのみクリックを開始します。あなたはあなたのベルトの下でいくつかのTDDの勝利を得る必要があります、そしてそれはあなたの信者を作ります。その後、他のプロジェクトに戻って、そのチャンピオンになりましょう。ただし、これらの重要な初期の勝利を得ることができる場所から始めてください。それはすべての違いを生みます。

0
Micah Hainline