チームをTDDに変換した後、可能な限りすべてのテストケースを作成して、完全なカバレッジを達成することをお勧めしますか?


17

ユニット/機能テストなしの大規模なエンタープライズレベルのアプリケーションがあるとします。非常に厳しい締め切りのために、開発中にテスト駆動型の開発プロセスはありませんでした(わからない場合、締め切りを約束するべきではありませんが、何が行われたかはわかりません!)

すべての期限が過ぎ、物事が落ち着いたので、誰もが生産的なTDD / BDDベースのチームに私たちを変えることに同意しました。

問題は、すでにあるコードについてです:(1)すべてが完全に正常に動作していても、ほとんどの開発を停止し、最初から可能なテストケース全体を書き始めることはまだ大丈夫ですか? ?または、(2)何か悪いことが起こるのを待ってから、修正中に新しい単体テストを作成するか、(3)以前のコードを忘れて、新しいコードのみの単体テストを作成し、次の主要なリファクタリングにすべてを延期する方がよいでしょう。

このようないくつかの良い関連記事があります。私たちには非常に限られた時間しかなく、他の多くのプロジェクト/作品が私たちを待っているので、これに投資する価値があるかどうかはまだわかりません。

:この質問は、開発チームの完全に厄介な状況を説明/想像しています。これは私や同僚のことではありません。それは単なる想像上の状況です。これは絶対に起こらないか、開発マネージャーがそのような混乱に責任があると思うかもしれません!しかし、とにかく、行われたことが行われます。可能であれば、これは絶対に起こらないと思われるからといって、投票しないでください。



6
次回の締め切りに備えて、おそらくTDDを行うことはできません。おそらく技術的な負債開発の最後のラウンドを運転した人に、なぜそれが素晴らしいアイデアではなかったのかを伝えることによって。
jonrsharpe

1
@gnat重複した質問ではないと思います。言及されたチームには、いかなる種類のテストもありません(統合テストもありません)
ミシェルゴカン

1
@gnatの質問:新しいユニットテストはどうなりますか?以前に記述されたコードのすべての単体テストを記述することなく、それらは不完全であるか、価値がないように見えるかもしれません。あなたが言及する質問は、この特定の懸念をカバーしていません。
ミシェルゴカン

1
考えられるすべてのテストケースを記述することはできません。関心のあるすべてのテストケースを書くことだけが役立ちます。たとえば、int値を受け入れて特定の値を返す関数が必要なint場合、可能な値すべてに対して単体テストを作成することはできませんが、おそらく、いくつかの有用な値をテストして、負の数(を含むminint)、ゼロなどのコードmaxintを使用して、一部のエッジケースがカバーされるようにします。
クリストファーシュルツ

回答:


36

期限が非常に厳しいため、開発中にテスト駆動の開発プロセスはありませんでした

この声明は非常に重要です。TDDを使用せずに開発したことや、すべてをテストしているわけではないからです。これは、TDDによって速度が低下し、締め切りに間に合わないことを示しているためです。

このように見れば、TDDの準備ができていません。TDDは徐々に使いこなせるものではありません。あなたはそれを行う方法を知っているか、知らないかのどちらかです。途中でやろうとすると、あなたはそれを作り、自分自身を悪く見せます。

TDDは、最初に自宅で練習する必要があるものです。それが役立ちますので、それを行うことを学ぶあなたがコーディングになりました。誰かがそれをするように言ったからではありません。後で変更するときに役立つからではありません。あなたが急いでいるからそれがあなたがすることになるとき、あなたはそれを専門的にする準備ができています。

TDDは、どのショップでできることです。テストコードを提出する必要さえありません。他の人がテストを軽disする場合、あなたはそれを自分自身に保つことができます。正しく実行すると、誰もテストを実行していなくても、テストによって開発が加速されます。

一方、他の人がテストを気に入って実行している場合でも、TDDショップでテストをチェックインするのはあなたの仕事ではないことに注意してください。実績のある実動コードを作成することです。それがたまたまテスト可能である場合、きちんと。

管理者がTDDを信じる必要がある、または同僚のコーダーがテストをサポートする必要があると考えている場合、TDDが行う最善のことを無視しています。コードが行うことと実際に行うことの違いをすぐに示します。

それだけでは、締め切りに間に合わせるのにどのように役立つかがわからない場合は、TDDを仕事で使う準備ができていません。家で練習する必要があります。

とはいえ、チームがテストを使用して本番コードを読み取れるようにしたり、管理者が新しいTDDツールを購入したりするのは素晴らしいことです。

チームをTDDに変換した後、考えられるすべてのテストケースを作成することをお勧めしますか?

チームが何をしているかに関係なく、可能なすべてのテストケースを作成することは常に良い考えとは限りません。最も有用なテストケースを作成します。100%のコードカバレッジにはコストがかかります。判断を下すのが難しいからといって、収益の減少の法則を無視しないでください。

興味深いビジネスロジックのためにテストのエネルギーを節約します。決定を下し、ポリシーを実施するもの。その全体をテストします。物をつなぎ合わせるだけのわかりやすい構造接着コードを退屈にすることは、テストをそれほどひどくする必要はありません。

(1)すべてが完全に正常に動作している場合でも(まだ!)、開発の大部分を停止し、最初から可能なテストケース全体を書き始めることは、まだ大丈夫ですか?または

いいえ。これは「完全に書き直そう」という考え方です。これは苦労して得た知識を破壊します。テストを書く時間を経営者に尋ねないでください。テストを書くだけです。何をしているかがわかれば、テストによって速度が低下することはありません。

(2)何か悪いことが起こるのを待ってから、修正中に新しい単体テストを作成するか、または

(3)以前のコードを忘れて、新しいコードのみの単体テストを記述し、すべてを次の主要なリファクタリングに延期します。

2と3も同じように答えます。何らかの理由でコードを変更する場合、テストに参加できると本当に便利です。コードがレガシーである場合、現在のところテストを歓迎していません。つまり、変更する前にテストすることは困難です。とにかく変更しているので、テスト可能なものに変更してテストできます。

それが核の選択肢です。危険です。テストなしで変更を行っています。変更する前にレガシーコードをテストするいくつかの創造的なトリックがあります。コードを変更せずにコードの動作を変更できるシームと呼ばれるものを探します。構成ファイル、ビルドファイルなど、必要なものを変更します。

マイケル・フェザーズは、これについての本を提供しました:Legacy Codeで効果的に働く。読んでみると、古いものをすべて焼き付けて新しいものを作成する必要がないことがわかります。


37
「誰もテストを実行していなくても、テストによって開発が加速されます。」-私はこれが明らかに間違っていると思います。これはおそらくこれについて議論を始める場所ではありませんが、読者はここで提示される視点が全会一致ではないことを心に留めておく必要があります。
マーティンBa

4
実際、多くの場合、テストは長期的に開発を向上させ、TDDが本当に効率的であるためには、誰もがそれを信じる必要があります。
hspandher

13
「TDDはあなたを遅くし、締め切りに間に合わないだろうと思います。」私はおそらくと思っている場合。TDDを使用する人は誰もいません。TDDを使用すると、最初の期限をより早く満たすことが期待されるためです。(少なくとも私の推定では)本当の利点は、将来のプレイをテストし、回帰をキャッチし、安全な実験に対する信頼を構築するための継続的な配当です。このメリットはテストを書くための初期費用を上回り、ほとんどの人が同意するだろうと思いますが、厳しい締め切りに間に合わせる必要がある場合は、選択の余地はありません。
アレクサンダー-モニカの復活

1
家を買うのに似ています。家を返済するための一時金があれば、利子を大幅に節約でき、長期的には素晴らしいでしょう。あなたはすぐに家を必要とする場合でも...その後、あなたは、長期的な次善のだ短期的アプローチ取ることを余儀なくしている
元に戻すモニカ-アレクサンダー

3
TDD = can =テストとコードが並行して開発される場合、パフォーマンスが向上しますが、開発者は機能が新鮮です。コードレビューは、他の人間がコードが正しいと考えているかどうかを教えてくれます。テストケースは、テストケースで具体化された仕様が実装されているかどうかを示します。そうでなければ、そうです、特に機能仕様がなく、テスト作成者もリバースエンジニアリングを行っている場合は、TDDがドラッグになる可能性があります。
オースティンのジュリー

22

開発の大部分を停止し、最初からすべての可能なテストケースの作成を開始することは、まだ大丈夫ですか?

レガシー1コードを前提として、次の状況で単体テストを作成します。

  • バグを修正するとき
  • リファクタリングするとき
  • 既存のコードに新しい機能を追加するとき

単体テストと同じくらい便利ですが、既存の1コードベースの完全な単体テストスイートを作成することは、おそらく現実的な考えではありません。権力はあなたに厳しい締め切りを果たすように押しやった。開発中に適切な単体テストを作成する時間はありませんでした。「動作するプログラム」のテストを作成するのに十分な時間を与えると思いますか?

1 レガシーコードは、単体テストのないコードです。これは、レガシーコードのTDD定義です。レガシーコードが新たに配信された場合でも(インクがまだ乾燥していない場合でも)適用されます。


ただし、新しい機能の新しい単体テストは、不完全であるか、単体テストが欠落していても価値がないように見える場合があります。そうじゃない?
ミシェルゴカン

7
(1)価値がない?確かにそうではありません。少なくとも、彼らは新しい機能をテストします。次に誰かがこの機能を変更したい場合、既存のテストの多くを再利用します。(2)不完全ですか?多分そうでないかもしれません。新しい機能が依存するレガシー機能をテストする単体テストも作成する場合、テストは実用的な目的のために十分に完了する可能性があります。言い換えると、レガシー機能を貫通する追加のユニットテストを作成します。どの深さまで浸透しますか?それは、プログラムのアーキテクチャ、利用可能なリソース、制度的サポートに依存します。
ニックアレキ

「テストが必要になったときにテストを書く」ことのマイナス面は、さまざまな開発者がさまざまなアイデアで書いたテストのパッチワークになるリスクが高くなることです。私はこの答えが間違っていると言っているわけではありませんが、テストの質とスタイルを均一に保つしっかりした手を必要とします。
フラット

4
@Flaterの均一性は、誤った快適さを提供します。実動コードを読みやすくするテストが必要です。すべてが同じように見えるテストではありません。本番コードが何をするのかを理解しやすくする場合、まったく異なるテストフレームワークを混在させることは許します。
candied_orange

2
@Flater productionい製品コードについては断言しませんでした。テストのポイントは、量産コードを読みやすくすることだと断言します。本番コードを読みやすくするさまざまなテスト群を喜んで受け入れます。均一性自体を目標にすることに注意してください。読みやすさが重要です。
candied_orange

12

私の経験では、テストが役立つために完全なカバレッジを必要としません。代わりに、カバレッジが増加するにつれて、さまざまな種類のメリットを享受し始めます。

  • 30%を超えるカバレッジ(2、3の統合テスト):テストが失敗した場合、何かが非常に壊れています(またはテストが不安定です)。ありがたいことに、テストはすぐに警告しました!ただし、リリースには依然として広範な手動テストが必要です。
  • 90%以上のカバレッジ(ほとんどのコンポーネントには表面的な単体テストがあります):テストに合格した場合、ソフトウェアはほとんど問題ありません。テストされていない部分はエッジケースであり、重要でないソフトウェアには適しています。しかし、リリースにはまだいくつかの手動テストが必要です。
  • 機能/ステートメント/ブランチ/要件の非常に高いカバレッジ:あなたはTDD / BDDの夢を生きており、テストはソフトウェアの機能を正確に反映しています。大規模なアーキテクチャの変更など、高い信頼性でリファクタリングできます。テストに合格すると、ソフトウェアはほぼリリース準備完了です。手動での煙テストのみが必要です。

真実は、BDDから始めないと、そこにたどり着くことはありません。なぜなら、コーディング後にテストするのに必要な作業が多すぎるからです。問題はテストを書くことではなく、実際の要件を(偶発的な実装の詳細ではなく)認識し、機能的でテストしやすい方法でソフトウェアを設計できることです。最初に、またはコードと一緒にテストを記述する場合、これは実質的に無料です。

新機能にはテストが必要ですが、テストには設計の変更が必要ですが、リファクタリングにもテストが必要なので、鶏と卵の問題が少しあります。ソフトウェアが適切なカバレッジに近づくにつれて、新しい機能をテスト可能にするために、新しい機能が発生するコードの部分で慎重にリファクタリングを行う必要があります。これにより、最初はかなり遅くなります。しかし、新しい開発が必要な部分のみをリファクタリングおよびテストすることにより、テストは、それらが最も必要とされる領域にも焦点を合わせます。安定したコードはテストなしで続行できます。バグがある場合は、とにかく変更する必要があります。

TDDに適応しようとすると、プロジェクト全体のカバレッジよりも優れたメトリックは、変更される部分のテストカバレッジになります。このカバレッジは最初から非常に高いはずですが、リファクタリングの影響を受けるコードのすべての部分をテストすることは不可能です。また、テスト対象コンポーネント内での高いテストカバレッジの利点のほとんどを享受できます。それは完璧ではありませんが、それでもかなり良いです。

単体テストは一般的であるように見えますが、最小のピースから開始することは、レガシーソフトウェアをテストするのに適した戦略ではないことに注意してください。ソフトウェアの大部分を一度に実行する統合テストから始めます。

例えば、実世界のログファイルから統合テストケースを抽出することが有用だとわかりました。もちろん、このようなテストの実行には時間がかかるため、テストを定期的に実行する自動サーバー(たとえば、コミットによってトリガーされるJenkinsサーバー)をセットアップする必要があります。このようなサーバーのセットアップと保守のコストは、テストの失敗が実際に迅速に修正される場合、テストを定期的に実行しないのに比べて非常に小さくなります。


「カバレッジの90%以上(ほとんどのコンポーネントには表面的な単体テストがあります):テストに合格した場合、ソフトウェアはほとんど問題ありませんテストされていない部分はエッジケースであり、重要ではないソフトウェアに適しています。」FWIW、これは少し奇妙に思えますが、予想されるパスの動作のみで構成される90%のカバレッジよりも、主にエッジケースで構成される30%のカバレッジを希望します(手動テスターに​​とっては簡単です)。テストを作成し、可能な場合は手動で検出された(異常な)テストケースに基づいてテストを作成するときに、「箱の外」を考えることをお勧めします。
jrh

5

既存のコードのテストを作成しないでください。それはそれだけの価値はありません。

あなたが作ったものは、完全に非公式な方法ですでにある程度テストされています-あなたは絶えず手でそれを試しました、人々はいくつかの非自動化されたテストをしました、それは現在使用されています。つまり、多くのバグは見つかりません

残っているのは、あなたが考えていなかったバグです。しかし、これらはどちらもユニットテストを書くとは思わないので、おそらくあなたはまだそれらを見つけられないでしょう。

また、TDDを使用する理由は、コードを記述する前に、少しのコードの正確な要件を把握するためです。さまざまな方法で、あなたはすでにそれをしました。

それまでの間、これらのテストを作成するのは、事前に作成するのと同じくらい多くの作業です。それは多くの時間を費やしますが、ほとんど利益はありません。

そして、間にコーディングをせずにバグをほとんど見つけずにたくさんのテストを書くのは非常に退屈です。あなたがこれを始めたら、TDDを初めて使う人それを嫌います。

要するに、開発者はそれを嫌い、管理者はそれを高価だと見なしますが、多くのバグは見つかりません。実際のTDDパートに到達することはありません。

プロセスの通常の部分として、変更したいものに使用します。


1
「既存のコードのテストを書かないでください。それは価値がありません。」に強く反対します。コードが適切に機能している場合、存在する仕様はテストのみである可能性があります。また、コードがメンテナンス中の場合、テストを追加することは、一見無関係な変更によって機能する機能が破損しないことを確認する唯一の方法です。
オースティンのジュリー

3
@JulieinAustin:一方、仕様がなければ、コードが何をすべきかを正確に知りません。そして、コードが何をすべきかをまだ知らない場合は、役に立たないテストを書くか、さらに悪いことに、仕様を微妙に変更する誤解を招くテストを書くかもしれません。
cHao

2

テストは、理解を伝える手段です。

したがって、理解すべきことのテストのみを作成してください。

あなたがそれを使って作業するとき、何が真実であるべきかを理解することができます。

したがって、作業しているコードのテストのみを記述してください。

コードを操作すると、学習できます。

したがって、学習した内容をキャプチャするためのテストを作成および書き換えます。

すすぎ、繰り返します。

テストでコードカバレッジツールを実行し、カバレッジを低下させないメインラインへのコミットのみを受け入れます。最終的には、高レベルのカバレッジに到達します。

しばらくコードを操作していない場合は、ビジネス上の決定を下す必要があります。おそらく非常に古いものなので、チームの誰もそれを操作する方法を知りません。おそらく古くなったライブラリ/コンパイラ/ドキュメントがあり、それはほぼすべての点で大きな責任です。

2つのオプション:

  1. 時間をかけて読んで、それから学び、テストを書き、リファクタリングします。頻繁にリリースされる小さな変更セット。
  2. そのソフトウェアを捨てる方法を見つけてください。とにかく頼まれた場合、おそらくそれを変更することができませんでした。

0

(1)すべてが完全に正常に動作している場合でも(まだ!)、開発の大部分を停止し、最初から可能なテストケース全体を書き始めることは、まだ大丈夫ですか?
(2)何か悪いことが起こるのを待ってから、修正中に新しい単体テストを書く方が良い

テストの主な目的の1つは、変更によって何も破壊されないことを確認することです。これは3段階のプロセスです。

  1. テストが成功することを確認します
  2. 変更を加える
  3. テストがまだ成功していることを確認します

これは、実際に何かを変更するに、作業テストが必要であることを意味します。2番目のパスを選択すると、コードに触れる前に開発者にテストを書かせる必要があります。そして、現実世界の変化にすでに直面しているとき、開発者はユニットテストに彼らがふさわしい注意を払うつもりはないことを強く疑います。

そのため、開発者が一方の品質を犠牲にすることを避けるために、テスト作成と変更を行うタスクを分割することをお勧めします。

すべてが完全に正常に動作していても(まだ!)

これを具体的に指摘するだけで、コードが機能していない場合にのみテストが必要であるという一般的な誤解です。コードが機能しているときにテストを行う必要があります。たとえば、[新しく発生したバグ]がテストに合格しているためにあなたの一部ではないことを誰かに証明する場合などです。
すべてが以前同じように機能することを確認することは、コードが動作しているときにテストが不要であることを意味する場合は省略しているテストの重要な利点です。

(3)以前のコードを忘れて、新しいコードのみの単体テストを記述し、すべてを次の主要なリファクタリングに延期する

理想的には、既存のソースコードのすべてが単体テストを取得するようになります。ただし、そのために必要な時間と労力(およびコスト)は、特定のプロジェクトにはまったく関係がないという合理的な議論があります。
たとえば、もはや開発されておらず、今後変更される予定のないアプリケーション(たとえば、クライアントがそれを使用しなくなった、またはクライアントがクライアントではなくなった)は、このコードをテストすることはもう関係ないと主張できます。 。

ただし、線を引く場所ほど明確ではありません。これは、企業が費用便益分析で検討する必要があるものです。テストの作成には時間と労力がかかりますが、そのアプリケーションの将来の開発を期待していますか?単体テストを作成することのメリットは、単体テストを作成するコストを上回りますか?

これは、(開発者として)あなたが下せる決定ではありません。せいぜい、与えられたプロジェクトにテストを実装するために必要な時間の見積もりを提供することができ、実際にプロジェクトを維持/開発する必要があるという十分な期待があるかどうかを決定するのは管理者次第です。

すべてを次の主要なリファクタリングに延期します

次の主要なリファクタリングが指定されている場合、実際にテストを記述する必要があります。

ただし、大きな変更に直面するまで延期しないでください。私の最初のポイント(テストの書き込みを組み合わせ、コードを更新していない)はまだ立って、私はここでは第二の点を追加したい:あなたの開発者は現在、彼らは6ヶ月で、彼らはその時間の作業を過ごすことになります場合よりも優れたプロジェクトの周りに彼らの方法を知っています他のプロジェクトで。開発者がすでにウォームアップされている期間を利用し、将来的に物事が再びどのように機能するかを把握する必要はありません。


0

私の2セント:

システムの主要な技術的なアップグレードを待ってから、テストを作成します...正式にビジネスのサポートを受けます。

あるいは、あなたがSCRUMショップであり、ワークロードが容量で表されているとしましょう。ユニットテストにその割合を割り当てることができますが、...

あなたが戻ってテストを書くと言うのは単純です、あなたが本当にやろうとしているのは、リファクタリングがコードをよりテスト可能にした後にテストを書き、リファクタリングし、より多くのテストを書くことです、それが開始するのが最善の理由ですあなたがすでに知っているテストで、そして...

元の作者が以前に書いたコードのテストを作成し、リファクタリングするのが最善です。理想的ではありませんが、経験からリファクタリングでコードをより良く、より良くしたいです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.