5

かなり単純なアルゴリズムを開発する必要がありますが、そのテストを最適に作成する方法としては少し混乱しています。

一般的な説明:ユーザーはプランを削除できる必要があります。プランにはタスクが関連付けられています。これらも削除する必要があります(まだ実行されていない場合)。

アルゴリズムの動作としての擬似コード:

   PlanController.DeletePlan(plan)
     =>
     PlanDbRepository.DeletePlan()
      ForEach Task t in plan.Tasks
          If t.Status = Status.Open Then
            TaskDbRepository.DeleteTask(t)
          End If
      End ForEach

私が理解している限り、単体テストはデータベースにアクセスしたり、一般的に外部システムへのアクセスを必要としたりすることは想定されていないため、ここでは2つのオプションがあると思います。

1)リポジトリ呼び出しをモックアウトし、それらがアサートとして適切な回数呼び出されているかどうかを確認します

2)両方のリポジトリクラスのスタブを作成し、それらの削除フラグを手動で設定してから、適切なオブジェクトが削除対象としてマークされていることを確認します。

どちらのアプローチでも、大きな問題は次のとおりです。ここで正確に何をテストしているのでしょうか。そのようなテストが私に与えるであろう追加の価値は何ですか?

これに関する洞察をいただければ幸いです。これは、RhinoMocksを使用する必要がありますが、技術的には特定の単体テストフレームワークにリンクされていません。しかし、私は一般的な説明を好みます。そうすれば、これに頭を適切に巻き付けることができます。

4

7 に答える 7

4

リポジトリをモックしてから、単体テストでオープンタスクとクローズドタスクの両方を含むダミープランを作成する必要があります。次に、この計画を通過する実際のメソッドを呼び出し、最後に、DeleteTaskメソッドが正しい引数で呼び出されたことを確認します(ステータス=オープンのみのタスク)。このようにして、このプランに関連付けられている開いているタスクのみがメソッドによって削除されていることを確認します。また、(おそらく別の単体テストで)DeletePlanパスするオブジェクトでメソッドが呼び出されたことを表明して、プラン自体が削除されたことを確認することを忘れないでください。

于 2010-12-08T10:49:39.713 に答える
2

お気づきのとおり、アルゴリズムのロジックが期待どおりに動作することをテストしています。あなたのアプローチは正しいですが、将来を考慮してください-数か月後に、このアルゴリズムを変更する必要があるかもしれません。別の開発者がそれを切り刻んでやり直し、重要なロジックが欠落しています。これでユニットテストは失敗し、開発者は彼らの間違いについて警告されます。ユニットテストは、開始時だけでなく、数週間/数か月/数年後にも役立ちます。

さらに追加する場合は、障害の処理方法を検討してください。DBモックにdeleteコマンドで例外をスローさせ、アルゴリズムがこれを正しく処理することをテストします。

于 2010-12-08T10:55:38.073 に答える
2

テストによって提供される追加の価値は、コードが正しいことを実行することを確認することです(この場合、プランを削除し、プランに関連付けられている開いているタスクを削除し、プランに関連付けられている閉じたタスクを残します)。

リポジトリクラスのテストが実施されている(つまり、deleteが呼び出されたときに正しいことを実行する)と仮定すると、必要なのは、deleteメソッドが適切に呼び出されていることを確認することだけです。

あなたが書くことができるいくつかのテストは次のとおりです:
空の計画を削除することは呼び出すだけDeletePlanですか?
2つの開いているタスクがあるプランを削除するとDeleteTask、両方のタスクが必要になりますか?
2つの閉じたタスクを含むプランを削除しても、まったく呼び出さDeleteTaskれませんか?
開いているタスクと閉じているタスクが1つずつあるプランを削除するとDeleteTask、適切なタスクが1回呼び出されますか?

編集:しかし、私はそれを実行する方法としてダリンの答えを使用します。

于 2010-12-08T10:56:06.310 に答える
2

ダリンの答えに加えて、あなたが実際に何をテストしているのかをお話ししたいと思います。そこには、ステータスのチェックなど、ビジネスロジックが少しあります。

この単体テストは今は少し馬鹿げているように見えるかもしれませんが、コードとモデルの将来の変更についてはどうでしょうか。このテストは、この一見単純な機能が常に機能し続けることを確認するために必要です。

于 2010-12-08T10:54:20.947 に答える
1

興味深いことに、単体テストは仕様に集中するのに役立ちます。そのために、この質問をさせてください...

3つのタスクを含む計画がある場合:

Plan1 {
 Task1: completed
 Task2: todo
 Task3: todo
}

そして私はそれらを削除と呼びます、計画はどうなりますか?

Plan1 : ?
Task1: not deleted
Task2: deleted
Task3: deleted

plan1は削除され、task1は孤立していますか?または、それ以外の場合は削除済みとマークされていますか?

これは、単体テストで表示される値の大部分です(ただし、4つの値のうちの1つにすぎません:1)仕様2)フィードバック3)回帰4)粒度

テストの仕方については、モックは一切お勧めしません。私は2つの部分からなる方法を検討します最初の方法は次のようになります

public void DeletePlan(Plan p)
{ 
  var objectsToDelete = GetDeletedPlanObjects(p);
  DeleteObjects(objectsToDelete);
} 

そして、私はこの方法をテストしません。GetDeletedPlanObjectsメソッドをテストします。これは、データベースにアクセスせず、上記の状況のようなシナリオで送信できるようにします。その後、www.approvaltests.comでアサートしますが、それは別の話です:- )。

ハッピーテスト、Llewellyn

于 2013-04-23T12:17:09.523 に答える
0

IMOを使用すると、抽象を中心に単体テストを作成できます。PlanRepository同じテストは、データベース内のデータの整合性をテストする場合にも役立ちます。

たとえば、テストを書くことができます-

void DeletePlanTest()
{
    PlanRepository repo = new PlanDbRepository("connection string");
    repo.CreateNewPlan(); // create plan and populate with tasks
    AssertIsTrue(repo.Plan.OpenTasks.Count == 2); // check tasks are in open state
    repo.DeletePlan();
    AssertIsTrue(repo.Plan.OpenTasks.Count == 0);
}

このテストは、リポジトリがプランを削除し、データベースがカスケードされた削除トリガーを介して関連タスクを削除した場合でも機能します。

このようなテストの値は、テストが実行されるかどうか、PlanDbRepositoryまたはMockRepository動作が正しいかどうかをチェックするかどうかです。したがって、リポジトリコードやデータベーススキーマを変更した場合でも、テストを実行して、何も壊れていないことを確認できます。

リポジトリのすべての可能な動作をカバーするこのようなテストを作成し、それらを使用して、変更によって実装が破損しないことを確認できます。

このテストを具体的なリポジトリインスタンスでパラメータ化し、リポジトリの将来の実装でテストを再利用することもできます。

于 2010-12-08T11:06:03.113 に答える
0

私にとってこれは動作のテストではなく実装であるため、このための単体テストは作成しません。ある時点で、タスクを削除せずに「無効」または「無視」の状態に設定する動作を可能にしたい場合、単体テストは失敗します。この方法ですべてのコントローラーをテストする場合、単体テストは非常に脆弱であり、頻繁に変更する必要があります。

これについてビジネスロジックをテストし、削除の実装の詳細をクラス自体に任せる場合は、ビジネスロジックを「TaskRemovalStrategy」にリファクタリングします。

于 2010-12-08T10:58:06.357 に答える