web-dev-qa-db-ja.com

UNITテストを適切に使用する方法とタイミング

私はiOS開発者です。

単体テストと、それを使用してコードの特定の部分をテストする方法について読みました。

非常に簡単な例は、データベースへのJSONデータの処理に関係しています。

単体テストは、プロジェクトバンドルからファイルを読み取り、JSONデータの処理を担当するメソッドを実行します。

しかし、これが実際にアプリを実行してサーバーでテストする方法とどう違うかわかりません。

だから私の質問は少し一般的かもしれませんが、私は正直に言って、ユニットテストの適切な使用法、またはそれがどのように役立つかさえ理解していません。 StackOverflowをサーフィンする経験豊富なプログラマーが私を助けてくれることを願っています。

どんな助けでも大歓迎です!

7
Zebs

ユニットテストのアイデアは、完全にモジュール化されたコード開発を可能にすることです。再利用可能で明確に焦点を絞った設計を促進するため、モジュラーコードがよい方法であることをすでにご存じでしょう。

システム全体を全体としてテストしようとすると、多くの異なる部分が失敗する可能性があります。適切なサイズのシステムでは、考えられるすべての問題を説明することはほぼ不可能です。また、問題が見つかった場合、原因となるコードを見つけるのが難しい(またはほぼ不可能)場合があります。

ただし、コードの異なる部分が他の部分から完全に分離されている場合(つまり、相互に依存していない場合)、ユニットテストを使用して、より大きなシステムのサブセットをテストできます。大量のコードではなく、少量のコードでバグを検出する方がはるかに簡単です。

提示した例では、コードの2つのスーパー部分があります。データベースからデータを取得する部分と、そしてそのデータを処理する部分。 2つを一緒にテストしようとすると、データベースアクセスの試行が原因で、テストが失敗する可能性があります。データベースの読み取り時に発生する可能性のあるネットワークおよびその他のI/Oの問題は多数あります。特に極端なケースでは、コードの処理部分のテストが非常に困難になる可能性があります。同様に、何らかの理由でコードのその部分に明確に配置されていない処理コードにバグがある可能性があります。

解決策は、単体テストを使用することです。取得と処理をテストするのではなくtogetherではなく、それらを分離します。必要なデータを処理部分にフィードして、正しく機能するかどうかを確認できます。何かがうまくいかない場合、問題は処理の問題であり、データベースの読み取りに関連していないことがわかります。同様に、簡単なテストを行って、正しい方法でそのデータベースにアクセスしようとしていることを確認できます。今回発生する問題は、データベースの読み取りに関連しているはずです。

したがって、ユニットテストは、コードの堅牢性をテストする上で非常に貴重です。また、それは非常に奨励されているデザインパターンを奨励しています。具体的には、ユニットテストの使用を考えている開発者は、コードをモジュール単位に分離できるように設計する必要があります。たとえば、グローバルな可変状態に大きく依存する関数は、結果を生成するために引数のみに依存する関数よりも、本質的に単体テストが少なくなります。

編集する

言及し忘れたことの1つは、単体テストは後付けではないということです。それらは開発プロセスの不可欠な部分であることを意図しているので、小さなコード片が堅牢であることが保証されます。これにより、開発全体を通じてコードの堅牢性が向上します。新しい部分が作成されるたびに、潜在的な欠陥を発見するためにすぐにユニットテストを行うことができます。したがって、堅牢な基盤は、堅牢なコードのどの層を記述できるかに基づいています。最終結果は、最終製品が、開発プロセスの後にテストされる同等の製品よりもはるかに高いレベルの修正度を持つ可能性が高くなります。また、テストに費やされる時間が一般的に短縮されます。

単体テストでは、アプリケーションなしでコードのモジュールをテストできます。アプリケーションが存在する前にコードをテストできます。オブジェクト指向開発では、単体テストは1つのクラスのみをテストする必要があります。統合テストは、協調して機能する複数のクラスを検証するために使用されます。幸い、多くの統合テストは、単体テストフレームワークを使用して実行できます。依存関係を満たすためにモックオブジェクトを提供する必要がある場合があるため、単一クラスのユニットテストは難しい場合があります。これは、特にデータベース関連のコードをテストする場合に当てはまります。多くの場合、例は統合テストです。

ユニットまたは統合、あるいはその両方でバンドルを取得してデータベースに処理するコードをテストしたとすると、アプリケーションのテストがより簡単になります。これで、アプリケーションがデータベースへのデータの処理に失敗した場合、実際にデータをデータベースにロードするコードの前に問題が発生する可能性が高いことがわかります。おそらく、バンドルが正しく準備されていないか、正しいハンドラーにディスパッチされていません。

ユニットテストや統合テストを行うコードが多いほど、アプリケーション全体をテストする方が簡単です。すでにテスト済みで、正しく動作することが信頼できる多くのパーツが必要になるためです。

単体テストと統合テストは、アプリケーションが完了する前に開発者またはビルドシステムがコードをテストできるという点でテストを簡素化します。航空機や車のようなものを構築するときにも、同様のテストが行​​われます。ネジから上まですべてがテストされ、それらが作業に適していることを確認します。次に、アセンブリがテストされます。そして最後に完成した製品がテストされます。これにより、テストを代替パーツに適用できるため、必要に応じてパーツを簡単に置き換えることができます。これらの手法、ユニット、統合、アプリケーションテストを適用すると、通常、より信頼性が高く、保守可能なソフトウェアが得られます。

単体または統合テスト済みのコードで問題が見つかった場合、新しいテストケースを追加して問題が解決されたことを確認するのが一般的です。これにより、テストスイートの堅牢性が徐々に向上します。

自動ビルドシステムは、多くの場合、ビルドプロセスの一部として単体テストと統合テストを実行します。これにより、ビルドシステムは、テストスイートに合格しなくなったコードにフラグを立てたり拒否したりできます。アプリケーションテストは、コードの機能についてあまり気にすることなく、ビジネスの機能性と使いやすさの検証に集中できます。

編集:私はこの質問のタイトルに答えていなかったことに気づきました。

UNITテストを使用する場合:ユニットテストを使用して、クラスまたはモジュールへのパブリックインターフェイスをテストします。簡単なコードをテストしないことを選択できます。通常、プライベートメソッドはテストされません。コードが複雑になるほど、単体テストの開発が重要になります。

ユニットテストの方法:jUnitなどのテストフレームワークを使用します(フレームワークは多くの言語用に開発されており、グループとしてxUnitと呼ばれます)。一連の入力と期待される出力を開発します。 Edgeケースと境界ケースのテストに集中してください。まだカバーされていない一般的なケースを処理するテストを追加します。これらの期待値を使用して、所定の入力が期待される結果を与えることを確認するテストケースを記述します。障害状態をテストすることを忘れないでください。

2
BillThor