18

これは別の質問について少し話し合うきっかけになったようで、私はそれ自身の質問にスピンする価値があると思いました。

DRYの原則は、メンテナンスの問題と戦うための私たちの選択の武器のようですが、テストコードのメンテナンスについてはどうでしょうか。同じ経験則が適用されますか?

開発者テストコミュニティのいくつかの強い声は、セットアップと分解は有害であり、避けるべきであるという意見です...いくつか例を挙げると:

実際、xUnit.netは、まさにこの理由でフレームワークからそれらを完全に削除しました(ただし、この自主的な制限を回避する方法はあります)。

あなたの経験は何ですか?セットアップ/ティアダウンは、保守性のテストに悪影響を及ぼしますか、それとも役立ちますか?

更新:JUnit4やTestNG(@ BeforeClass、@ BeforeGroupsなど)で利用できるようなよりきめ細かい構造が違いを生むでしょうか?

4

9 に答える 9

11

セットアップおよびティアダウン メソッドの有効な使用法の大半 (すべてではないにしても) は、セットアップ/ティアダウン パラダイムに悩まされているように見える問題に陥ることなく DRY を可能にするファクトリ メソッドとして記述できます。

ティアダウンを実装している場合、これは通常、単体テストではなく、統合テストを行っていることを意味します。多くの人がこれを分解しない理由として使用していますが、IMO には統合と単体テストの両方があるはずです。個人的にはそれらを別々のアセンブリに分けますが、優れたテスト フレームワークは両方のタイプのテストをサポートできるはずだと思います。すべての優れたテストが単体テストになるわけではありません。

ただし、セットアップでは、テストを実際に実行する前に何かを行う必要がある理由がいくつかあるようです。たとえば、テストの準備をするためのオブジェクト状態の構築 (たとえば、依存性注入フレームワークのセットアップ)。これはセットアップの正当な理由ですが、工場で簡単に行うことができます。

また、クラス レベルとメソッド レベルのセットアップ/ティアダウンには違いがあります。何をしようとしているのかを考えるときは、このことを念頭に置いておく必要があります。

セットアップ/ティアダウン パラダイムを使用する際に発生した最大の問題は、テストが常に同じパターンに従っていないことです。これにより、代わりにファクトリ パターンを使用するようになりました。これにより、DRY を使用できると同時に、読みやすく、他の開発者を混乱させることはありません。工場ルートをたどり、ケーキを食べて食べることができました。

于 2009-07-06T14:41:08.797 に答える
2

彼らは私たちのテストの保守性を本当に助けてくれました. 私たちの「単体」テストは、実際には、DB に書き込み、結果をチェックする完全なエンドツーエンドの統合テストです。私のせいではありません。私がここに来たとき、彼らはそうでした。私は状況を変えるために取り組んでいます。

とにかく、1 つのテストが失敗した場合、次のテストに進み、最初のテストから同じユーザーを DB に入力しようとし、一意性制約に違反し、そこから失敗が連鎖しました。ユーザーの作成/削除を [Fixture][SetUp|TearDown] メソッドに移動することで、すべてが混乱することなく失敗した 1 つのテストを確認できるようになり、私の人生はずっと楽になり、安定したものになりました。

于 2009-07-06T14:42:00.230 に答える
2

DRY の原則は、コードと同じようにテストにも適用されると思いますが、その適用は異なります。コードでは、コードの 2 つの異なる部分で文字通り同じことを行わないようにするために、はるかに長い時間を費やします。テストでは、それを行う必要がある (同じセットアップを何度も行う) ことは確かに臭いですが、解決策は必ずしも重複をセットアップ メソッドに除外することではありません。クラス自体で状態を設定しやすくするか、テスト中のコードを分離して、この量の状態に意味があるかどうかにあまり依存しないようにすることができます。

テストごとに 1 つのことだけをテストするという一般的な目標を考えると、特定のケース (特定のタイプのオブジェクトの作成など) で同じことを何度も何度も行うことを避けることは実際には不可能です。それがたくさんある場合は、パラメータ化されたテストなどを導入するなど、テストのアプローチを再考する価値があるかもしれません。

セットアップとティアダウンは、主に環境を確立するためのもの (環境を運用環境ではなくテスト環境にするためのインジェクションなど) であるべきであり、テストの一部であるステップを含めるべきではないと思います。

于 2009-07-06T14:43:54.343 に答える
2

私はジョセフが言わなければならないことすべてに同意します。特に、tearDown が統合テストを書く兆候であるという部分 (そして、99% の時間は私がそれを使用したものです) に同意しますが、それに加えて、セットアップの状況は、テストを論理的にグループ化する必要がある場合と、複数のテスト クラスに分割する必要がある場合の適切な指標です。

レガシ コードにテストを適用する場合、大規模なセットアップ メソッドに問題はありませんが、セットアップはスイート内のすべてのテストに共通する必要があります。setup メソッドが実際に複数のセットアップを実行していることに気付いたら、テストを複数のケースに分割します。

「テスト駆動」の例に従い、セットアップ方法はテストケースの重複を取り除くことから得られます。

于 2009-07-06T15:03:12.753 に答える
1

テストのセットアップとティアダウンの方法自体には問題はありません。

私にとっての問題は、テストのセットアップと破棄の方法がある場合、各テストで同じテスト オブジェクトが再利用されていることを意味することです。テスト間で状態の一部の要素をクリーンアップするのを忘れた場合、テスト結果が順序に依存する可能性があるため、これは潜在的なエラー ベクトルです。本当に必要なのは、状態を共有しないテストです。

xUnit.Net は、実行されるテストごとに新しいオブジェクトを作成するため、セットアップ/ティアダウンを取り除きます。つまり、コンストラクターがセットアップ メソッドになり、ファイナライザーがティアダウン メソッドになります。テスト間で (オブジェクト レベルの) 状態が保持されないため、この潜在的なエラー ベクトルが排除されます。

私が作成するほとんどのテストには、必要なモックを作成し、テスト対象のオブジェクトをモックに接続するだけであっても、ある程度のセットアップが必要です。彼らがしないことは、テスト間で状態を共有することです。ティアダウンは、その状態を共有しないようにするだけです。

于 2009-07-07T03:33:37.000 に答える
1

私は Java と Python でかなり頻繁に setup を使用し、共同作業者 (本物かテストかによって異なります) をセットアップするために頻繁に使用します。テスト対象のオブジェクトにコンストラクターがない場合、またはコンストラクターとしてコラボレーターのみがある場合は、オブジェクトを作成します。単純な値クラスの場合、通常は気にしません。

Java でティアダウンを使用することはめったにありません。Python では、グローバルな状態を変更する可能性が高かったため、より頻繁に使用されていました (特に、それらのモジュールのユーザーをテスト対象にするためにモジュールにパッチを適用するサル)。その場合、テストが失敗した場合に呼び出されることが保証されるティアダウンが必要です。

統合テストと機能テスト (xunit フレームワークを使用することが多い) では、セットアップとティアダウンが必要になる可能性が高くなります。

覚えておくべきポイントは、DRYだけでなくフィクスチャについても考えることです。

于 2009-07-06T15:06:22.763 に答える
0

単体テストを機能させるためにセットアップと分解が必要な場合、本当に必要なのはモック オブジェクトではないでしょうか?

于 2009-07-07T03:43:48.840 に答える
0

あなたが投稿した両方を読む時間がありませんでしたが、特に次のコメントが気に入りました。

各テストは、実行するために必要なものの初期化を強制されます。

セットアップと破棄は便利なメソッドです。デフォルト コンストラクターなどを使用してクラスを初期化する以上のことを行うべきではありません。5 つのテスト クラスで 3 つのテストが必要とする共通コードはそこに表示されません。このコードを直接呼び出す必要があります。これにより、一般的な初期化ルーチンを変更したという理由だけで、テストが互いに足を踏み入れたり、一連のテストを壊したりすることもなくなります。主な問題は、これが特定のテストだけでなく、すべてのテストの前に呼び出されることです。ほとんどのテストは単純である必要があり、より複雑なものには初期化コードが必要になりますが、セットアップ時の複雑な初期化と破棄時の複雑な破棄をトレースする必要がない場合、単純なテストの単純さを簡単に確認できます。テストが実際に何を達成することになっているのかを考えます。

于 2009-07-06T14:42:49.400 に答える
0

個人的には、セットアップとティアダウンが常に悪であるとは限らず、この推論は少し独断的であることがわかりました。しかし、それらを単体テストのコードの匂いと呼んでも問題ありません 。いくつかの理由から、それらの使用は正当化されるべきだと思います:

  1. テスト コードは、その性質上手続き型です。一般に、セットアップ/分解テストの可読性/フォーカスを低下させる傾向があります。
  2. セットアップ メソッドは、単一のテストに必要なものよりも多くを初期化する傾向があります。乱用すると、扱いにくくなる可能性があります。オブジェクト マザー、テスト データ ビルダー、おそらく FactoryGirl のようなフレームワークは、テスト データの初期化に適しているようです。
  3. それらは「コンテキストの肥大化」を促進します。テスト コンテキストが大きくなればなるほど、保守性が低下します。

私のセットアップ/ティアダウンがこれを行わない限り、それらの使用は正当化されると思います。テストでは常に重複が発生します。Neal Ford はこれを次のように述べています

私自身で作業しているので、これが実際に問題になったことはありません。しかし、チーム環境でテスト スイートを維持するのは非常に難しいことがわかりました。その理由は、お互いのコードをすぐには理解できないか、理解するためにコードをステップ実行する必要がないためです。テストの観点からは、テストの重複を許可すると、この負担が軽減されることがわかりました。

ただし、他の人がこれについてどう感じているかを聞きたいです。

于 2009-07-06T14:43:39.493 に答える