ビジネスロジックが変更されたときに失敗した場合、単体テストは脆弱と見なされますか?


27

以下のコードをご覧ください。女性の性別を持つ人がoffer1に適格であるかどうかをテストします。

[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
    var personId = Guid.NewGuid();
    var gender = "F";
    var person = new Person(personId, gender);

    var id = Guid.NewGuid();
    var offer1 = new Offer1(id,"Offer1");
    Assert.False(offer1.IsEligible(person));
}

この単体テストは成功します。ただし、今後「Offer1」が女性に提供されると、失敗します。

言うことは受け入れられますか?オファー1を取り巻くビジネスロジックが変更された場合、ユニットテストは変更されなければなりません。データベースによっては、ビジネスロジックが次のように変更される場合があります(一部のオファーでは)。

update Offers set Gender='M' where offer=1;

そして、このようなドメインモデルの場合には:

if (Gender=Gender.Male)
{
  //do something
}

また、背後のドメインロジックが定期的に変更を提供する場合と、そうでない場合もあることに注意してください。


2
別の角度から考えます。テスト対象のシステムのロジックを変更しても、失敗しないテストが必要ですか?
ファビオ

回答:


77

これは通常の意味では脆くない。ユニットテストは、テスト中の動作に影響を与えない実装の変更により破損した場合、脆弱であると見なされます。しかし、ビジネスロジック自体が変更された場合、このロジックのテストは中断されるはずです。

ただし、ビジネスロジックが実際に頻繁に変更される場合、単体テストに期待をハードコードすることはおそらく適切ではありません。代わりに、データベース内の構成が期待どおりにオファーに影響するかどうかをテストできます。

テストの名前はReturns False When Given A Person With A Gender Of Femaleビジネスルールを説明していません。ビジネスルールは次のようになりOffers Applicable to M should not be applied to persons of gender Fます。

あなたがテストを書くことができるようにそのことを確認した場合にはオファーがM人数を入力するだけで該当するとして定義され、その後、タイプFの人はそれの対象として示されることはありません。このテストは、特定のオファーの構成が変更された場合でも、ロジックが機能することを確認します。


@JaquesB、それは単体テストではないでしょうか?またはそれだろうか?データベースが含まれていれば、統合テストになると思います。そうですか?ビジネスロジックが大きく変化する場合、単体テストを使用しないでください。
w0051977

@ w0051977:テストの書き方に依存します。テストに実際にデータベース内の何かを変更する変更が含まれている場合、それは統合テストになります。
ジャックB

3
@ w0051977より良いアイデア-リポジトリを、ビジネスルールの実装を担当するコンポーネントの依存関係にしないでください。リポジトリを呼び出してからビジネスルールを呼び出す高レベルのオーケストレーションがあります。これで、ビジネスルールを単体で単体テストできます。
Ant P

5
@ w0051977もちろんそうです-テストは動作を指定します。コンポーネントの動作を管理するルールが変更された場合、動作の変更を反映するためにテストを変更する必要があります。何べきではありません変更する必要があることは変更されているもの以外の動作を指定するテストです。動作がデータベースによって決定される場合、他のコードを対象とするテストは本質的に無関係であり、そのデータベースロジックがテストの範囲内にない限り変更する必要はありません。その範囲はユーザーが定義するものであり、単体テストであるか統合テストであるかのセマンティクスはあまり重要ではありません。
Ant P

3
@ w0051977ビジネスロジックの変更またはバグが修正され、テストを調整する必要がない場合は、テストが十分なケースをカバーしておらず、一般に拡張する必要があることを示しています。
モルゲン

14

プロパティは本番データベース(またはテスト用クローン)で定義されている場合、これはない単体テスト。単体テストは作業単位をチェックし、特定の外部状態が機能することを要求しません。これはOffer1、データベースで男性のみのオファーとして定義されていることを前提としています。それが外部状態です。したがって、これは統合テスト、具体的にはシステムまたは受け入れテストに近いものです。多くの場合、受け入れテストはスクリプト化されていません(テストフレームワークでは実行されませんが、人間が手動で実行します)。

ドメインモデルでifステートメントを使用してプロパティが定義されている場合、同じテストは単体テストです。そして、それはもろいかもしれません。しかし、実際の問題は、コードが脆弱であることです。一般的なルールとして、ビジネスの動作をハードコーディングするのではなく設定できる場合、コードの復元力が高まります。小さなコーディングエラーを修正するために急いで展開することはまれです。しかし、ビジネス要件が予告なしに変更されるのは、火曜日(毎週発生するもの)にすぎません。

単体テストフレームワークを使用してテストを実行している可能性があります。ただし、単体テストフレームワークは、単体テストの実行に限定されません。統合テストも実行できます。

あなたはユニットテストを書いていた場合は、両方を作成しますpersonoffer1、データベースの状態には依存して地面から。何かのようなもの

[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
    var personId = Guid.NewGuid();
    var gender = "F";
    var person = new Person(personId, gender);

    var id = Guid.NewGuid();
    var offer1 = new Offer1(id, "ReturnsFalseWhenGivenAPersonWithAGenderOfFemale");
    offer1.markLimitedToGender("M");

    Assert.False(offer1.IsEligible(person));
}

これはビジネスロジックに基づいて変化しないことに注意してください。offer1女性を拒否することを主張しているのではありません。それはoffer1女性を拒絶するタイプの申し出をしている。

テストの一部としてデータベースを作成および構成できます。C#では、NUnitを使用して、またはJavaのJUnitでは、Setupメソッドでデータベースをセットアップします。おそらく、テストフレームワークには同様の概念があります。この方法では、SQLを使用してデータベースにレコードを挿入できます。

実稼働データベースの代わりにテストデータベースを使用するコードを記述することが難しい場合、アプリケーションのテストの弱点のように聞こえます。テストでは、置換を許可する依存性注入のようなものを使用する方が良いでしょう。次に、現在のビジネスルールに依存しないテストを作成できます。

これの副次的な利点は、多くの場合、ビジネスオーナー(必ずしも企業オーナーではなく、企業階層のこの製品の責任者のような)がビジネスルールを直接構成しやすいことです。この種の技術的なフレームワークがある場合、ビジネスオーナーがユーザーインターフェイス(UI)を使用してオファーを構成できるようにするのは簡単だからです。ビジネスオーナーはUIで制限を選択し、markLimitedToGender("M")呼び出しを発行します。その後、オファーがデータベースに永続化されると、これが保存されます。しかし、それを使用するためにオファーを保存する必要はありません。そのため、テストでは、データベースに存在しないオファーを作成および構成できます。

説明したシステムでは、ビジネスオーナーが技術グループにリクエストを送信する必要があります。技術グループは適切なSQLを発行し、テストを更新します。または、技術グループがコードとテスト(またはテストとコード)を編集する必要があります。それはかなり重いアプローチのようです。できます。ただし、テストするだけでなく、ソフトウェアの脆弱性はそれほど高くありません。

TL; DR:このようなテストを書くことはできますが、ソフトウェアを書く方がよいので、そうする必要はありません。


私はあなたの答えのいくつかの小さな詳細を改善する自由を提供します。あなたの意図が正しいかどうか確認してください。
Doc Brown

元の投稿には、データベースが関係しているという兆候はありません。そのため、Offer1がすでにデータベースにあると想定するのは奇妙です。
ウィンストンユワート

2
@WinstonEwert:明確な兆候があります。質問をもっと注意深く読む必要があります。私も最初の読み物でそれを理解していませんでしたが、それは実際にOPが話していることです。
Doc Brown

@ mdfst13、それを見逃してすみません。ただし、OPが言っているのは、条件がデータベース内にある場合とドメインモデル内にある場合があることです。あなたの答えは、最初のケースでは完全に、2番目のケースでは不i好です。その点を明確にするために回答を編集する場合は、急いで下票を削除します。
ウィンストンユワート
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.