web-dev-qa-db-ja.com

良いユニットテストを書くには?

誰かがユニットテストを学ぶために本や資料を提案できますか?

一部の人々は、ユニットテストなしのコードをレガシーコードと見なしています。現在、テスト駆動開発は、大きなソフトウェアプロジェクトを簡単に管理するためのアプローチです。私はC++が大好きです。正式な教育を受けずに自分でC++を学びました。私はこれまでユニットテストを調べたことがなかったので、取り残されたと感じます。単体テストは重要であり、長期的には役立つと思います。このトピックについて何か助けていただければ幸いです。

私の主な懸念事項は次のとおりです。

  1. 単体テストとは何ですか?分析すべきテストケースの包括的なリストですか?それでは、いくつかのメソッドを含む「複素数」というクラスがあるとします(共役、多重定義された代入演算子、多重定義された乗算演算子を見つけると言います。そのようなクラスの典型的なテストケースは何でしょうか?方法論はありますか?テストケースを選択するには?

  2. 私のために単体テストを作成できるフレームワークはありますか、またはテスト用に独自のクラスを作成する必要がありますか? Visual Studio 2008で「テスト」のオプションが表示されますが、機能しません。

  3. ユニットテストの基準は何ですか?クラスのありとあらゆる関数のユニットテストがあるべきですか?クラスごとにユニットテストを行うことは理にかなっていますか?

41
Aaron Berry

重要な点(最初は気付かなかった)は、単体テストは、完全なテスト駆動手法を適用する必要なしに、単体で使用できるテスト手法であることです。

たとえば、問題のある領域に単体テストを追加して改善したいレガシーアプリケーションがある場合や、既存のアプリのバグを見つけたい場合などです。次に、問題のあるコードを公開するための単体テストを作成し、それを修正します。これらは半テスト駆動型ですが、現在の(TDD以外の)開発プロセスに完全に適合できます。

私が役に立つと思った2冊の本は:

Microsoft .NETでのテスト駆動開発

Kent BecksのオリジナルTDDブックに続く、テスト駆動開発の非常に実践的な見解。

C#とnUnitによる実用的なユニットテスト

ユニットテストとは何か、そしてどのようにそれを適用するかという点に直接行き着きます。

あなたのポイントに応じて:

  1. ユニットテストは、実際には、アプリケーションの1つの側面/動作をテストするのに十分なだけのコードを含むクラスの単一のメソッドです。したがって、多くの場合、非常に単純な単体テストが多数あり、それぞれがアプリケーションコードのごく一部をテストします。たとえばnUnitでは、任意の数のテストメソッドを含むTestFixtureクラスを作成します。重要な点は、テストがコードの「ユニットをテストする」、つまり可能な限り最小の(賢明な)ユニットであることです。使用する基になるAPIはテストせず、作成したコードのみをテストします。

  2. テストクラスを作成する面倒な作業の一部を実行できるフレームワークがありますが、お勧めしません。実際にリファクタリングのセーフティネットを提供する有用な単体テストを作成するには、開発者がコードをテストするために何をどのようにテストするかを検討するしかありません。単体テストの生成に依存し始めた場合、それらを実行する必要がある別のタスクとして見るのは簡単すぎます。この状況に陥った場合、それは完全に間違っています。

  3. クラスごと、メソッドごとなどの単体テストの数に関する単純なルールはありません。アプリケーションコードを確認し、複雑さがどこにあるのかについての知識に基づいた評価を行い、これらの領域のテストをさらに記述する必要があります。ほとんどの人は、パブリックメソッドをテストすることから始めます。これは、これらのメソッドが通常、残りのプライベートメソッドを実行するためです。ただし、これが常に当てはまるわけではなく、プライベートメソッドをテストする必要がある場合もあります。

要するに、経験豊富なユニットテスターでさえ、明白なユニットテストを作成することから始め、次に、明白なテストを作成した後に明らかになる、より微妙なテストを探します。彼らはすべてのテストを事前に受けることを期待していませんが、頭に浮かんだら追加します。

22
Ash

質問への回答は既に承諾済みですが、まだ言及されていない他のいくつかの書籍をお勧めします。

  • レガシーコードで効果的に作業する-Michael Feathers-私が知る限り、これは、テスト容易性のために設計されていない既存のコードをテスト可能なコードに変えるというトピックに適切に取り組む唯一の本です。リファレンスマニュアルの詳細として記述され、3つのセクションに分かれています。ツールと手法の概要、レガシーコードの一般的なロードブロックに関する一連のトピックガイド、本書の残りの部分で参照されている特定の依存関係解除手法のセット。
  • アジャイルの原則、パターン、および実践-Robert C. Martin-Javaの例、C#の例の続編があります。どちらもC++に簡単に適応できます
  • クリーンコード:アジャイルソフトウェアの職人技のハンドブック-ロバートC.マーティン-マーティンは、これを彼のAPPP本の前編として説明し、私も同意します。この本はプロフェッショナリズムと自己規律、つまり真面目なソフトウェア開発者にとって2つの本質的な資質を証明します。

Robert(Uncle Bob)Martinによる2冊の本は、ユニットテストだけではなく、より多くの内容をカバーしていますが、コードの品質と生産性にとってユニットテストがいかに有益であるかを理解しています。私はこれらの3冊を定期的に参照しています。

7
Kenneth Cochran
  1. テスト駆動設計では、通常、最初にテストを記述します。実際に使用している、または使用しようとしている操作をカバーする必要があります。つまりクライアントコードがその仕事をするのに必要でない限り、それらは存在すべきではありません。テストケースの選択は、芸術のようなものです。境界条件のテストのような明白なものがありますが、結局のところ、テスト(ユニットまたはその他)が重要なすべての条件をカバーすることを保証する本当に信頼できる体系的な方法は誰も見つかりません。

  2. はい、フレームワークがあります。最もよく知られているものは次のとおりです。
    ブーストユニットテストフレームワーク
    CPPUNit

    CPPUnitはJUnitの移植版なので、以前にJUnitを使用したことがある人はおそらく快適だと思うでしょう。それ以外の場合は、Boostをお勧めする傾向があります-個々のテストの作成に役立つ Test Library もあります-便利な追加です。

  3. ユニットテストは、コードが機能することを確認するのに十分なはずです。 (たとえば)内部で使用されるプライベート関数がある場合、通常は直接テストする必要はありません。代わりに、パブリックインターフェイスを提供するものをテストします。それが正しく機能する限り、それがどのように機能するかは外の世界のビジネスではありません。もちろん、いくつかのケースでは、小さな部分をテストするのが簡単であり、そうである場合、それは完全に正当です-しかし、最終的には目に見えるインターフェースを気にします、内部ではありません。確かに、外部インターフェイス全体を実行する必要があり、一般に、コードを介したパスを実行するためにテストケースを選択します。繰り返しになりますが、単体テストと他の種類のテストには大きな違いはありません。これは通常、通常のテスト手法を適用するためのより体系的な方法です。

2
Jerry Coffin

.NETでは、Roy Osheroveによる「The Art of Unit Testing」を強くお勧めします。非常に包括的であり、優れたアドバイスが満載です。

2
Mathias

現在、テスト駆動開発は、大きなソフトウェアプロジェクトを簡単に管理するためのアプローチです。

これは、TDDを使用すると、各変更後に変更前に機能していたすべての機能が引き続き機能することを確認できるためです。 (最後に参照)

単体テストとは何ですか?分析すべきテストケースの包括的なリストですか?

ユニットテストは、コードの「ユニット」に操作を実行するように要求し、操作が実際に実行され、結果が期待どおりであることを確認するコードです。結果が正しくない場合は、エラーが発生または記録されます。

それでは、いくつかのメソッドを含む「複素数」というクラスがあるとします(共役、多重定義された代入演算子、多重定義された乗算演算子を見つけると言います。そのようなクラスの典型的なテストケースは何でしょうか?方法論はありますか?テストケースを選択するには?

理想的には、すべてのコードをテストします。

  • クラスのインスタンスを作成すると、正しいデフォルト値で作成されます

  • あなたが共役を見つけるようにそれを頼むとき、それは正しいものを見つけます(ゼロのための共役のような境界ケースもテストします)

  • 値を割り当てると、値が割り当てられ、正しく表示されます

  • 複素数に値を乗算すると、正しく乗算されます

私のためにユニットテストを作成できるフレームワークはありますか、またはテスト用に独自のクラスを作成する必要がありますか?

CppUnit を参照

Visual Studio 2008で「テスト」のオプションが表示されますが、機能しません。

よくわかりません。私はVS 2008を使用していませんが、.NETでのみ使用できる場合があります。

ユニットテストの基準は何ですか?クラスのありとあらゆる関数のユニットテストがあるべきですか?クラスごとにユニットテストを行うことは理にかなっていますか?

はい、そうです。これはコードを書く(変更のたびに維持する)とてつもない数のコードですが、大規模なプロジェクトの費用は支払う価値があります。コードベースへの変更によって、期待どおりの結果が得られることが保証されます他には何もありません

また、変更を行う場合は、その変更の単体テストを更新する必要があります(それらが再度パスするようにするため)。

TDDでは、まずコードに何を実行させたいか(たとえば、複素数クラス)を決定し、次にそれらの演算を検証するテストを記述してから、テストが正しくコンパイルおよび実行されるようにクラスを記述します(それ以上は行いません)。

これにより、可能な限り最小限のコードを記述し(そして複雑なクラスの設計を複雑にしすぎないようにする)、コードが実行することを確実にします。コードの記述の最後に、コードの機能をテストして、コードが正しいことを確認する方法があります。

また、いつでもアクセスできるコードの使用例もあります。

さらに読む/ドキュメント化するには、「依存性注入」とユニットテストおよびTDDで使用されるメソッドスタブを調べてください。

2
utnapistim

ユニットテストは、コードの特定の本体を実行して、定義された条件のセットが期待される結果セットにつながることを確認するための単純な方法です。スティーブンが指摘しているように、これらの「演習」はさまざまな基準(「BICEP」)をチェックする必要があります。はい。理想的には、すべてのクラスとこれらのクラスのすべてのメソッドをテストする必要がありますが、常に判断の余地があります。テストはそれ自体で終わりではなく、より広いプロジェクト目標をサポートする必要があります。

OK、それで...理論はいいですが、ユニットテストを本当に理解するには、適切なツールをまとめて、すぐに始めることが私の推奨です。プログラミングのほとんどのことと同様に、適切なツールがあれば、実行することで簡単に学ぶことができます。

まず、 NUnit のコピーを取得します。これは無料で、インストールが簡単で、操作も簡単です。いくつかのドキュメントが必要な場合は、チェックアウトしてください C#とNUnitを使用した実用的なユニットテスト

次に、 http://www.testdriven.net/ に移動して、TestDriven.netのコピーを取得します。これはVisual Studio 2008にインストールされ、ファイル、ディレクトリ、またはプロジェクトに対してNUnitテストを実行する機能(通常、テストは別のプロジェクトに書き込まれます)を含むさまざまなテストツールへの右クリックアクセスを提供します。また、デバッグを使用してテストを実行することも、最も優れた点として、NCoverのコピーに対してすべてのテストを実行することもできます。 NCoverは、どのコードが実行されているかを正確に表示するので、テストカバレッジを改善する必要がある場所を特定できます。 TestDriven.netのプロフェッショナルライセンスは170ドルですが、私のような人であれば、すぐにツールボックスの不可欠なツールになります。とにかく、私はそれが優れた専門的な投資であることを発見しました。

幸運を!

1

Visual Studio 2008の質問にはお答えできませんが、 Netbeans には、使用できる統合ツールがいくつかあります。

  1. コードカバレッジ2では、チェックされたパスと、ユニットテストで実際にカバーされているコードの量を確認できます。
  2. 組み込みの単体テストのサポートがあります。

テストの品質に関しては、Andrew HuntとDavid Thomasによる " Pragmatic Unit Testing in Java with JUnit ")から少し借りています。

ユニットテストでは[〜#〜] bicep [〜#〜][〜#〜] bをチェックする必要があります[〜#〜]oundary、[〜#〜] i [〜#〜]nverse relationship、[〜#〜] c [〜#〜]ross-checking、[〜#〜] e [〜#〜 ]エラー条件、および[〜#〜] p [〜#〜]パフォーマンス。

また、テストの品質はA-TRIPによって決定されます:[〜#〜] a [〜#〜] 自動、[〜#〜] t [〜#〜]詳細、[〜#〜] r [〜#〜]繰り返し可能、[〜#〜] i [〜#〜]ndependent、および[〜#〜] p [〜#〜]rofessional。

1
monksy

現在、テスト駆動開発は、大きなソフトウェアプロジェクトを簡単に管理するためのアプローチです。

TDDは単体テストに基づいていますが、それらは異なります。単体テストを利用するためにTDDを使用する必要はありません。私の個人的な好みは、最初にテストを書くことですが、私はTDDのすべてを行うとは思いません。

単体テストとは何ですか?

ユニットテストは、1つのユニットの動作をテストする少しのコードです。 1つの単位の定義方法は人によって異なります。しかし、一般的には次のとおりです。

  1. すぐに実行
  2. 互いに独立している
  3. コードベースのごく一部(ユニット;)のみをテストします。
  4. バイナリの結果-つまり、合格または不合格です。
  5. ユニットの1つの結果のみをテストする必要があります(結果ごとに異なるユニットテストを作成します)
  6. 繰り返し可能

単体テストを作成できるフレームワークはありますか

テストを書くために-はい、しかし私は誰かが彼らについて何かいいことを言うのを見たことがありません。
テストの作成と実行を支援するために、テストの 全体

クラスのありとあらゆる関数のユニットテストがあるべきですか?

あなたはこれにいくつかの異なるキャンプを持っています-100%の人はイエスと言うでしょう。すべてのメソッドをテストする必要があり、100% コードカバレッジ が必要です。もう1つの極端な点は、単体テストでは、バグに遭遇したり、バグを発見したりする可能性のある領域のみをカバーすることです。中立的な立場(そして私がとる立場)は、「破壊するのが単純すぎる」ではないすべてのものを単体テストすることです。セッター/ゲッター、および他の単一のメソッドを呼び出すだけのもの。私は80%のコードカバレッジと低い [〜#〜] crap [〜#〜] ファクターを目指しています(そのため、私はいたずらで、何かをテストしないことに決めました "テストするには複雑すぎます)。

ユニットテストの「取得」に役立つ本 JUnit in Action 。申し訳ありませんが、C++の世界ではあまり機能していないため、C++ベースの代替案を提案することはできません。

単体テストを作成しない場合(つまり、実行可能であり、単体テストをスキップするほうが好ましい場合)は、次のとおりです。 1つの内部実装をテストするか、パブリック動作のみをテストする必要がありますか?

短い答えは:

  • 統合テストを自動化できる場合(自動テストを行うことが重要ですが、それらのテストは単体テストである必要はないため)
  • 統合テストスイートを実行するのが安価な場合(実行に2日かかる場合、またはすべての開発者に統合テスト装置へのアクセスを許可する余裕がない場合)
  • 統合テストの前にバグを見つける必要がない場合(コンポーネントが個別に開発されているか、段階的に開発されているかに一部依存します)
0
ChrisW

本「xUnit Test Patterns:Refactoring Test Code」を購入してください。その非常に優れています。高レベルの戦略決定と低レベルのテストパターンをカバーしています。

0