TDDアプローチを使用することを自分で学びたいと思っていたので、しばらくの間、やりたいプロジェクトがありました。大規模なプロジェクトではなかったので、TDDの良い候補になると思いました。しかし、何かがおかしくなったように感じます。例を挙げましょう:
高レベルでは、私のプロジェクトはMicrosoft OneNoteのアドインであり、プロジェクトをより簡単に追跡および管理できます。また、いつか自分のカスタムストレージとバックエンドを構築することにした場合に備えて、このためのビジネスロジックをOneNoteから可能な限り切り離したままにしておきたいと考えました。
最初に、基本的な平易な言葉の受け入れテストから始めて、最初の機能で何をしたいかを概説しました。これは次のようなものです(簡潔にするために説明を省略しています)。
- ユーザーがプロジェクトの作成をクリックします
- プロジェクトのタイトルにユーザーが入力する
- プロジェクトが正しく作成されたことを確認します
UIのものといくつかの中間計画をスキップして、最初のユニットテストに行きます。
[TestMethod]
public void CreateProject_BasicParameters_ProjectIsValid()
{
var testController = new Controller();
Project newProject = testController(A.Dummy<String>());
Assert.IsNotNull(newProject);
}
ここまでは順調ですね。赤、緑、リファクタリングなど。今では実際に保存する必要があります。ここでいくつかの手順を省略して、これで終わります。
[TestMethod]
public void CreateProject_BasicParameters_ProjectMatchesExpected()
{
var fakeDataStore = A.Fake<IDataStore>();
var testController = new Controller(fakeDataStore);
String expectedTitle = fixture.Create<String>("Title");
Project newProject = testController(expectedTitle);
Assert.AreEqual(expectedTitle, newProject.Title);
}
私はまだこの時点で気分が良いです。私はまだ具体的なデータストアを持っていませんが、私はそれがどのように見えるか予想したインターフェイスを作成しました。
この投稿は十分に長くなっているので、ここでいくつかの手順をスキップしますが、同様のプロセスに従って、最終的にデータストアのこのテストに進みます。
[TestMethod]
public void SaveNewProject_BasicParameters_RequestsNewPage()
{
/* snip init code */
testDataStore.SaveNewProject(A.Dummy<IProject>());
A.CallTo(() => oneNoteInterop.SavePage()).MustHaveHappened();
}
これを実装するまでは良かったです。
public String SaveNewProject(IProject project)
{
Page projectPage = oneNoteInterop.CreatePage(...);
}
そして、「...」のあるところに問題があります。この時点で、CreatePageにはセクションIDが必要であることがわかりました。コントローラーに関連するビットのテストのみに関心があったため、コントローラーレベルで考えていたときに、このことに気づきませんでした。ただし、ここまでずっと、プロジェクトを保存する場所をユーザーに尋ねる必要があることに気付きました。ここで、データストアに場所IDを追加し、プロジェクトに1つ追加し、次にコントローラーに1つ追加し、それらすべてに対して既に書き込まれているすべてのテストに追加する必要があります。すぐに退屈になり、TDDプロセス中に設計するのではなく、事前に設計をスケッチしておけば、これをもっと早く理解できたように思わずにはいられません。
このプロセスで何か間違ったことをした場合、誰かに説明してもらえますか?とにかく、この種のリファクタリングは回避できますか?それともこれは一般的ですか?それが一般的であれば、それをより痛みのないものにする方法はありますか?
皆さんありがとう!