web-dev-qa-db-ja.com

大きな関数を小さな関数にリファクタリングするときに追加の単体テストを作成することの価値は何ですか?

複雑な単体テスト済み関数がある場合:

def do_everything():
    # turn twizzles
    # Push buttons
    # move mountain

そして、それをいくつかの小さな単位にリファクタリングします:

def do_everything():
    turn_twizzles()
    Push_buttons()
    move_mountain()

def turn_twizzles():
    # turn twizzles

def Push_buttons():
    # Push buttons

def move_mountain():
    # move mountain

これらの小さなユニット用の追加の単体テストを書くのに時間を無駄にしていますか?

8
Adam Terrey

do_everything()の動作をカバーする単体テストはすでにあると思いますか? turn_twizzles()などをプライベートメソッドとして破壊した場合、外部の動作は変更されていないため、テストを変更する必要はありません。

ただし、turn_twizzles()が公開されている場合は、(クラスの外部から見た)新しい機能が導入されているため、これをテストすることは重要です。

15
JacquesB

場合によりますより正確には、

  • 元の機能の複雑さ(非常に複雑だった場合は、各部分を独自にテストすると効果があります)
  • 小さな機能の複雑さ(それ自体が複雑な部分である場合、それらを個別にテストすると、よりきめの細かいテストと、欠陥の場合のより正確な根本原因の検出につながります)
  • 既存の単体テスト(これらすべての「パーツ」に対して十分なカバレッジがすでに生成されている場合は、個別のテストを記述する価値はおそらくないでしょう)
  • これらの小さい関数を元の関数の「実装の詳細」にしたい場合、または保持しない場合(前者の場合、小さい関数の単体テストを作成すると、この目標に対して逆効果になります)。

特に、これらの「小さい関数」が例のように簡単ではないが、多少複雑な入力パラメーターのリストがある場合、小さい関数がテストされることを保証するために元の関数の十分な単体テストを作成するのは非常に難しくなる可能性があります。すべての「興味深い」入力の組み合わせ。これは、より小さな関数用の特定の単体テストを作成する明確な兆候でもあります。

したがって、この質問に明確な「はい」または「いいえ」はありません。ケースごとに決定する必要があるトレードオフです。

12
Doc Brown

turn_twizzlesPush_buttons、およびmove_mountainがパブリックであり、他のコードによって呼び出される場合、これらの関数を個別にテストするためにテストをリファクタリングすることが重要だと思います。

残念ながら、リファクタリング後に問題が発生します:do_everythingを単体テストするには、turn_twizzlesPush_buttons、およびmove_mountainをモックできる必要があります。依存関係をモックせずにdo_everythingのテストを作成すると、統合テストになります。テスト計画によっては必ずしも悪いことではありませんが、すでに3つの小さな関数を個別にテストしているので、あまりメリットはありません。これは、このコンポーネントを再設計し、他のオブジェクトと協力してdo_everythingのすべての作業を行う適切なタイミングかもしれません。

turn_twizzlesPush_buttons、およびmove_mountainが外部から呼び出されない場合は、プライベートとしてマークする必要があります。do_everythingとは別にテストすることはお勧めしません。これは、外から見て、do_everythingが最小単位になるためです(他のものがアクセスできないため)。プライベートメソッドを使用してメソッドを分割する方法についても この回答 を参照してください。

6
Samuel

いいえ。追加の単体テストはより正確です。 move_mountain失敗した場合、1つのテストが失敗し、何が問題だったかが具体的に示されます。

その精度により、デバッグ時間が短縮されます。これは貴重なことです。また、テストの焦点が絞られているため、全機能を介して同じ機能をテストするよりも実行速度が速く、フィードバックを迅速に提供できるため、貴重です。

4
Telastyn