18

以前は大規模なメソッドを持っていたクラスがあるため、このメソッドの作業を「ヘルパー」メソッドに分割しました。

これらのヘルパー メソッドはprivate、カプセル化を強制するように宣言されていますが、大きなパブリック メソッドを単体テストしたいと考えています。ヘルパー メソッドの単体テストを行うのはよいことでしょうか。そのうちの 1 つが失敗すると、それを呼び出すパブリック メソッドも失敗するため、失敗した理由を特定できますか?

また、モック オブジェクトを使用してこれらをテストするには、可視性をプライベートからプロテクトに変更する必要がありますが、これは望ましいですか?

4

9 に答える 9

13

private1 つの方法は、テストを省略して同じパッケージに入れることです。その後、テストは内部メソッドを呼び出すことができますが、他の誰も (= パッケージの外部) はできません。

また、内部メソッドが失敗すると、問題を簡単に修正できるエラー メッセージが生成されます。コードを本番環境に置くと、テストよりも少ないことがわかり、問題を迅速に修正するという大きなプレッシャーにさらされます。したがって、ここで 1 分過ごすと、1 時間後に上司があなたの首に座っているときに節約できます。

于 2009-12-07T17:06:50.093 に答える
13

これは、あなたが間違った問題を抱えているようなにおいがします。あなたが説明したことは、サブ「単体テスト」の作成に似ています。これにより、単体テストが実際に単体をテストしていると信じるようになります。

これは、あなたがやろうとしていることに対する批判ではありません。「現在の場所」から「測定可能なほど優れた別の場所」に移行することは勝利の動きです。ただし、自分がどこにいるのかを評価するために少し後退することをお勧めします。現在の状況がプラトニックな理想とどのように異なるかを理解することは、新しい可能性を示すのに役立ちます.

ここには、ヘルパー メソッドのスコープに関する提案がたくさんあります。もう 1 つの可能性は、実装を見直して、現在の実装に潜んでいるヘルパー クラスがあるかどうかを判断することです。新しいクラスとそれを実行するための一連のテストを作成することは、常に受け入れられます。

このアプローチはリファクタリングからあなたを隔離することに注意してください: テスト スイートを変更せずに実装を変更できます (ヘルパー オブジェクトが本番環境の実装の一部ではなくなった場合でも、ヘルパー オブジェクトの単体テストは引き続きパスするため)。実装とそのテストのクリーンなパッケージ化 (ユースケース: bozo-sort は間違った実装であり、もはや使用すべきではないと判断した場合。bozo-sort 実装が分離されている場合は、単純にそれとそのテストを削除します。しかし、bozo-sort 実装のテストが他のすべてのテストと絡み合っている場合、より多くの思考が必要になります)。

コードの単体テストを行う理由を確認することも役立つ場合があります。理由の 1 つが「リファクタリングを安全にするため」である場合、実装に縛られるテストを作成したくありません。

于 2009-12-07T17:53:09.693 に答える
8

クラスが本当に大きい場合は、ヘルパーメソッドだけでなく、ヘルパーオブジェクトを分割する必要があるように思われます(ただし、メソッドの抽出は多くの場合、途中のステップです)。これを行うと、古いクラスのテストがより簡単になり(おそらくモックを使用する場合もあれば、そうでない場合もあります)、新しいサポートクラスのメソッドを直接テストできます。

私の好みは、オブジェクトのパブリックAPIを介してテストすることです。それが難しすぎる場合は、オブジェクトを分割する必要があることを示唆しています。

于 2010-01-11T21:11:32.717 に答える
6

ヘルパーメソッドをテストしたい場合は、それらをプライベートから変更できますが、これを検討することもできます。

実装のプライベートな詳細を単体テストしないでください。これは主に、リファクタリングによって変更され、テストが「中断」する可能性があるためです。

于 2009-12-07T17:06:00.803 に答える
6

ここでいくつかの答えにかなりショックを受けました。

本質的に、「TDD パラダイムに違反するため、プライベート コードをテストしないでください」と言う人もいます。

いまいましいコードをテストします。必要に応じて正確に機能するようにするために、必要なことは何でもしてください。

個人的には、メソッドを保護またはデフォルトにして、テストを書き、テストを実行し、成功したらプライベートに戻します。この時点で、関連するテストをコメント アウトし、その上に命令ブロックを残します。

/** 申し訳ありませんが、混乱を招きました... * これらのメソッドをテストする必要がある場合は、ソースでそれらを公開し、次の行のコメントを解除してください */

しかし、開発方法論への厳格な順守がコードの改善の妨げになることは絶対に許してはなりません。

于 2009-12-07T18:04:30.030 に答える
1

これは、先に進んでルールを破ると私が言うケースの1つです.

クラスを最初から設計していた場合、ヘルパー メソッドを単独で単体テストしたくないことは間違いありませんが、既存のクラスをリファクタリングしているため、確実に実行しないようにするためにルールを曲げることは許容されます。何も壊さないでください。

それらを保護すると、ヘルパー自体をテストして、大きなヘアボール メソッドからロジックを引き出したときに期待どおりの動作をしていることを確認できます。リファクタリングしている大きなメソッドが、ヘルパー メソッドの特定の結果に対して期待どおりに動作することを確認できます。

しかし、その時点ではまだ完了していません。メソッドを分割しても、実際には問題の根本に到達していません。メソッドが分割され、すべてのロジックが何をするかを正確に示す一連の (やや非正統的な) テストができたので、クラス全体を再調査して、メソッドがなぜ変更されたのかを解明するのに適した位置にいます。そもそもこんなに大きい。ほとんどの場合、クラス全体を個別の責任を持つ小さなユニットに分割する必要があります。そうすれば、ルールを曲げることなく簡単にテストできます。

于 2009-12-07T17:53:44.153 に答える
0

基本的に 2 つのオプションがあります。

  1. ヘルパー メソッドのスコープをプライベートからデフォルトに増やします。その後、これらのメソッドをテストできます (テスト クラスがテスト サブジェクトと同じパッケージにあると仮定します)。これにより、クラスのテスト容易性が向上しますが、カプセル化が犠牲になります

  2. すべてそのままにしておきます。これにより、非常に細かいテストを作成できなくなりますが、カプセル化を犠牲にする必要はありません。

個人的には (2) を選択します。プライベート メソッドを実際にテストする必要はないからです。クラスは、そのパブリック インターフェイスを介してテストする必要があります (これにより、プライベート メソッドが呼び出されます。プライベート メソッドをテストすると、脆弱なテストが発生する可能性があります。つまり、クラスの内部動作のみが変更された場合に失敗するテストです。

3 番目のオプション (言及するのは気が進まない) があります。リフレクション (または他のブードゥー教) を使用して、テスト クラス内でプライベート メソッドを呼び出します。これには、(1) の欠点と、リフレクティブ コードに固有の欠点 (たとえば、型チェックがバイパスされ、読みにくい) があります。

于 2009-12-07T17:15:30.970 に答える
0

Don と Dror が言うように、メソッドを公開して単体テストを作成できるようにすると、カプセル化が壊れます。次に、特定の実装に結び付けます。それらを公開することにより、これらのメソッドが公開されたインターフェースの一部であることを世界に宣言し、したがってそれらの仕様はロックされます。

個人的には、より実用的な解決策をとります。非公開にして単体テストを作成しないことです。パブリック メソッドが失敗し、その理由がわからないが、プライベート メソッドの 1 つに問題があると思われる場合は、それらを一時的にパブリックにし、単体テストを記述し、デバッグし、完了したら、それらを再び非公開にして、単体テストをコメントアウトします。

于 2009-12-07T17:25:57.783 に答える