web-dev-qa-db-ja.com

レガシーコードへのユニットテストの追加

事後、レガシーコードに単体テストを追加したことはありますか?コードはどれほど複雑で、すべてをスタブ化およびモック化するのがどれほど困難でしたか?最終結果は価値がありましたか?

76

最良の方法は、ただ飛び込んでアプリケーションの単体テストを行うと言うのではなく、単体テストを段階的に追加することです。

そのため、バグ修正やリファクタリングのためにコードに触れる場合は、最初にユニットテストを記述します。バグの場合、ユニットテストは問題がどこにあるかを証明するのに役立ちます。

リファクタリングする場合は、単体テストを作成する必要がありますが、テストを作成できないことがわかる場合があります。そのため、リファクタリングする関数を呼び出す高レベルを見つけ、その部分を単体テストする必要があります。次に、攻撃関数をリファクタリングするときに、テストを作成して、正常に動作していることを確認できるようにします。

これを行う簡単な方法はありません。

この質問はより多くの提案に役立つかもしれません。 どのようにしてユニットテストを大規模なレガシー(C/C++)コードベースに導入しますか?

54
James Black

マイケル・フェザーズの著書「レガシー・コードを効果的に使用する」は、このトピックを網羅した本全体です。 Michaelは、テスト可能な構造になっていないため、レガシーコードのテストを導入するのは難しいことが多いと述べています。私がこの本から最も得たものは、「スプラウト関数」と「スプラウトクラス」という名前のいくつかのパターンでした。スプラウト関数は、コードで行う必要がある変更をカプセル化する関数です。次に、これらの機能のみを単体テストします。 sproutクラスは、新しい機能がクラスに含まれていることを除いて同じ考えです。

38
Phillip Ngan

はい、それは一般に苦痛です。代わりに、統合テストを作成しなければならないことがよくありました。

この本 The Art of Unit Testing にはこれに関する良いアドバイスがあります。また、この本を推奨しています レガシーコードを効果的に使用する ;後者はまだ読んでいませんが、私のスタックにあります。

編集:しかし、はい、最小限のコードカバレッジでも価値がありました。コードをリファクタリングするための自信と安全策を与えてくれました。

編集:私はレガシーコードで効果的に作業を読んで、それは素晴らしいです。

8
TrueWill

レガシーコードユニットテストの領域の新しいアプローチもご覧ください- Asisプロジェクト 、それは ApprovalTestsに触発されています プロジェクトを作成し、その重要な概念を共有します。

この記事 でApprovalTestsアプローチについて述べたように:

多くの場合、テストをまったく行わない巨大なレガシーコードプロジェクトがありますが、新しい機能を実装するためにコードを変更するか、リファクタリングする必要があります。レガシーコードの興味深い点は、それが機能することです!どのように書かれていても、何年も機能します。そして、これはそのコードの非常に大きな利点です。承認により、1つのテストだけで、すべての可能な出力(HTML、XML、JSON、SQL、またはそれが可能な出力)を取得し、承認することができます。このようなテストを完了し、結果を承認した後、リファクタリングを行うことで、既存のすべての動作を「ロックダウン」することができるため、非常に安全になります。

Asisツールは、特性評価テストを自動的に作成および実行することで、レガシーコードを維持することを目的としています。

詳細については

6
zavg

ユニットコードの代替方法の1つは、「レガシーコードの効果的な使用」でも紹介されている キャラクタリゼーションテスト です。このようなテストで興味深い結果が得られました。ポイントからテストするので、テストできるよりも単体テストよりもセットアップが簡単です(シームと呼ばれます)。欠点は、テストが失敗したときに、テスト対象の領域が単体テストよりもはるかに大きくなる可能性があるため、問題の場所についてのヒントが少ないことです。ロギングはここで役立ちます。


XUnitファミリーのような単体テストフレームワークを使用して、特性評価テストを作成できます。

事実の後に書かれたこのようなテストでは、アサーションはコードの現在の動作を検証します。単体テストとは異なり、コードが正しいことを証明するのではなく、コードの現在の動作を特定(特徴付け)するだけです。

プロセスはTDDのプロセスと似ています。

  • コードの一部のテストを書く
  • 実行-失敗
  • 観測されたコードの動作からテストを修正します
  • 実行-パス
  • 繰り返す

コードの外部動作を変更すると、テストは失敗します。コードの外部動作?おなじみの音?はい、そうです、ここにいます。これで、コードをリファクタリングできます。

明らかに、リスクは特性評価テストの範囲に依存します。

5
philant

無料のオープンソースの単体テストユーティリティライブラリ ApprovalTests をご覧ください。あなたが.NET開発者である場合、作成者のLlewellyn Falcoは 一連のビデオ を作成し、ApprovalTestsを使用して新しいコードとレガシーコードの両方の単体テストを改善する方法を示しています。

5
Lynn Langit

レガシーコードのリファクタリングを計画している場合は、これらの単体テストを作成する必要があります。モックやスタブを心配する必要はありません-変更やリファクタリングの努力によって現在の機能が損なわれないように、システムの入力と出力をテストすることを心配してください。

私はあなたに嘘をつきません、レガシーコードにユニットテストを改造することは難しいです-しかし、それは価値があります。

4
Andrew Hare

XPDaysのレガシーコードのリバーステストピラミッドのアイデアについて少し前に話しました http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/

このプレゼンテーションでは、レガシーコードを使用して統合/機能テストまたは高レベルの受け入れテストを開始することが非常に重要な場合がある理由についての質問に答える必要があります。そしてゆっくりと、ユニットテストを段階的に導入します。コードの例はありません。申し訳ありませんが、Michaels Feathersの本「レガシーコードを効果的に使用する」でそれらの束を見つけることができます。

また、レガシーコードリトリート http://www.jbrains.ca/legacy-code-retreat を確認して、お住まいの地域でその会議を探すこともできます。

1
streser