クラス/モジュール/パッケージ/などの内部/プライベートコンポーネントをどのくらいユニットテストしますか?それらをまったくテストしますか、それとも単に外界へのインターフェースをテストしますか?これらの内部の例は、プライベートメソッドです。
例として、1つの中央手続きから呼び出されるいくつかの内部手続き(関数/メソッド)がある 再帰降下パーサー を想像してください。外の世界への唯一のインターフェースは、文字列を取り、解析された情報を返す中心的な手順です。他のプロシージャは文字列のさまざまな部分を解析し、中央のプロシージャまたは他のプロシージャから呼び出されます。
当然、サンプル文字列を使用して呼び出し、手作業で解析した出力と比較することにより、外部インターフェイスをテストする必要があります。しかし、他の手順はどうですか?それらを個別にテストして、部分文字列が正しく解析されることを確認しますか?
私はいくつかの議論を考えることができます:
長所:
短所:
あなたの意見は何ですか?
Case:「モジュール」(広義には、パブリックインターフェースと、場合によってはいくつかのプライベート内部パーツを持つもの)には、内部に複雑な/複雑なロジックがあります。モジュールインターフェースのみをテストすることは、モジュールの内部構造に関連する統合テストのようなものです。したがって、エラーが検出された場合、そのようなテストは、障害の原因となっている正確な内部/コンポーネントを特定しません。
ソリューション:複雑な内部パーツをモジュール自体に変換し、それらを単体テストして(複雑すぎる場合はこれらのステップを繰り返して)、元のモジュールにインポートします。これで、uniit-test(動作が正しいことを確認し、エラーを修正する)を簡単に行うのに十分単純なモジュールのセットが手に入りました。これですべてです。
注:
「サブモジュール」が新しい/変更された契約を満たすのに十分なサービスを提供しない場合を除き、モジュールの契約を変更するときに、モジュールの(以前の)「サブモジュール」のテストで何も変更する必要はありません。
不必要なことは何も行われませんpublicつまり、モジュールのコントラクトが保持され、カプセル化が維持されます。
[更新]
オブジェクトのパブリックインターフェースを介して入力を供給するだけで、オブジェクトの内部パーツ(つまり、プライベートにインポートされたモジュール/パッケージではないメンバー)を適切な状態にすることが難しい場合に、いくつかのスマート内部ロジックをテストするには:
フレンド(C++の用語で)またはパッケージ(Java)にアクセスして、内部から実際に状態を設定し、必要に応じて動作をテストするテストコードを用意するだけです。
FSMベースのコードへのアプローチは、従来使用されているものとは少し異なります。これは、ハードウェアテスト(通常はFSMでもあります)の説明 here とよく似ています。
つまり、特定の出力を生成するだけでなく、特定の「不良」出力を生成するときに、障害の性質によって障害のあるコンポーネントを特定できるテスト入力シーケンス(または一連のテスト入力シーケンス)を作成します。このアプローチは非常にスケーラブルであり、テスト設計に費やす時間が長いほど、テストの品質が向上します。
この種のテストは、いわゆる「機能テスト」に近いものですが、実装に少し触れるたびにテストを変更する必要がなくなります。
まあ-それは依存します:-)。 BDD(Behaviour Driven Development)またはATDD(Acceptance Test Driven Development)アプローチを使用している場合、パブリックインターフェイスのテストは問題ありません(さまざまな入力で徹底的にテストする限り)。プライベートメソッド(プライベートメソッドなど)は実際に重要です。
ただし、そのアルゴリズムの一部を特定の時間枠内または特定のbigO曲線(nlognなど)に沿って実行したい場合は、個々の部分をテストすることが重要です。これを従来のTDD /ユニットテストアプローチと呼ぶ人もいます。
すべてのように、YMMV
ParseQuotedString()
、ParseExpression()
、ParseStatement()
、ParseFile()
などの機能的な意味を持つ複数の部分に分割し、それらをすべて公開します。構文が大きく変化し、これらが無関係になる可能性はどのくらいありますか?