ユニットテストを追加することは、よく知られているレガシーコードにとって意味がありますか?


21
  • 私はTDDの意味でのユニットテストについて話している。(自動化された「統合」ではなく、テストと呼ぶのが好きです。)
  • レガシーコード:(C ++)テストなしのコード。(参照:マイケルフェザーズのレガシーコードでの効果的な作業
  • しかし、次のようなレガシーコード:私たちのチームが過去10〜5年間作業してきたコードです。そのため、何かを変更するためにどこに置くべきかについて非常によく考えています。
  • 私たちは何のために(Boost.Test経由)の場所でのユニットテスト持ち、いくつかの後に来たか、ユニットテストのための「自然な」フィットされているモジュール(一般的なアプリの特定のコンテナ、文字列のもの、ネットワークヘルパーなど)
  • 適切な自動受け入れテストはまだありません。

さて、最近、3つの新しいユーザー向け機能を実装する「喜び」がありました。

それらのそれぞれは、私が変更するのに必要なコード部分に慣れるのに約1〜2時間、変更するのに必要な(小さな)コードを実装するのに1〜2時間、そしてアプリを確認するのにさらに1〜2時間かかりましたその後正しく実行され、実行するはずでした。

今、私は本当に小さなコードを追加しました。(各機能に対して1つのメソッドといくつかの呼び出し行があると思います。)

このコードを(WEwLCで提案されている方法のいずれかを介して)除外するので、単体テストが理にかなっている(完全なトートロジーではない)ため、さらに2〜4時間は簡単にかかっていました。これにより、各機能に50%〜100%の時間が追加され、すぐにメリットは得られません。

  1. コードについて何かを理解するのに単体テストは必要ありませんでした
  2. コードがアプリの他の部分に正しく統合されているかどうかをテストする必要があるため、手動テストは同じ量の作業です。

確かに、あれば、後に、「誰かが」に沿って来て、そのコードに触れ、彼は理論的には、そのユニットテストからいくつかの利点を持つことができます。(テストされたコードの島はテストされていないコードの海に住んでいるので、理論的にのみ。)

したがって、「今回」は、ユニットテストを追加するというハードワークを行わないことを選択しました。テスト対象のものを取得するためのコード変更は、機能を正しく(そしてクリーンに)実装するためのコード変更よりもはるかに複雑でした

これは、強く結合されたレガシーコードの典型的なものですか?私は怠け者ですか/チームとして間違った優先順位を設定していますか?または、オーバーヘッドが高すぎないものだけをテストするのが賢明ですか?


他の部門が「よく知られているレガシーコード」を引き継ぐとしたらどうでしょうか。そこの人はそれで何をしますか?
アレックス

回答:


18

あなたはこれらの状況について実用的でなければなりません。すべてにビジネス価値がなければなりませんが、ビジネスは技術的な仕事の価値を判断するためにあなたを信頼しなければなりません。はい、ユニットテストを行うことには常に利点がありますが、その利点は費やした時間を正当化するのに十分なものですか?

私は常に新しいコードについて議論しますが、レガシーコードについては、判断を下す必要があります。

このコード領域に頻繁にいますか?その後、継続的な改善のケースがあります。大きな変更を行っていますか?次に、すでに新しいコードである場合があります。しかし、おそらく1年も変わらないような複雑な領域で1行のコードを作成する場合、もちろんリエンジニアリングのコスト(リスクは言うまでもなく)は大きすぎます。そこにコードを1行入力するだけで、すぐにシャワーを浴びます。

経験則:常に自分自身に考えてください、「ビジネスは、結果として遅れる予定の仕事よりも、私がやるべきだと思うこの技術的な仕事の恩恵を受けると思いますか?


良いコードとは何ですか?適切に設計され、テストされ、文書化されており、将来の証拠となるもの、または支払いを受けるものですか?いつものように:あなたはそれを持つことができます良いです。あなたはそれを安くすることができます。あなたはそれを速く持つことができます。2つを選んでください。3つ目はあなたの費用です。
サルダスリオン

2
「私は常に新しいコードについて議論するだろう」...「新しいコード」はレガシーコードベースか「新しいコード」か?:-)
マーティンバ

pdrには正しい考えがあります。これはエンジニアリング上の決定です(トレードオフのあるもの)。一般に、吟味されたコードの大きな部分がある場合は、そのままにしておくことをお勧めします。レガシコード(1年だけですが、それで十分です)でTDDの取り組みを見たことがあります。コード/機能が完了してテストされている場合、インストルメンテーション(TDD)を追加するためにコードを壊すことはしないでください。
アノン

10

TDDの意味での単体テストの利点は、安定したチームによって長年にわたって構築された口承の伝統を必要とせずに、それ自体で独立したものを取得することです。

同じチームが長い間同じプロジェクトに参加しているのは大きな幸運です。しかし、これは最終的に変更されます。人々は病気になり、退屈し、昇進します。彼らは動いたり、引退したり、死んだりします。新しいものには新しいアイデアがあり、学校で学んだ方法ですべてをリファクタリングする衝動があります。企業は売買されます。管理ポリシーが変更されます。

プロジェクトを存続させるには、変更に備えてプロジェクトを準備する必要があります。


3

単体テストを書くことは、将来コードを校正することです。 コードベースにテストがない場合は、すべての新機能に新しいテストを追加する必要があります。これにより、コードのビットが少しだけ堅牢になります。

テストを追加することは、レガシーコードであっても、中長期的には有益であることがわかりました。あなたの会社が中長期を気にしないなら、私は別の会社を探します。また、セットユニットテストを記述するよりも手動でテストする方が時間がかかるとは思いません。もしそうなら、テストを書くことに焦点を当てたコードカタを練習する必要があります。


1
しかし、しかし、しかし!:-)その少し、新しい機能を実装するために必要な時間の100%の増加に変換する必要があります。後続の機能を実装するのに必要な時間短縮されませ。ものを変更するときに必要な時間を減らすことができます。
マーティンBa

3
コードのその領域の変更が新しいバグを引き起こさないこと、新しい(経験の少ないユーザー)がコードを明確に理解できること、そしてその領域に影響する副作用がリリース時ではなくテスト時に咳をすることを確認しています時間。テストは、コードが後で機能を追加するのを容易にするべ​​きではないことをコードが検証するのに役立ちます。テストを追加することは、レガシーコードであっても、中長期的には有益であることがわかりました。あなたの会社が中長期を気にしないなら、私は別の会社を探します。
サルダスリオン

1
@Martinは、明らかにあなたがすることは、あなたがその機能がどうあるべきだと思うかをコーディングし、それを出荷するからです。どの段階でもテストは行われません...いいえ、待ってください。開発者として、私たちは全員、コードを実行する前に(少なくとも手作業で)テストします。「手作業で」を「自動化されたテストを書くことで」置き換えることは、時間の100%の増加ではありません。多くの場合、ほぼ同じ時間がかかっていることがわかります。
カズドラゴン

1
@Kaz-「「手で」を「自動化されたテストを書くことで」置き換えることは、時間の100%の増加ではありません。多くの場合、ほぼ同じ時間がかかることがわかります。」-YMMVですが、私のコードベースでは、これは明らかに間違っています(質問で説明されています)。
マーティンBa

3
@Kaz: :-)の意味:ユニットテストは、コードを単独でテストします。単体テストを作成しない場合、コードを単独でテストするのではなく、コードが正しく呼び出され、アプリで目的の結果が生成される場合のみです。この2つのポイント(「正しく」と「アプリが何をすべきか」と呼ばれる)は、とにかく(手動で)テストする必要があり、単体テストではカバーされません。そして、単体テストはこれらの2つのポイントをカバーしませんが、私の機能を単独で「ただ」テストします。(そして、この単体テストのテストは追加であり、私の知る限りでは相殺されません。)
マーティンバ

2

確かにベストプラクティスでは、変更するコードを単体テストする必要があります。ただし、実際のコーディングには多くの妥協が必要であり、時間と素材には限りがあります。

行う必要があるのは、バグを修正し、単体テストなしで変更を加えるという実際の観点でコストを評価することです。その後、これらのテストの作成への投資に対して評価できます。単体テストは、将来の作業のコストを大幅に削減しますが、今は高価です。

結論としては、システムがめったに変更されない場合、単体テストを書く価値はないかもしれませんが、定期的な変更が必要な場合は価値があります。


1

テストを作成しないというこれらの小さな合理的な決定はすべて、誰かが去り、新しい雇用者が入ってきてスピードを上げなければならないときにあなたを悩ませるように戻ってくる不自由な技術的負債を構築しています。

はい、ユニットテストを書くのにさらに2-3時間かかるかもしれませんが、コードがテストから返送された場合、手動ですべてを再度テストし、テストを文書化する必要があります-あなたはそうしませんか?それ以外の場合、誰がどのようにあなたがテストしたものとあなたが使用した値を知っていますか?

単体テストは、機能の確認に使用したテストデータのコードの予想される動作を記録し、新しいコーダーが変更時に何かを壊していないという合理的な自信を与えます。

今日は手動テストよりも数時間かかりますが、変更を行うたびにテストしているので、コードの有効期間中に何時間も節約できます。

ただし、コードが2年以内に廃止されることがわかっている場合は、コードにテストを入れ終えず、返済しないため、変更点はすべて述べました。


「また、テストを文書化してください-そうしますか?」-{冷笑的な帽子をかぶる:}もちろんそうではありません。私たちは開発者の妖精の国にいません スタッフは実装され、テストされ、出荷されます。後で壊れて修正され、テストされて出荷されます。
マーティンBa

単体テストの数に関係なく、すべてが手動でテストされることを望みます。自動化された受け入れテストはまったく別の問題です。ただし、コードベースがレガシであるため受け入れテストが難しくなることはないため、ここでは対象外とします。
pdr

2
mcottle- 重要なポイントが欠落しています。ユニットテストはありません、完成した特徴の「手動機能テスト」を行うのにかかる時間を減らします。私はまだ、可能な入力の慎重なサブセットに関連するすべてのダイアログをクリックして、実際の完成したアプリが構築されたとおりに動作することを確認する必要があります。(ユニットテストにより、手動テスト中にのみ明らかな問題が発見されないことを確認する場合理論的にユニットテストはこの手動テストサイクルを1つのループに制限するのに役立つことを認めます。)
Martin Ba

0

単体テストの価値は、それが開発されたときに新しい機能をテストすることだけにありません。単体テストの利点は、主に将来的に得られます。

はい、レガシーコードをテスト可能にするために、途方もない時間のように思われる時間を費やす必要があるかもしれません。

あなたがいない場合でも、あなたは意志、または確かにする必要があり、機能をテストし、多くの、多くの、より多くの時間を費やしています。最初の開発時だけでなく、ソフトウェアのすべての新しいバージョンで。単体テストや他の形式の自動テストがない場合、他のオプションはありませんが、機能自体が変更されていない場合でも、機能が意図せず破損しないように手動テストに何時間も費やす必要があります。


1
「単体テストがなければ、機能自体が変更されていなくても、機能が意図せずに破損しないことを保証する他の手段はありません。」-単体テストは役に立ちません。本当に確認して、私は自動化された統合/受け入れテストを持っている必要があるだろう。
マーティンBa

はい、単体テストは最初のステップにすぎません。明確にするために編集された回答
マージャンヴェネマ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.