web-dev-qa-db-ja.com

レガシーコード(わかりません)の単体テストを作成するにはどうすればよいですか?

進む

この質問をする前に、SEに関する多くの関連する質問を含め、多くのことを読みました。

しかし、私は助けを求めて読んだ後、かゆみがまだ引っかかれていないと感じざるを得ません。


TL; DR

実行、シミュレーション、読み取り、または簡単に理解できないレガシーコードの単体テストを作成するにはどうすればよいですか?おそらく意図したとおりに機能するコンポーネントに役立つ回帰テストは何ですか?


全体像

私は大学院に移行するので、再び夏の帰国研修生です。私の仕事には次の要件が含まれます。

  1. 特定の製品について、当社のソフトウェアチームが既存のプロジェクトとの互換性を失うことなくIDEおよびJUnitバージョンをアップグレードできるかどうかを評価します。
  2. 既存のJavaコード(大部分はJavaではない)のコードで一部のコンポーネントのユニットテストを開発します。ユニットテストとTDDは、使用する必要がある非常に貴重なツールであることをソフトウェアチームに納得させたいです。(現在0%のコードカバレッジ。)
  3. どういうわけか、重要なシステムのカウボーイコーディングの時代を終わらせてください。

ソースコードのコピーを入手した後、この製品の機能と動作を理解できるように、ビルドして実行しようとしました。できませんでした。上司に自分のやり方を尋ねたところ、実際にビルドスクリプトを含む、それをビルドできる新しいスタンドアロンマシンが発行されました。彼らの予想どおり、製品コードは設計された組み込みシステムでのみ実行されるため、これも機能しませんでした。しかし、彼らはこの目的のためにシミュレーターを持っているので、彼らはシミュレーターを手に入れて、このマシンにそれを置いてくれました。シミュレータも機能しませんでした。代わりに、私は最終的に特定の画面のGUIのプリントアウトを受け取りました。また、700,000 + Java LOC内のどこにもコードコメントがないため、把握がさらに困難になります。さらに、プロジェクトが新しいIDEと互換性があるかどうかを評価する問題がありました。特に、コードがIDE=使用するバージョンに正しく読み込まれませんでした。

私の在庫は次のようになっています:

  • NetBeans 8、9、10、11
  • JUnit 4、5
  • 特定の製品のソースコード(700,000以上Java LOCを含む)
  • 実質的にコードコメントはありません(場合によっては署名)
  • 既存のテストはありません
  • GUIウィンドウの物理的な写真
  • 画像内のコンポーネントについて説明していないソフトウェア設計ドキュメント(109ページ)

少なくとも理論的には実行可能なテストを書くのに十分です。そこで、このコンポーネントについて基本的な単体テストを試しました。しかし、モデル、マネージャー、DB接続など、依存関係として持つオブジェクトを初期化できませんでした。基本的な単体テスト以外にJUnitの経験はあまりないので、次のセクションに進んでください。


私の読書から学んだこと

  1. モック:単体テストを作成する場合、setUpで簡単に初期化できない本番依存関係のモック変数が必要になる可能性があります。
  2. ここの誰もが、マイケルフェザーズの著書「レガシーコードを効果的に使用する」を寛大に提案しています。
  3. 回帰テストは、おそらく開始するのに適しています。統合テストを試すのに十分な武器はないと思います。回帰テストは、ソフトウェアチームに即座に満足感を与えるでしょう。ただし、私は彼らの既知のバグにアクセスできません。しかし、私はたぶん尋ねることができました。

そして今、私がまだ疑問として持っている不確実性を明確にする試み。基本的に、私はこれらのテストを書くことのhow部分を理解していません。 (おそらく)上司からこれ以上のガイダンスを受け取らないと想定すると、このコンポーネントの機能を理解するだけでなく、どのテストが回帰テストとして実際に役立つかを判断するのは私の球場です。

このようなプロジェクトに携わってきた専門家として、このような状況で単体テストを作成する方法について何かアドバイスはありますか?

8
Joshua Detwiler

第一に、テストスイートの関係者は、コードの開発者/保守者です。あなたは彼らの時間のいくらかを必要とするでしょう。 これを主張する。

彼らが直面している問題について彼らに尋ねます。
最近修正したバグについて質問します(過去数年で、これは非常に時間がかかるプロジェクトであると想定しています)。

あなたは彼らがあなたの仕事に好意的であるとは期待していないような印象を受けます。多分あなたは正しいです。しかし、私はあなたが彼らの助けなしに有用なものを構築できるとは思いません。

彼らは最初のテストを書くまであなたの手を握ります。多分あなたはそれらをドラッグするでしょうが、あなたはどちらかの方法で手をつなぐでしょう。

1つのテストを取得すると、2番目の記述方法が明確になることを願っています。なんらかの信頼関係を構築できた場合、それは確かにより明確になります。

10
ShapeOfMatter

ある時点で、少なくともコンパイルするコードを取得できると想定します。これまでに取得できない場合は、愚か者の用事です。


適切な要件、仕様、またはスクリーンショットがないことは、テストを作成する上での障害にはなりません。ソースコードを読むことができる限り、テストを書くことができます。

独自のインターフェースの背後にあるデータベース接続などを分離するためにコードベースをリファクタリングする権限が与えられている場合、いくつかのブラックボックスユニットテストを作成することが可能になります。 1つの方法でコードの各行をカバーするテストを取得し、チームの上級メンバーの1人にテストをレビューしてもらいます。

ユニットテストを作成するためにコードベースをリファクタリングする権限が与えられていない場合は、完全な統合テストまたはUI自動化テストが唯一の選択肢です。それでも、ブラックボックステストが最善の戦略です。UIにいくつかの入力を投げて、それがどのように反応するかを確認します。あなたの主張をします。チームの上級メンバーにテストをレビューしてもらいます。

ある時点で、コードベースのリファクタリングを開始して自信を持って単体テストを導入できる十分な自動テストが作成されます。 UIテストでは、主要なビジネスユースケースが機能することを確認してから、ユニットまたはコンポーネントレベルのテストに役立つアーキテクチャを後付けできます。

UIテストのもう1つの利点は、コードベースを理解しているチームで評判を築くことができることです。これにより、証拠がプディングにあるため、変更を導入しやすくなります。そして、あなたは合格したテストを書くことによってプリンを作ったでしょう。

要するに:

  • ブラックボックステストを単体または自動UIテストとして記述
  • 上級メンバーにテストをレビューしてもらいます

700,000行のアプリケーションの全体像をどれだけすばやく学習できるかは驚くでしょう

3
Greg Burghardt

問題の説明とコメントに基づいて、できる限り最善の方法は、Java APIから始めて、分離されたメソッドを中心に単一の単体テストを構築することです。

コードにアクセスできないと、限られたガイダンスしか提供できませんが、a)依存関係がないb)状態が変化しないものを探します。例えば。値を受け取り、それが特定の範囲内にあることを確認するメソッドがあるとします。依存関係のないものが見つからない場合は、依存関係から値を取得するものを試し、それを模擬してみてください。

このような小さなものが見つかったら、テストの作成を開始できます。メソッドが正の値をテストする場合は、負の値を渡して、値がキャッチされることを確認します。ここでの問題は、正しい動作が何であるかがわからない場合があることです。そのためには、ドキュメントを介して、ヘルプまたはDigを要求する必要があります。

あなたはこれで非常に遠くに行くことはほとんどありません。現実には、ユニットテストが可能なようにコードを書くこと自体が芸術です。これを念頭に置いて作成されていないコードは、単体テストが不可能になる可能性があります。

より簡単に実装できるもう1つのオプションは、バイナリ互換性テストです。つまり、システムの入力と出力をキャプチャしてから、テストするためにそれらの同じ入力をフィードして、出力を比較します。これは、コードが最初から正しいか間違っているかを教えてくれませんが、他の変更を行ったときに意図せず変更された回帰エラーを検出するのに役立ちます。ただし、それを実現するには、アプリケーション全体を実行できる必要があります。

1
JimmyJames