我想教自己使用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添加到数据存储中,然后将其添加到项目中,然后将其添加到控制器中,然后将其添加到已针对所有这些内容编写的所有测试中。它变得非常繁琐,我不禁感到,如果我提前草拟设计而不是在TDD过程中进行设计,我会更快地抓住这一点。
如果我在此过程中做错了什么,可以给我解释一下吗?无论如何,可以避免这种重构吗?还是这很常见?如果很常见,有什么方法可以使它更轻松吗?
谢谢大家!