web-dev-qa-db-ja.com

TDDは理論上のみ

1年ちょっと前、私は幸運にも仕事から9か月の休憩を取ることができました。その時に、C#のスキルを磨くことにしました。私はたくさんのプロジェクトに取り組み始め、TDDに従うことを自分に強いました。

それはかなり啓蒙的なプロセスでした。

最初は大変でしたが、やがてテスト可能なコードを書く方法を学びました(結局のところ、これはより多くのSOLIDコード)になる傾向があります)。その過程で私の= OOデザインスキル。

今、私は労働力に戻っており、奇妙なことに気づいています。

私はTDDに従わないことを好みます。

TDDを使用すると動作が遅くなり、実際にはクリーンなアプリケーションの設計が難しくなります。

代わりに、少し(大規模に)異なるアプローチを採用しました。

  1. 仕事の垂直スライスを選ぶ
  2. 機能するプロトタイプを開発する
  3. すべてがうまく整頓されるまでリファクタリングする
  4. 美しくSOLIDおよび私が書いたテスト可能なコードに感謝してください。

ステップ1が「私のテストターゲットのパブリックサーフェスを定義する」のではなく、ステップ2が「そのパブリックサーフェスからベジェサスをテストする」のではないことに気づいたかもしれません。また、ステップにテストが含まれていないことに気づいたかもしれません。私はテスト可能なコードを書いていますが、テストはしていません...まだです。

ここで、私が実際にどのような種類のテストにも先行していないことを明確にしたいと思います。私が書いているコードは機能します。手動でテストしているので機能します。

また、すべての自動テストの前に立つわけではないことも明確にしたいと思います。これが私のプロセスが異なるところです。そして、これが私がこの質問をしている理由です。

理論的にはTDD。実際にはありません。

私のプロセスは少し進化し、TDDと非常に生産的であり、安全であると私が思うテストがないことのバランスをとっています。それは次のようになります:

  1. テストを念頭に置いて作業の垂直方向のスライスを実装しますが、テストは記述しないでください。
  2. 今後(たとえば1か月後)、そのスライスを変更する必要がある場合。
    1. 一連の作業が正しいことを保証する単体テスト、統合テスト、動作テストなどを作成する
    2. コードを変更する
  3. そのスライスを変更する必要がない場合は、
    1. 何もしない

テストを書く負担を前のwriteから前のmodifyingコードはるかに機能するコードを生成することができました。また、テストの作成に取り掛かると、テストの作成ははるかに少なくなりますが、ほぼ同じ範囲(高いROI)をカバーします。

私はこのプロセスが好きですが、うまくスケーリングできないのではないかと心配しています。その成功は、開発者が物事を変える前にテストを書くことに熱心であることにかかっています。そして、それはかなり大きなリスクのようです。ただし、TDDには同じリスクがあります。

それで、私は[BT] DD地獄に行くのですか、それとも実用的なコーディングとテストの一般的な形式ですか?

この方法で作業を続けたいと思います。このプロセスを長期的に機能させるにはどうすればよいですか?

私は自分のプロジェクトの唯一の開発者であり、要件の収集、設計、アーキテクチャ、テスト、展開など、すべてに対して責任があります。これが私のプロセスが機能している理由だと思います。

29
MetaFight

プロセスを長期的に機能させるために、コードの作成時にテストを作成します。

これはあなたのアプローチと矛盾するように見えるかもしれません。しかし、あなたが質問を投げかけたので、私はあなたに私の見解を与えます:

コードの前にテストを記述する必要はありません。その純粋さを忘れてください。しかし、あなたはテストを書きたいaroundその時。
コードが機能するようになったら、少し微調整し、いくつかのバグを解消しました(ここでは時間のタイムスケールについて話しています)。コードがやっています。これは、知識を取り込むテストを作成する絶好の機会です。

これを後回しにすることは、知識が(自然に)時間とともに減少することを意味します。

それはまた、あなたがこれから去り、他の誰かがあなたを引き継いだとしても、何が何をするかを(テストを通じて)文書化していないという当面の技術的責任がないということも意味します。

何より「いつか」は来ないかもしれません。あなたはバスにぶつかるか、新しい冒険のためにバスに乗るかもしれません。

最後に、手動テストは拡張できず、エンドユーザーが使用するすべてのデバイスを網羅していないことがよくあります。

6
Michael Durrant

TDDは100%を実装するのは難しいですが、アプローチに欠陥があります

  1. 作業の垂直方向のスライスを実装する

    1.1 1年経過...

    1.2新しい開発者がプロ​​ジェクトの作業を開始します

  2. そのスライスに変更が必要な場合

    2.3「クリーンコーディング」スタイルのメソッド名とパラメータ「GetUnicorn(colourOfUnicorn)」を解析する

    2.4 XMLコメント「Gets A Gold Unicorn(for Riding)(obvs)」を読む

    2.5元の開発者を追い詰める

    2.6コードが何をすることになっているのか覚えておいてほしい

    2.7すべて説明してもらう

  3. 単体テスト、統合テスト、動作テストなどを記述しますうまくいけば作業のスライスが正しいことを保証します

  4. コードを変更する

変更が必要なときに単体テストが実際にその価値を示すことを確認するのは正しいと思います。

9
Ewan

Daniel HollinrakeとEwanの両方に同意します。テストのみの場合、変更のみがこれまでうまく機能する最初の重要な点は次のとおりです。

I am the sole developer on my projects and I am responsible for everything

そして、2番目の重要なポイントは次のとおりです。

you're producing Nice clean code

TDDが単一のプログラマーに大きな生産性の向上をもたらすとは思いません。すでに優れたクリーンなコードを作成している場合は、コードの品質を大幅に向上させることはできません。

ただし、TDDは確実に、貧しい/経験の浅い/時代遅れのプログラマーのコードの品質を確実に向上させます。さらに、コードを変更する人が最初にコードを書いた人と同じでない場合、または数か月が経過した場合はなおさらです。

言い換えれば、TDDは、コードの品質を向上させるための優れた方法(自分自身を認める)であると同時に、平均的または平凡なプログラマ(たとえば、部署または別の会社)。これは、単独で作業するよりもはるかに一般的な状況です。

4
sergut

ユニットテストは、コードを維持する問題に取り組むことです。 TDDを使用せずにコードを作成する方が速いと言う人もいますが、テストを作成せずに新しいコードを作成できることは驚くことではありません。

あなたがそれを変更する直前にテストを書く練習で私が見ることができる問題:

急いで変更する必要があることが多い

必要なときにテストを書くだけで全体的に時間を節約できるかもしれませんが、すべての時間が等しいわけではありません。テストを書いて2時間費やして、私が危機的状況にあるときに1時間節約する-それだけの価値があります。

コードを書くのと同時にテストを書く方が簡単です

単体テストを適切に作成するには、テストしているコードを理解する必要があります。私はよく理解の練習として単体テストを使用しますが、既存のコードの理解には時間がかかるため、既存のコードの単体テストには時間がかかる場合があります。コードを書くときにテストを書くのとは対照的です。すでにコードを理解しているので、コードを書いただけなので、はるかに速く見つけることができます。


Michael Feathersによるレガシーコードの定義は、テストのないコードです。あなたが彼の定義に同意するかどうかに関係なく、既存のコードを変更するコストのかなりの部分は、それが期待どおりに機能することを確実にすることであり、多くの場合、期待される動作が何であるかさえ明確ではありません。

ユニットテストを作成すると、正しい動作が何であるかについての理解をエンコードすることにより、そのコストが相殺されます。

3
Justin

私にとって重要なことはこれであると思われます:

私は自分のプロジェクトの唯一の開発者であり、要件の収集、設計、アーキテクチャ、テスト、展開など、すべてに対して責任があります。これが私のプロセスが機能している理由だと思います。

これはあなたのために機能し、あなたは素晴らしいクリーンコードを生成しています(私は仮定します!)私があなたがしなければならない唯一のことは、他の開発者がやって来て変更を加えることに自信を持つことができるようにテストハーネスを作成することです。また、テストハーネスは、コードの動作の一貫性を保証します。

あなたのアプローチは私のものに似ていると思います。私は通常、プロジェクトの唯一の開発者です。 TDDを理解することで、より小さな関数とよりクリーンなコードを記述できるようになりましたが、コードをテストハーネスとして記述しながら、テストを追加しています。そうすることで、コードが進化して機能が変更されるので、変更を加えることにある程度の自信を持つことができます。

テストを作成するもう1つの理由は、テストは一種のドキュメントだと感じているからです。彼らは、関数が作成された理由の背後にある私の推論を説明できます。しかし、ここでは、振る舞い駆動型開発についてもっと考えています。

3

これは良い質問です。FWIWを2セントで投入します。

約1年前、Salesforceでコーディングをしていました。これは、コーディングする前にテストを書く必要がなく、強制されたメカニズムを備えたプラットフォームでした。一般的にテストを記述します。

それが機能した方法は、システムがテストを書くことを強制し、テストされたコードの行数をパーセンテージで計算することでした。実稼働インスタンス全体のすべてのコードが75%を下回った場合、テスト済みです。Salesforceは機能しません。

その結果、Salesforceで何かをするたびにテストを作成または更新する必要がありました。これはSalesforceの市場シェアに大きな影響を与えると確信していますが、開発者の生活の面ではお尻に大きな苦痛がありました

多くの場合、小さなチケットを通過しようとしただけで、その後テストが行​​われ、開発時間が2倍になります。これは、知っている機能動作します。

次に、TDDの厄介な概念が、私たちのデータベースに至るまで、私たちの部門を席巻しました。私たちのアーキテクトは、IT部門のあらゆる側面に徹底的なテストをプッシュしたいと考えていました。お尻のわずかな痛み、お尻のさらに大きな痛みに会います。

その当時、TDDは私には実際に意味をなさなかったし、今でもまだ意味がありません。私の現在の役割で記述した機能の多くは、先ほどお話ししたのと同様のメカニズムで実行されます。垂直スライスでは、機能するまで調整します。私がその古い役割にあったとき、そして今でも、実際にコードを書くまで、コードが何をするのかわからないことがよくあります。私が書こうとしているコードを実行するためのテストを書くことができるという考えは..私には意味がなく、面倒であり、ほとんどの時間の無駄です。

それはすべて言った、テストは世界のすべてを正しくする素晴らしい魔法のようなものです。彼らはあなたのコードを正しくし、あなたのアプリがあなたが思っていることを実行することを保証し、そして一般的にすべてがよりスムーズになります。問題は、コーディングの前にテストを作成するか、コーディングの後にテストを作成するかではなく、テストにどれだけの時間を費やすかです。それは、少なくとも私のソフトウェア開発の経験では、本当の問題です。テストには時間と費用がかかり、競合する利害の枠組みの中でそれを行わなければなりません。

したがって、一般的に私はあなたに同意します。実際のTDDは少し厄介で扱いにくいものです。その時点で、現在の状況で最も効果的に機能するものを覚えておく必要があります。重要なコードを記述している場合は、一般的にテストされていることを確認してください。時間がある場合は、TDDを試して、プロセスに何か追加されるかどうかを確認してください。

2
Canadian Coder

私はあなたのアプローチをお勧めできませんでした。

私があなたのアプローチを使うならば、それは例えば次のようになります(家はアプリケーションです):

  1. 知識のある煉瓦工として、または初心者として、家族のために家を建て始めます。
  2. 子供部屋、ゲストルームなどの要件を理解し、「プロトタイプ」の家の建設を始めます。
  3. 数回後、「プロトタイプ」の家が完成しました。
  4. 構造が手動で十分に安定しているかどうかを調べ始めます。それで、私はたくさんのウェイトを拾い上げ、それを1階の別の部屋に持ってきます。私が家族と一緒に部屋に座っているときに天井が壊れないことを確認するために。しかし、それは壊れ、リファクタリングを開始します。最初にすべての塊を掃除します。それを新しくビルドして、十分に安定するまで手動でもう一度テストします。
  5. 家族と一緒に引っ越すより。すべて良好。
  6. 後に蛾、私のいとこや両親が私たちを訪ねてきます。しかし、彼らが私たちの家に入る前に、1階の部屋の1つに座ったときに天井が壊れないように、建築家と土木技師に支払う必要があります。
  7. 建築家と土木技師は、最初から何もないため、多くの仕事をしています。だから彼らは私の家に入り、私がそれをどのように建てるかを見る必要がある。
  8. また、安定性も十分ではありません。したがって、彼らは1階の地面をリファクタリングする必要があります。
  9. しかし、その後はすべて順調で、誰もが安全に私の家に入ることができます。

したがって、私があなたのアプローチで家を建てる前に、あなたのアプローチには多くの時間と多くの知識が必要です。それとも時間がかかります!また、要件が変更されたときに、コードの他のテストを他の人に書かせることは、かなり紳士的ではありません。

したがって、「プロトタイプ」をプログラミングせずにリファクタリングを開始するよりも優れたアプローチがあります。プロトタイプをプログラミングする代わりに、次のようにアプリケーションのUMLを使用してデザインを作成します。

  1. UseCaseダイアグラムを作成します。最初に draw.io を使用できます。
  2. UseCasesに基づいてEPKダイアグラムを作成して、動作を決定するよりも。 (アプリケーションの動作)コード化されたプロトタイプをリファクタリングするよりもリファクタリングが高速です。特にあなたが初心者の場合。
  3. クラス図を作成します。 (あなたのアプリケーションの構造)
  4. 動作の実装で問題が発生する可能性のある場所を特定します。
  5. この動作を実装する方法を決定するために、おそらく10行または20行のコードを含む単純なプロトタイプを記述します。初心者に最適です。または、チュートリアルを見て、他のサンプルアプリケーションのソースコードを調べてください。彼らがそれをどのように解決したか。
  6. コーディングを始めるより。 UseCaseの成功したテストを試してください。これはさまざまな方法で行うことができます。最初に、テストに必要なすべての構造とそのUseCaseを作成します。 Enterprise Architekt を使用すると、構造を生成できます。あなたの図に基づいています。または、テストの配線中に構造を作成します。したがって、コンパイルエラーは表示されません。ここで言及しているのは、アプリケーションの動作をテストするだけでよいということです。あなたが持っているユースケース。
  7. UseCaseの動作を実装するよりも。
  8. 成功したUseCasesが開始したら、例外のテストを記述します。そして、テストが有効なときに緑色が表示されると、いつも気持ちがいいです;)
  9. これで完了です。

確かに、このアプローチにはUMLの知識も必要ですが、学ぶのは速いです。また、IDEで行うよりも、クラスの名前を変更したり、図の矢印を移動したりする方が常に高速です。しかし、テストフレームワークの使用法を学ぶことは、最初はより困難になります。オープンソースプロジェクトの実行テストを見て、それらがどのように機能するかを確認するのが最適です。しかし、テスト駆動型アプリケーションを作成すると、次のアプリケーションの方がはるかに高速になります。そして、すべてがうまく機能することを知るのは良い感じだと思います。

それで、私はアプローチが初心者にとって非常に時間がかかり、結局良くないので、私はそれらのアプローチに反対票を投じます。構造と動作の間に明確な境界を設けるには、ドメイン駆動設計を使用して、2つのパッケージ(1つのパッケージは構造という名前のパッケージ、もう1つは動作という名前のパッケージ)でドメインを配置します。あなたのテストにも。簡単な例をチェックしてください Javaで書かれています。

1
Rocks360

私が書いているコードは動作します。手動でテストしているので機能します。

少し変更した後、条件の考えられるすべての分岐を手動でテストしましたか?手動テストのフィードバックループにかかる時間。自動テストで得られるフィードバックループにどれだけ近いか。

自動テスト(テストを優先するかどうかは関係ありません)を使用すると、コードのフィードバックループを高速化することで、テストを高速化できます。

6か月後にいくつかの条件を手動でテストすることを忘れないでください。テストするすべての重要な条件を文書化するとは言わないでください-種類のドキュメント/コメントを書くことは、テスト(実行可能ドキュメント)を書くことと同じです。

  • 仕事の垂直スライスを選ぶ

  • 機能するプロトタイプを開発する

  • すべてがうまく整頓されるまでリファクタリングする

また、リファクタリング中に、リファクタリングの影響を受けるすべてのロジックを手動でテストしましたか?リファクタリングの変更をテストするのにどのくらい時間がかかりますか?コードのリファクタリングが中断した場合、中断の理由を見つけるのにどのくらい時間がかかりますか?

  • 美しくSOLIDと私が書いたテスト可能なコードに感謝します。

あなたが楽しんだ美しくクリーンなコードは非常に主観的です。あなたのコードはあなたのためにきれいで合理的でありえます。コードが本当に読みやすく、理解しやすく、テスト可能かどうかを確認する最良の方法は、他の開発者が作成したテストとコードレビューです。

あなたはコードを扱う開発者だけであるという理由だけで、そして私が思うに、あなたはこのプロジェクトで作業を始めただけなので、非常に生産的な方法を見つけました(このプロジェクトで何歳ですか?6-8か月?)。
あなたはまだあなたが書いたすべてを覚えていて、起こりうる問題の理由を認識することができます。プロジェクトの2〜3年後からテストを書き始めると思います。何かを忘れないようにしたいからです。

1
Fabio

あなたが間違いを犯さないなら、あなたは本当にテストを必要としません。ほとんどの開発者は間違いを犯しますが、間違いがなく、将来間違いを犯すことがないと確信している場合(そしてプロジェクトで唯一のミスである場合)、テストの作成に時間を費やす理由はありません。

しかし、コードを変更するときにテストを書くことを提案しているため、ソリューションは中途半端ですが、同時に、メソッドは、コードのどの部分をテストするかを決定するときに間違いを犯さないことを前提としています。これは、変更が影響する可能性のある領域を常に完全に理解している場合にのみ機能します。多くの一般的な開発者(もちろんあなたではありません!)が変更を加えた経験があると思いますが、間違いを犯したため、予期しない場所でテストが失敗します。

もちろん、優れたアーキテクチャ、SOLID原則などはこれを防止するはずですが、ほとんどの開発者は完璧ではありません。そのため、システム全体のテストが重要です。

0
JacquesB