Я хотел научить себя использовать подход TDD, и у меня был проект, над которым я давно хотел работать. Это был не большой проект, поэтому я подумал, что это будет хорошим кандидатом на TDD. Однако я чувствую, что что-то пошло не так. Позвольте мне привести пример:
На высоком уровне мой проект является надстройкой для Microsoft OneNote, которая позволит мне более легко отслеживать и управлять проектами. Теперь я также хотел сохранить бизнес-логику для этого максимально изолированной от OneNote на тот случай, если я когда-нибудь решу создать собственное хранилище и серверную часть.
Сначала я начал с простого теста на прием простых слов, чтобы описать, что я хотел сделать от своей первой функции. Это выглядит примерно так (из соображений краткости):
- Пользователь нажимает создать проект
- Типы пользователей в заголовке проекта
- Убедитесь, что проект создан правильно
Пропустив пользовательский интерфейс и промежуточное планирование, я прихожу к своему первому модульному тесту:
[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 раздела. Я не осознавал этого, когда думал на уровне контроллера, потому что меня интересовало только тестирование битов, относящихся к контроллеру. Тем не менее, теперь я понимаю, что должен попросить пользователя указать место для сохранения проекта. Теперь мне нужно добавить идентификатор местоположения в хранилище данных, затем добавить один в проект, затем добавить один в контроллер и добавить его ко ВСЕМ тестам, которые уже написаны для всех этих вещей. Это очень быстро стало утомительно, и я не могу помочь, но чувствую, что поймал бы это быстрее, если бы набросал дизайн раньше, чем позволил бы его разрабатывать во время процесса TDD.
Может кто-нибудь объяснить мне, если я сделал что-то не так в этом процессе? Есть ли в любом случае такого рода рефакторинг можно избежать? Или это распространено? Если это распространено, есть ли способы сделать его более безболезненным?
Спасибо всем!