すべてのエンジニアリングに関する質問と同様、TDDも同じです。答えは常に「それは依存する」です。常にトレードオフがあります。
TDDの場合は、まず行動的な期待からテストを開発します。私の経験では、行動的期待は単位です。
たとえば、姓が「A」で始まるすべてのユーザーを取得したい場合、システムでアクティブになっているとします。したがって、コントローラアクションを作成してアクティブユーザーを取得するテストを作成し、 'A'で始まるものをpublic ActionResult GetAllActiveUsersThatStartWithA()
とします。最後に
、私はこのようなものかもしれません。私に
public ActionResultGetAllActiveUsersThatStartWithA()
{
var users = _repository.GetAllUsers();
var activeUsersThatStartWithA = users.Where(u => u.IsActive && u.Name.StartsWith('A');
return View(activeUsersThatStartWithA);
}
これを単位です。私は、今、リファクタリング
public IEnumerable<User> GetActiveUsersThatStartWithLetter(char startWith)
{
var users = _repository.GetAllUsers();
var activeUsersThatStartWithA = users.Where(u => u.IsActive && u.Name.StartsWith(startsWith);
}
とコントローラの私の新しい実装(下記の方法でservice
クラスを追加することで動作を変更することなく、私の実装を変更)することができます。これは明らかに非常に不自然である
public ActionResultGetAllActiveUsersThatStartWithA()
{
return View(_service.GetActiveUsersThatStartWithLetter('A');
}
なりしかし、それは私の考えのアイデアを与える。このようにすることの主な利点は、私のテストがrepository
以外の実装の詳細に縛られていないことです。私のテストでservice
を嘲笑した場合、私は今この実装に縛られています。どんな理由であれservice
レイヤーが削除されても、すべてのテストが中断します。私は、service
レイヤーがrepository
レイヤーよりも変化する可能性が高いことがわかります。
コントローラのクラスでservice
を模倣すると、すべてのテストが正常に動作するシナリオに遭遇する可能性がありますが、システムが見つかった唯一の方法は統合テスト(アウトオブプロセスまたはアセンブリコンポーネントが相互に作用することを意味します)、または生産上の問題によって発生します。例えば、私は以下にservice
クラスの実装を変更した場合
は:再び
public IEnumerable<User> GetActiveUsersThatStartWithLetter(char startsWith)
{
throw new Exception();
}
、これは非常に不自然な例ですが、ポイントはまだ関連しています。私はcontroller
テストでこれをキャッチしません。したがって、システムが私の渡す "ユニットテスト"で正しく動作しているように見えますが、実際にはシステムは全く動作していません。
私のアプローチの欠点は、テストがセットアップに非常に面倒になる可能性があることです。したがって、テストの複雑さを抽象化/モック可能な実装とバランスさせることがトレードオフです。
TDDは回帰を捉えるという利点がありますが、システムの設計には大きな利点があります。言い換えれば、あなたが書いたテストをデザインに指示させてはいけません。テストがシステムの機能を最初に指示してから、リファクタリングによる設計について心配してください。
あなたの前提は正しかったです:私はユニットテストを書いています。そして今、私は単体テストの仕方を知りました。どうもありがとうございました! – umainyosu