実稼働中の既存のプロジェクトに単体テストを追加することを強く検討しています。 TDD(face Palm)の利点を実際に見ることができるようになる前に、18か月前に開始されました。そのため、今では多くのプロジェクトを備えたかなり大規模なソリューションであり、ユニットテストを追加する際にどこから始めればよいのか、私にはわかりません。これを考慮しているのは、時折古いバグが表面化したり、reallyが修正されずに修正済みとしてバグがチェックインされたりすることです。単体テストは、これらの問題の発生を軽減または防止します。
SOで- similarの質問を読むことで、バグトラッカーで開始し、回帰を防ぐために各バグのテストケースを書くなどの推奨事項を見てきました。ただし、全体像を見逃してしまい、TDDを最初から使用した場合に含まれていたはずの基本的なテストを見逃してしまうのではないかと心配しています。
既存のソリューションが適切に適切にユニットテストされ、単に拘束されるだけではないことを保証するために従うべきプロセス/ステップはありますか?どのようにすれば、テストが良質であり、テストがないというよりもテストのケースではないことを保証できます。
だから私も私が求めているのは推測しています。
(明らかに、3番目のポイントに対する答えは、経営者と開発者のどちらに話しているかによって完全に異なります)
報奨金を追加することで、それが良いことだという既存の疑念を確認するだけでなく、反対するいくつかの正当な理由もある幅広い回答を試みることができます。
私はこの質問を賛否両論で後から書き上げ、製品の将来の開発をTDDに移行するのに工数を費やす価値があることを経営者に示すことを目指しています。私はこの挑戦に取り組み、自分の偏った視点なしに推論を発展させたいと思っています。
以前は持っていなかったコードベースに単体テストを導入しました。私がこれに関与した最後の大きなプロジェクトは、チームに到着した時点で、製品が既にユニットテストなしで生産されていました。 2年後、私が辞めたとき、4500以上のテストがあり、230 000 +本番LOC(リアルタイム金融Win-Formsアプリケーション)のコードベースで約33%のコードカバレッジが得られました。それは低いように聞こえるかもしれませんが、その結果、コードの品質と欠陥率が大幅に改善され、さらに士気と収益性が改善されました。
関係者からの正確な理解とコミットメントの両方がある場合に実行できます。
まず、単体テストはそれ自体がスキルであることを理解することが重要です。 「従来の」標準によって非常に生産的なプログラマーになることができますが、それでも大きなプロジェクトでスケールする方法で単体テストを書くのに苦労します。
また、特に状況に応じて、テストのない既存のコードベースに単体テストを追加することも、それ自体が専門スキルです。あなたまたはあなたのチームの誰かが既存のコードベースに単体テストを導入することに成功した経験がない限り、私は Feather's book を読むことは必須であると言います(オプションまたは強く推奨されません)。
コードの単体テストへの移行は、コードベースの品質と同様に、人とスキルへの投資です。これを理解することは、考え方や期待を管理する上で非常に重要です。
さて、あなたのコメントと質問のために:
ただし、全体像を見逃してしまい、TDDを最初から使用した場合に含まれていたはずの基本的なテストを見逃してしまうのではないかと心配しています。
簡単な答え:はい、あなたはテストを見逃します。はい、それらは最初はグリーンフィールドの状況で持っているもののように見えないかもしれません。
より深いレベルの答えはこれです:それは問題ではありません。テストなしで開始します。テストの追加を開始し、必要に応じてリファクタリングします。スキルレベルが向上するにつれて、プロジェクトに追加されたすべての新しく記述されたコードの水準を上げ始めます。改善を続けるなど...
さて、ここの行の間を読むと、これは「行動を起こさない言い訳としての完璧さ」の考え方から来ているという印象を受けます。より良い考え方は、自己信頼に集中することです。あなたはまだそれを行う方法を知らないかもしれないので、あなたが行くと空欄を埋める方法を見つけます。したがって、心配する必要はありません。
繰り返しますが、そのスキル。 1つの「プロセス」または「ステップバイステップ」クックブックアプローチで、直線的な方法でゼロテストからTDDパーフェクトに進むことはできません。それはプロセスになります。あなたの期待は、段階的かつ漸進的な進歩と改善をすることでなければなりません。魔法の薬はありません。
幸いなことに、数か月(さらには数年)が経過すると、コードは徐々に「適切な」十分にファクタリングされ、十分にテストされたコードになり始めます。
補足として。古いコードベースにユニットテストを導入する際の主な障害は、結束力の欠如と過度の依存関係であることがわかります。したがって、おそらく最も重要なスキルは、実際の単体テストを記述するのではなく、既存の依存関係を破り、コードを分離する方法になることでしょう。
既存のソリューションが適切に単体テストされることを保証するために遵守すべきプロセス/ステップはありますか?
既にお持ちでない場合は、ビルドサーバーをセットアップし、コードカバレッジのすべての単体テストを含むすべてのチェックインで実行される継続的な統合ビルドをセットアップします。
あなたの人々を訓練します。
どこかで開始し、顧客の観点から進捗を確認しながらテストの追加を開始します(以下を参照)。
テスト対象の実稼働コードベースの量の目安として、コードカバレッジを使用します。
ビルド時間は常に速いはずです。ビルド時間が遅い場合、ユニットテストのスキルが遅れています。遅いテストを見つけて改善します(製品コードとテストを分離して分離します)。うまく書かれていれば、数千のユニットテストを簡単に実行でき、10分以内にビルドを完了することができます(〜1数ms /テストは良いですが非常に大まかなガイドラインであり、リフレクションなどを使用するコードのようにいくつかの例外が適用される場合があります)。
検査と適応。
どのようにすれば、テストが良質であり、テストがない場合よりもテストの方が優れていることを保証できます。
あなた自身の判断が現実の主要な源でなければなりません。スキルに代わる指標はありません。
あなたがその経験や判断を持っていない場合は、誰かに契約することを検討してください。
2つの大まかなセカンダリインジケータは、コードカバレッジ全体とビルド速度です。
実稼働中の既存のソリューションに労力をかける価値はありますか?
はい。カスタムビルドシステムまたはソリューションに費やされたお金の大部分は、実稼働に投入された後に使用されます。そして、品質、人材、スキルへの投資は決してスタイルを損なうべきではありません。
このプロジェクトのテストを無視して、将来の書き換えに追加する方が良いでしょうか?
人とスキルへの投資だけでなく、最も重要なのは総所有コストとシステムの予想寿命を考慮する必要があります。
私の個人的な答えは、ほとんどの場合「もちろん」です。なぜなら、私はその方がはるかに良いことを知っているからです。しかし、例外があるかもしれないことを認識しています。
より有益なもの;テストの追加に数週間を費やすか、機能の追加に数週間を費やしますか?
どちらでもない。あなたのアプローチは、機能の面で進歩を遂げている間に、コードベースにテストを追加することです。
繰り返しますが、これは人、スキル、およびコードベースの品質への投資であり、そのためには時間がかかります。チームメンバーは、依存関係を解消する方法、単体テストを作成する方法、新しい習慣を学ぶ方法、規律と品質意識を改善する方法、ソフトウェアをより良く設計する方法などを学ぶ必要があります。そのアプローチが成功するために必要なレベルでこれらのスキルをまだ持っているので、多くのテストを追加するためにすべての時間を費やすために進行を止めることは、単に機能しません。
また、かなりのプロジェクトサイズの既存のコードベースに単体テストを追加することは、コミットメントと永続性を必要とする大規模な取り組みです。基本的な何かを変更することはできません。途中で多くの学習を期待し、スポンサーにビジネス価値の流れを止めることでROIを期待しないよう依頼することはできません。それは飛ぶことはありませんし、率直に言ってそうではありません。
第三に、チームに健全なビジネス重視の価値を植え付けたいと思っています。品質が顧客の犠牲になることはなく、品質がなければ迅速に進むことはできません。また、顧客は変化する世界に住んでいます。あなたの仕事は、顧客がより簡単に適応できるようにすることです。顧客との連携には、品質とビジネス価値の流れの両方が必要です。
あなたがしているのは、技術的な負債を返済することです。そして、お客様は常に変化するニーズに応えながら、そのようにしています。借金が返済されるにつれて、状況は徐々に改善され、顧客により良いサービスを提供し、より多くの価値を提供することが容易になります。等このポジティブな勢いは、持続可能なペースの原則を強調し、開発チーム、顧客、および利害関係者の両方の道徳を維持および改善するため、目指すべきものです。
役立つことを願っています
- 実稼働中の既存のソリューションに労力をかける価値はありますか?
はい!
- このプロジェクトのテストを無視して、将来の書き換えに追加する方が良いでしょうか?
いや!
- より有益なもの;テストの追加に数週間を費やすか、機能の追加に数週間を費やしますか?
テスト(特に自動テスト)を追加すると、muchプロジェクトの将来的な動作が容易になり、大幅に向上しますバカな問題をユーザーに出荷する可能性は低くなります。
先験的にaを入れるテストは、コード(およびその中の各モジュール)へのパブリックインターフェイスがあなたのやり方で動作していると思われるものをチェックするものです。と思います。可能であれば、コードモジュールに必要な分離された各障害モードも誘導するようにしてください(これは簡単ではない可能性があるため、実際に失敗したくないなど、失敗する方法を慎重にチェックしないように注意してください)失敗時に生成されたログメッセージの数を数えるなどのことを行います。ログに記録されていることを確認するだけで十分です)。
次に、バグデータベース内の現在の各バグに対して、正確にバグを誘発し、バグが修正されたときに合格するテストを実行します。その後、それらのバグを修正してください! :-)
テストを追加するには前もって時間がかかりますが、コードの品質がはるかに高くなるため、バックエンドで何度も返済されます。新しいバージョンを出荷したり、メンテナンスを実行したりするとき、それは非常に重要です。
単体テストを改良する際の問題は、ここに依存関係を挿入したり、そこにインターフェースを使用したりすることを考えていなかったことに気づき、やがてコンポーネント全体を書き換えることになります。これを行う時間がある場合は、ニースセーフティネットを構築しますが、途中で微妙なバグが発生する可能性があります。
私は初日からユニットテストを本当に必要としていた多くのプロジェクトに携わってきましたが、完全な書き直しを除いてそこに入れる簡単な方法はありません。最近、私は、問題が発生するとすぐに再現するようにコードを実行するpowershellスクリプトを記述し、これらのスクリプトを一連の回帰テストとして今後の変更のために保持しました。そうすれば、アプリケーションをあまり変更することなく、少なくともアプリケーションのテストの構築を開始できますが、これらは適切な単体テストではなく、エンドツーエンドの回帰テストに似ています。
私は他のほとんどの人が言ったことに同意します。既存のコードにテストを追加することは有益です。私はその点に決して異議を唱えませんが、一つ注意点を加えたいと思います。
既存のコードにテストを追加することは重要ですが、コストがかかります。それは、not新しい機能を構築するという犠牲を払って行われます。これら2つのことをどのようにバランスさせるかは、プロジェクトに完全に依存し、多くの変数があります。
繰り返しになりますが、テストは貴重であり、古いコードをテストするために作業する必要があります。これは、実際のアプローチ方法の問題です。すべてをドロップしてすべての古いコードをテストする余裕がある場合は、実行してください。それが現実的でない場合、あなたがすべきことは次のとおりです少なくとも
また、これはすべてまたは何も命題ではありません。たとえば、4人のチームがあり、1人または2人をレガシーテストの任務にかけることで納期に間に合う場合は、必ずそれを行います。
編集:
私はこの質問を賛否両論で後から書き上げ、製品の将来の開発をTDDに移行するのに工数を費やす価値があることを経営者に示すことを目指しています。
これは、「ソース管理を使用することの長所と短所は何ですか?」または「人を雇う前に面接することの長所と短所は何ですか?」または「呼吸の長所と短所は何ですか?」
引数の片側しか存在しない場合があります。複雑なプロジェクトには、何らかの形式の自動テストが必要です。いいえ、テストはそれ自体を記述しません。そして、はい、物事をドアから出すのに少し余分な時間がかかります。しかし長い目で見れば、テストを前もって書くよりも、バグを修正するのにより多くの時間と費用がかかります。期間。これですべてです。
テストの追加を開始したとき、それは10年前の約100万行のコードベースであり、UIとレポートコードのロジックが多すぎました。
(連続ビルドサーバーをセットアップした後)最初に行ったことの1つは、回帰テストを追加することでした。これらはエンドツーエンドのテストでした。
回帰テストの目的は、何か変更があった場合に通知することです。つまり、何かを壊した場合は失敗しますが、意図的に何かを変更した場合も失敗します(この場合、修正はスナップショットファイルを更新することです)。スナップショットファイルが正しいことすらわかりません。システムにバグがある可能性があります(これらのバグを修正すると、回帰テストは失敗します)。
それでも、回帰テストは私たちにとって大きな勝利でした。システムのほぼすべてにレポートがあるため、レポートにテストハーネスを数週間使用することで、コードベースの大部分をある程度カバーすることができました。同等の単体テストを作成するには、数か月または数年かかりました。 (単体テストは、私たちにはるかに良いカバレッジを与え、脆弱性ははるかに少なかったでしょう。しかし、完成まで何年も待つのではなく、今は何かが欲しいです。)
その後、戻って、バグを修正したり、機能強化を追加したり、コードを理解する必要があるときに、単体テストを追加し始めました。回帰テストは、単体テストの必要性を決して排除しません。これらは単なる第1レベルのセーフティネットであるため、someレベルのテストカバレッジをすばやく取得できます。その後、リファクタリングを開始して依存関係を解消し、単体テストを追加できます。そして、回帰テストは、リファクタリングが何も壊さないというレベルの自信を与えます。
回帰テストには問題があります。速度が遅く、壊れる理由が多すぎます。しかし、少なくとも私たちにとっては、彼らはso価値がありました。過去5年間で数え切れないほどのバグを発見し、QAサイクルを待つのではなく、数時間以内にバグを発見しています。元の回帰テストがまだあり、7つの異なる連続ビルドマシン(高速ユニットテストを実行するマシンとは別のマシン)にまたがっています。 +単体テストは対象外です。
それは絶対に価値があります。このアプリには複雑な相互検証ルールがあり、最近、ビジネスルールに大きな変更を加える必要がありました。競合が発生し、ユーザーが保存できなくなりました。アプリケーションで整理するのに永遠に時間がかかることに気付きました(問題が発生した場所に到達するまでに数分かかります)。自動化された単体テストを導入したいので、フレームワークをインストールしましたが、動作を確認するためにダミーのテストをいくつか実行することはありませんでした。新しいビジネスルールを手に入れて、テストを書き始めました。テストにより、競合の原因となった条件をすばやく特定し、ルールを明確にすることができました。
追加または変更する機能をカバーするテストを作成すると、すぐにメリットが得られます。書き直しを待つ場合、自動化されたテストを行うことはできません。
すでに動作している既存のもののテストを書くのに多くの時間を費やすべきではありません。ほとんどの場合、既存のコードの仕様はないため、テストしている主なものはリバースエンジニアリング能力です。一方、何かを変更する場合は、その機能をテストでカバーする必要があるため、変更を正しく行ったことがわかります。そしてもちろん、新しい機能については、失敗するテストを作成し、欠落している機能を実装します。
私は自分の声を追加して、はい、それは常に便利だと言います!
ただし、留意すべきいくつかの違いがあります。ブラックボックスとホワイトボックス、ユニットと機能です。定義はさまざまであるため、これらの意味は次のとおりです。
ゲームの後半で出荷製品にテストを追加したときに、white-boxおよびfunctionalテストから最大の価値を得ることがわかりました。特に脆弱であることがわかっているコードの部分がある場合は、問題をカバーするホワイトボックステストを作成して、同じ方法が2回繰り返されないようにします。同様に、システム全体の機能テストは、最も一般的な10のユースケースを決して壊さないようにするのに役立つ便利な健全性チェックです。
小さいユニットのブラックボックスおよびユニットテストも有用ですが、時間に制限がある場合は、早期に追加することをお勧めします。出荷する頃には、これらのテストで発見されたEdgeのケースと問題の大部分を(困難な方法で)通常発見しました。
他の人と同様に、TDDについての2つの最も重要なことも思い出してください。
実装言語については言及しませんが、Javaの場合は、このアプローチを試すことができます。
別のソースツリーで、回帰テストまたは「煙」テストを作成し、ツールを使用してそれらを生成します。これにより、カバー率が80%近くになります。これらのテストは、すべてのコードロジックパスを実行し、その時点から、コードが(バグが存在する場合でも)現在の動作を正確に実行することを確認します。これにより、必要なリファクタリングを行ってコードを手作業で簡単にユニットテストできるようにするときに、不注意による動作の変更に対する安全策が提供されます。
修正するバグ、または今後追加する機能ごとに、TDDアプローチを使用して、新しいコードがテスト可能に設計され、これらのテストが通常のテストソースツリーに配置されるようにします。
既存のコードは、新しい機能を追加する一環としてテスト可能にするために、変更またはリファクタリングが必要になる可能性があります。煙テストは、回帰または不注意による動作の微妙な変化に対するセーフティネットを提供します。
TDDを介して変更(バグ修正または機能)を行う場合、完了時にコンパニオンスモークテストが失敗している可能性があります。手書きの単体テストでは改善されたコンポーネントが完全に網羅されているため、変更による障害が予想どおりであることを確認し、読みにくい煙テストを削除します。テストカバレッジが低下しないことを確認してください。
バグを修正するときは、最初にバグを公開する失敗した単体テストを記述します。
実稼働中のアプリに単体テストを追加する価値があるかどうかは、アプリのメンテナンス費用に依存します。アプリにバグや機能強化リクエストがほとんどない場合は、努力する価値はないかもしれません。 OTOH、アプリにバグがあるか、頻繁に変更される場合、単体テストは非常に有益です。
この時点で、最初からTDDを実践していた場合に存在するテストに似たテストスイートを生成しようとするのではなく、ユニットテストを選択的に追加することを話していることに注意してください。したがって、2番目の質問の後半に対応して、次のプロジェクトでTDDを使用することのポイントを作成します。新しいプロジェクトであれ、書き換えであれ(謝罪ですが、ここにへのリンクがあります)あなたが本当に読むべきもう一つの本: テストに導かれたオブジェクト指向ソフトウェアの成長 )
3番目の質問に対する私の答えは、最初の質問と同じです。プロジェクトのコンテキストに依存します。
投稿に埋め込まれているのは、レトロフィットされたテストが確実に行われるようにするためのさらなる質問ですproperly。確認する必要がある重要なことは、単体テストが実際にunitテストであり、これが(より頻繁にnot)は、テストの改造が既存のコードをリファクタリングして、レイヤー/コンポーネントの分離を可能にすることを意味します(依存関係の注入、制御の反転、スタブ、モックを参照)。これを強制しない場合、テストは統合テストになります。これは便利ですが、ターゲットテストが少なく、真の単体テストよりも脆弱です。
ユニットテストはバグが実稼働に入る前に阻止できるので、ユニットテストは本当に重要だと言って、この回答を始めたいと思います。
バグが再導入されたプロジェクト/モジュールの領域を特定します。テストを書くためにそれらのプロジェクトから始めてください。新しい機能とバグ修正のためにテストを書くことは完全に理にかなっています。
実稼働中の既存のソリューションに労力をかける価値はありますか?
はい。バグが落ち、メンテナンスが容易になることがわかります。
このプロジェクトのテストを無視して、将来の書き換えに追加する方が良いでしょうか?
今から開始することをお勧めします。
より有益なもの;テストの追加に数週間を費やすか、機能の追加に数週間を費やしますか?
間違った質問をしている。間違いなく、機能は他の何よりも重要です。しかし、テストを追加するのに数週間費やすことでシステムがより安定するかどうかを尋ねるべきです。これは私のエンドユーザーに役立ちますか?チームの新しい開発者がプロジェクトを理解し、変更の全体的な影響を理解していないためにバグが発生しないようにするのに役立ちますか。
どこでリファクタリングを開始するかという質問に対する答えとして、私は Low-hanging Fruitのリファクタリング がとても好きです。それは、噛むことができる以上のことを食い止めることなく、より良いデザインを容易にする方法です。
同じロジックがTDDに適用されると思います-または単体テスト:必要に応じて、必要なテストを記述します。新しいコードのテストを作成します。バグのテストを表示します。あなたはコードベースの到達困難な領域を無視することを心配しており、それは確かにリスクですが、始める方法として:始めましょう!コードカバレッジツールを使用すると、将来のリスクを軽減できます。とにかく、リスクはそれほど大きくありません(私の意見では)。 、その後、テストの必要性が最も高いコードをカバーします。
更新
最初の回答から6年後、私は少し異なる見解を持っています。
書いたすべての新しいコードに単体テストを追加し、変更を加えた場所をリファクタリングしてテスト可能にするのは理にかなっていると思います。
既存のすべてのコードに対して一度にテストを作成しても効果はありませんが、作成する新しいコード(または変更する領域)のテストを作成しないことも意味がありません。リファクタリング/物事の追加時にテストを追加することは、おそらくテストを追加せず、テストのない既存のプロジェクトでコードをより保守しやすくする最良の方法です。
以前の回答
私はここでいくつかの眉を上げるつもりです:)
まず第一に、あなたのプロジェクトは何ですか-コンパイラー、言語、フレームワーク、または機能的に長期間変化しないものであれば、単体テストを追加することは非常に素晴らしいと思います。
ただし、(要件の変更のために)機能の変更が必要になる可能性のあるアプリケーションで作業している場合、その余分な努力をする意味はありません。
どうして?
単体テストは、コードテスト(コードが意図したとおりに機能するかどうか)のみをカバーします(とにかく行わなければならない手動のテストに代わるものではありません)
単体テストには時間がかかります!私の出身地は貴重な商品です。ビジネスは一般に、完全なテストスイートよりも優れた機能を選択します。
アプリケーションがユーザーにとってもリモートで有用な場合、ユーザーは変更を要求します-そのため、より良い、より速く、おそらく新しいことを行うバージョンがあります-コードが大きくなると、多くのリファクタリングが行われる可能性があります。動的な環境で完全に成長した単体テストスイートを維持することは頭痛の種です。
単体テストは、製品の知覚品質(ユーザーが見る品質)には影響しません。もちろん、メソッドは1日目とまったく同じように機能する可能性があります。プレゼンテーションレイヤーとビジネスレイヤーとの間のインターフェイスは初期のままかもしれませんが、何を推測しますかユーザーは気にしません!実際のテスターにアプリケーションをテストしてもらいます。そして、多くの場合、これらのメソッドとインターフェースは遅かれ早かれとにかく変更しなければなりません。
より有益なもの;テストの追加に数週間を費やすか、機能の追加に数週間を費やしますか? -テストを書くよりもうまくできることがたくさんあります-新しい機能を書く、パフォーマンスを改善する、使いやすさを改善する、ヘルプマニュアルを書く、保留中のバグを解決するなど.
誤解しないでください-物事が今後100年間変わらないことを絶対に確信している場合は、先に進み、自分自身をノックアウトしてそれらのテストを書いてください。自動テストは、サードパーティのコードを壊したくないAPIにとっても素晴らしいアイデアです。他のどこでも、それは私が後で出荷するものです!
はい、できます。今から書くすべてのコードがテストされていることを確認してください。
既に配置されているコードを変更する必要があり、テストできる場合は、そうしますが、安定したコードのためにテストを配置しようとするのはあまり積極的ではありません。そのようなものは、ノックオン効果を持つ傾向があり、制御不能にスパイラルする可能性があります。
実稼働中の既存のソリューションに労力をかける価値はありますか?
このプロジェクトのテストを無視して、将来の書き換えに追加する方が良いでしょうか?
より有益なもの;テストの追加に数週間を費やすか、機能の追加に数週間を費やしますか?
かなりのテストカバレッジが得られることはまずないので、テストを追加する場所について戦術的にならなければなりません。
OTOH、人々が満足しているコードの周りにテストを書くのに座っているだけの価値はありません-特に誰もそれを修正するつもりがない場合。単に価値を追加するだけではありません(システムの動作を理解することを除いて)。
がんばろう!
私はベテランのTDDの専門家ではありませんが、もちろん、できる限り単体テストを行うことは非常に重要です。コードは既に配置されているので、まずはある種の単体テストの自動化を配置することから始めます。 TeamCityを使用して、プロジェクトのすべてのテストを実行します。これにより、コンポーネントがどのように機能したかをまとめたニースが提供されます。
それができたら、失敗しない本当に重要なビジネスロジックのようなコンポーネントに移ります。私の場合、さまざまな入力に対して解決する必要のある基本的な三角法の問題があるので、それらの全体をテストします。私がこれを行う理由は、真夜中の油を燃やしているときに、実際に触れる必要のないコードの深さまで掘り下げる時間を無駄にするのは非常に簡単だからです、あなたはテストされていることを知っている =可能なすべての入力に対して(私の場合、有限数の入力があります)。
わかりましたので、今、あなたはそれらの重要な部分について良くなることを願っています。座ってすべてのテストを叩くのではなく、テストが開始されたら攻撃します。修正すべき本当のPITAであるバグに遭遇した場合は、そのための単体テストを作成し、邪魔にならないようにしてください。
テストから特定のクラスをインスタンス化できないため、テストが難しい場合があります。そのため、モックする必要があります。ああ、でもインターフェイスに書いてないので簡単にモックできないかもしれません。私はこれらの「おっと」シナリオを、前述のインターフェースを実装する機会と考えています。それは、まあ、それは良いことだからです。
そこから、ビルドサーバー、またはコードカバレッジツールで構成された自動化されたものを取得します。それらは、カバレッジの悪い大きな赤いゾーンを持つ厄介な棒グラフを作成します。 100%のカバレッジは目標ではありませんし、100%のカバレッジは必ずしもあなたのコードが防弾であることを意味するわけではありません。 :)
TopTalエンジニアによる素晴らしい 記事 を読むことをお勧めします。テストでは、whereを説明しています。 、しかし基本的な考え方は:
1)コードのAfferent Coupling(CA)(クラスが他のクラスによってどれだけ使用されているか、それを壊すことは広範囲の損害を引き起こすことを意味する)を測定する
2)コードのCyclomatic Complexity(CC)を測定します(複雑度が高い=破壊の変化が大きい)
CAとCCの高いクラスを識別する必要があります。つまり、関数f(CA、CC)と2つのメトリック間の最小の差異には、テストカバレッジの最高の優先順位を与える必要があります。
どうして?高いCAであるが非常に低いCCクラスは非常に重要ですが、壊れることはないためです。一方、低いCAで高いCCは破損する可能性が高くなりますが、被害は少なくなります。バランスを取りたいです。
良い答えがたくさんあるので、私は彼らの内容を繰り返しません。プロファイルを確認しましたが、C#.NET開発者のようです。そのため、Microsoft PEX and Moles プロジェクトへの参照を追加しています。これは、レガシーコードの単体テストの自動生成に役立ちます。自動生成は最良の方法ではないことを知っていますが、少なくとも開始する方法です。 レガシーコードのPEX の使用に関するMSDNマガジンの非常に興味深い記事を参照してください。
別の本を買いたくないと言います。マイケルフェザーの レガシーコードを効果的に使用する の記事を読んでください。それから本を買ってください:)
私があなたの代わりにいたなら、システム全体を実行する機能テストから始めて、おそらく外部からのアプローチを取るでしょう。 RSpecのようなBDD仕様言語を使用してシステムの要件を再文書化し、ユーザーインターフェイスを自動化してこれらの要件を検証するテストを作成します。
次に、新しく発見されたバグの欠陥駆動型開発を行い、ユニットテストを作成して問題を再現し、テストに合格するまでバグを処理します。
新しい機能については、アウトサイドインアプローチに固執します:RSpecで文書化され、ユーザーインターフェイスの自動化(もちろん最初は失敗します)で検証された機能から開始し、実装が進むにつれてよりきめ細かいユニットテストを追加します。
私はプロセスの専門家ではありませんが、経験が少ないことから、自動化されたUIテストを介したBDDは簡単ではないことを伝えることができますが、努力する価値があり、おそらくあなたのケースで最も利益が得られると思います。
場合によります...
単体テストを行うのは素晴らしいことですが、バグのない製品を入手するためには、ユーザーが誰であり、どの程度許容できるかを考慮する必要があります。ユニットテストが現在存在しないコードをリファクタリングすることは避けられないため、バグが発生し、多くのユーザーは、長期的に製品を一時的に欠陥を減らして欠陥を少なくすることを理解するのが難しくなります。最終的には最終決定権を持つのはユーザーです...