単体テストの手続きコードは効果的ですか?


13

現在のプロジェクトでは、コードに浸透していると思われる一定量のバグを回避するために、開発サイクルにユニットテストを組み込むことを望んでいます。問題は、スパゲッティコードの95%が手続き型であり、ユニットテストを一度も行ったことがないことです(ユニットテストの経験はすべて、OOPコードを使用したことです)

簡単に言えば、私の質問は、現在のコードベースで単体テストを進めるのが賢明でしょうか、それともアプリケーションが適切なOOPフレームワークに移行されるまで延期することを提案するのでしょうか?

PS:私はこの問題を言語にとらわれないものとしてスタイル付けようとしましたが、問題のアプリケーションはPHPとjavascriptを使用していると述べると、経験からこの発生はこのようなアプリケーションで最も多く発生するため、この質問に答えることができるより具体的な回答を提供するのに役立つと感じています。


13
単体テストは新しいバグを防ぎませんが、リグレッションを防ぎます。
デニーズ

2
可能性のある複製ユニットテストジェネレーターは、レガシーコードで作業するときに役立ちましたか?他にもたくさんの質問があります。「レガシーユニットテスト」を検索
mattnz

4
あなたの問題は、コードがスパゲッティ/ Big Ball Of Mudであることであり、「手続き型」であることではありません(優れた手続き型コードは問題なくテストできます-BTDTGTTS)。あなたの力は、より多くの」テスターを獲得し、「一定量のバグを避けたい」なら、プロジェクトの徹底した専門的品質保証を手配するでしょう。
ブヨ

@ l0b0はい。私の謝罪は、テストをより明確に更新します
カナダ

@mattnz Ya手続き型単体テストを検索しましたが、レガシーは検索しませんでした。手続きのことを考え出し、その形式で作成された新しいコードはまだありますので、=レガシー!
canadiancreed

回答:


14

単体テストは、特にモックオブジェクトなどの多くの派手な機能を提供するため、オブジェクトでうまく機能します。

とはいえ、手続き型コードベースで単体テストを行うことを禁止するものはありません。OOPでは、ほとんどのユニットテストはメソッドをテストするためにいくつかのパラメーターを渡し、特定のタイプの結果または例外を期待します。これは、手続き型コードでも実行できます。ちょうどその代わりにテストする方法の、あなたは機能をテストします

以下を行う必要があることに注意してください。

  • テストする必要のある機能と不要な機能を分離します。OOPでは、これは簡単です。プライベートメソッドをテストする必要はありません。呼び出し元がメソッドに直接アクセスできないためです。手続き型コードでは、いくつかの関数はこのようなものであり、テストを必要としません。

  • グローバルスコープについて考えます。OOPにも問題がありますが、スパゲッティコードをテストする必要があると言うと、このコードを書いた人は、グローバルスコープを使いすぎたり$_GET$_POST内部で変更配列のようなクレイジーなことをするなどの悪い習慣を持っている可能性があります関数。

  • 関数外のコードを処理します。これはより複雑なケースですが、それでも可能です。require_once何が起こるかを確認しob_start/ を介して出力をキャッチob_get_cleanするページか、テストスイートからHTTP要求実行し、HTMLを解析して応答を分析します。これは実際にはUIテストではありません。ここでは、ページ上のボタンが左または右に表示されるか、リンクが大きな赤い大文字または小さな青い文字であるかは気にしません。気にするのは、DOM介していくつかのHTML要素見つけ、それらのコンテンツを予想されたものと比較することです。

  • 応答コードをテストしますrequire_once出力バッファリングは優れていますが、Webアプリケーションがエラーを処理する方法もテストする必要があります。たとえば、テストの予期される結果が404 Not Foundである場合、応答が何であるかを知るためにHTTP要求を行う必要があります。


5

アプリケーションが適切なOOPフレームワークに移行されるまで延期することを提案する

その後ではなく、別のプラットフォーム移行する前に、いくつかの自動テストを実施してください。その後ではなく、移行中にさらにテストを追加します。これらのテストが「統合テスト」または単体テストである場合、自分で決定する必要がありますが、通常は両方の種類のお気に入りのxUnitテストフレームワークを使用できます。


5

単体テストを開始する最も効果的な方法は、最も頻繁に発生する、または最もコストの高いエラーのクラスを特定することです。次に、それらのエラーを対象とするテストを作成します。

これらのテストの実装方法は、パラダイムと言語によって異なります。ユニットテストを行う能力に影響を与える最大の要素は、コードの品質です。少ないので、使用されるパラダイム。ユニットテストとは、コードの「ユニット」を単独でテストすることです。コードの「ユニット」を分離する能力に影響を与えるものはすべて、テストを難しくします。

  • グローバルの使用
  • 副作用
  • 密結合コード
  • 不十分な結合コード
  • 多数の条件
  • うまく設計されていない「ユニット」

これらはすべて、言語パラダイムよりもテストの難易度に大きな影響を与えます。


4

コードの一部を自動的にテストできる状況にあるときはいつでも、単体テストが効果的です。そのため、問題は手続き型コードを効果的に単体テストすることはできません。問題はこのコードを単体テストすることです。それは、どの程度の状態を読み取り、どの程度の状態を設定するかに依存します。理想的には両方の答えはゼロですが、そうでない場合でもテストできます。

いつものように、コードが正しいという自信と、その自信を得るためのコストを比較検討する必要があります。ユニットテストの利点の一部は、依存関係を明示的に識別することであり、その意味では、OOPコードと比較してプロシージャコードを単体テストする方がより効果的であることに注意してください。


-4

手続き型コードに対して本当の単体テストを行うことは不可能だと思います。主な問題は、各プロシージャがスタブ化できない多くの依存関係を持つ可能性が高いことです。テストはせいぜい統合テストになります。MS AccessのVB6モジュールとVBAモジュールを使用して、多くの月前に同じようなことをしました。

そうは言っても、最も苦痛を引き起こす方法の周りにテストの足場を置くことができるなら、それは価値があるはずですよね?


5
-1:悪い設計と実装が問題であり、手続き型コードではありません。ひどいOPを書くことができるように、すばらしい手続き型コードを書くことができます。
マッテンツ

@mattnz-あなたのコメントが、手続き型コードを単体テストすること、またはできないことについて私が言ったことにどのように関係するのかわかりません。
ロブ・グレー

7
手続きコードはスパゲッティとは異なります。適切に設計された、モジュール化された、きれいに分離された、凝集度の高い/結合度の低いコードを手順で記述することは非常に可能です。
マルジャンヴェネマ

2
優れた設計は、手続き型であるかどうかにかかわらず、あらゆるコードに単体テスト可能性を導入します。
ドックブラウン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.