web-dev-qa-db-ja.com

自動テストでレガシーコードを改造するためのベストプラクティス

私は、比較的大きくて古いコードベースで、既に定義されているインターフェイス(C++ヘッダーファイルのセット)を再実装するタスクを引き受けようとしています。これを行う前に、可能な限り完全なテストカバレッジを用意して、再実装エラーをできるだけ早く簡単に検出できるようにしたいと考えています。問題は、既存のコードベースが、(非常に)大きなクラスと関数、高度な結合、(多くの)副作用がある関数など、簡単にテストできるように設計されていないことです。

以前の同様のタスクの経験や、自動テスト(ユニット、統合、回帰など)をレガシーコードに後付けする方法についてのいくつかの優れた具体的なヒントを聞いていただければ嬉しいです。

22
tjansson

まず第一に、入手して読んでください レガシーコードで効果的に作業する マイケルフェザーズ-それはそのようなタスクに不可欠な援助です。

次に、いくつかのメモ:

  • インターフェースの正確な仕様/契約がありますか、それとも「仕様」としての既存の実装のみがありますか?前者の場合は、最初から完全に書き直す方が簡単ですが、後者の場合は困難から不可能です。
  • インターフェイスを再実装する場合、テストリソースを費やす最も便利な方法は、インターフェイスに対してのみテストを作成することです。もちろん、これは厳密な意味での単体テスト、つまり機能/受け入れテストとは見なされませんが、私は純粋主義者ではありません:-)ただし、これらのテストは再利用可能であり、2つの実装の結果を直接比較できます。 。
  • 全体的に、メンテナンスが完全に不可能でない限り、既存のコードを一から書き直すよりもリファクタリングするほうを好みます。 (しかし、この場合、とにかくユニットテストをどのように記述しますか?)この件に関する詳細な議論については、 Joelからのこの投稿 をチェックしてください。インターフェイスに対する一連の受け入れテストを作成すると、薄くて便利なセーフティネットが得られます。これに対して既存のコードを慎重にリファクタリングして、ユニットテスト可能にする(Feathersの本のアイデアを使用して)ことができます。
20
Péter Török

最良の方法は、ミカド法です。 http://mikadomethod.wordpress.com/2010/08/04/the-mikado-method-book/ これは単純なテクニックの一般化に過ぎませんが、改善を始めるために知っている唯一の方法です不要なリスクを負うことなく、大きなコードベースでコードの品質を高めます。

WEWLCについても非常に優れた本ですが、C++で書かれていると、JavaまたはRubyコードを使用した場合、.

5
Uberto

設計がモノリシックである場合、古いコードベースへのレトロフィットテストは非常に困難です。

可能であれば(時間/お金はありますか)、先に進む1つの方法は、コードをよりテスト可能なユニットにリファクタリングすることです。

2
ozz

link を1つ追加します。より簡単にテスト可能な実装をより多くのxUnitフレンドリーなコードにリファクタリングした例はほとんどありません。一般的なアプローチについては、前述のリンクを試してください(Joelの投稿、レガシーコードの使用

1
yoosiba