Скажем, я начинаю делать игру с TDD. Действительно ли это - хороший первый тест?
[TestMethod]
public void Can_Start_And_End_Game()
{
Tetris tetris = new Tetris();
tetris.Start();
tetris.End();
}
Это в основном вынуждает меня определить 3 вещи: Tetris
класс и Start()
и End()
методы, но помимо которого это довольно бесполезно. Это могло бы сразу иметь свой интерес как с ними, я могу определить тот класс и те методы, но позже это, вероятно, не будет служить никакому виду цели. Его единственная цель, возможно, показала бы, что должно быть возможно запустить игру и закончить его, не получая исключение в середине.
Каковы Ваши мысли об этом?
По сути, это вынуждает меня определить три вещи: класс Tetris и его методы Start () и End (),
True.
но кроме этого это довольно бесполезно.
Неверно.
позже это, вероятно, не будет служить какой-либо цели
Тоже неверно.
Его ... цель [состоит в том], чтобы показать, что должна быть возможность начать игру и закончить ее, не получая исключения в середине
И это ОГРОМНО. Эпично. Монументальный.
Действительно, этот тест будет терпеть неудачу так часто, что вы возненавидите его. Каждое необработанное, неперехваченное исключение из всевозможных случайных мест в вашей программе не пройдет этот тест. Благодаря этому тесту вы создадите тщательное ведение журнала и отладку.
Этот тест - ЭПИЧЕСКИЙ.
На самом деле вы не управляете развитием класса Tetris с помощью этого теста - вы решили, каким должен быть его API, и это нормально, но почему бы не написать тест, который проверяет то, что он действительно должен делать?
Тесты должны информировать API, а не наоборот (imho).
Я думаю, что цель теста может быть прояснена путем перехвата любых исключений и явного провала теста, если это произойдет:
[TestMethod]
public void Can_Start_And_End_Game()
{
try
{
Tetris tetris = new Tetris();
tetris.Start();
tetris.End();
}
catch (Exception ex)
{
Assert.Fail("Unexpected exception thrown: " + ex.ToString());
}
}
Как сказал С. Лотт, этот тест охватывает ТОННУ земли. Это настолько «того стоит», что стоит разбить на как минимум 3 теста и добавить соответствующие утверждения к каждому:
[TestMethod]
public void Test_Contructor()
{
Tetris tetris = new Tetris();
// make assertions
}
[TestMethod]
public void Test_Start()
{
// setup
Tetris tetris = new Tetris();
// exercise
tetris.Start();
// make assertions
}
[TestMethod]
public void Test_End()
{
// setup
Tetris tetris = new Tetris();
tetris.Start();
// exercise
tetris.End();
// make assertions
}
Я не большой поклонник этого теста. Да, это помогло определить интерфейс, но не очень хорошо для определения (и тестирования) поведения.
Я думаю, что было бы лучше иметь один тест, который обрабатывает запуск. Вероятно, он подтвердит настройки по умолчанию или значения оценки. Тогда у меня будут дополнительные тесты, чтобы узнать, сможете ли вы закончить игру.
В идеале каждый метод тестирования должен выполнять одно поведение.
Да, тест подтверждает, что в конструкторе, методе Start ()
и методе Stop ()
не генерируется исключение.
Я не вижу особой ценности в дополнительном блоке try / catch внутри теста для перехвата исключений. Инструмент, выполняющий тест, обнаружит и сообщит об этом. Используя принцип TSTTCPW, тест может обойтись без блока try / catch.
Вы можете сделать тест немного более значимым, добавив в конце утверждения, например, проверку значения свойств объекта tetris
.
Обратите внимание на разницу между написанием модульного теста и использованием TDD. Ценность заключается в понимании этой разницы.