Во-первых, извиняюсь за название, я не мог придумать самый простой способ объяснить это!
У меня есть метод, для которого я хочу написать модульные тесты. Я собираюсь оставить его достаточно общим, так как я не хочу обсуждать реализацию метода, только его тестирование. Метод таков:
public void HandleItem(item a)
{
CreateNewItem();
UpdateStatusOnPreviousItem();
SetNextRunDate();
}
Так что у этого класса есть один открытый метод, который затем вызывает некоторые частные методы для выполнения логики.
Поэтому при написании модульного теста я хочу проверить, все ли три вещи были выполнены. Поскольку все они вызываются в одном прогоне, я подумал, что смогу сделать это как один тест:
public void GivenItem_WhenRun_Thenxxxxx
{
HandleItem(item);
// Assert item has been created
// Assert status has been set on the previous item
// Assert run date has been set
}
Но я подумал, что я мог бы написать это как три отдельных теста:
public void GivenItem_WhenRun_ThenItemIsCreated()
{
HandleItem(item);
}
public void GivenItem_WhenRun_ThenStatusIsUpdatedOnPreviousItem()
{
HandleItem(item);
}
public void GivenItem_WhenRun_ThenRunDateIsSet()
{
HandleItem(item);
}
Так что мне это кажется более приятным, так как это, по сути, перечисление требований, но тогда все три взаимосвязаны и требуют точно такой же работы, выполненной на тестируемом методе, поэтому я выполняю один и тот же код 3 раза.
Есть ли рекомендуемый подход с этим?
Благодарность
источник
Короткий ответ: гораздо важнее, чтобы ваши тесты охватывали всю функциональность, а не как они это делают.
Более длинный ответ: если вы все еще хотите выбрать одно из этих в значительной степени эквивалентных решений, вы можете использовать вспомогательные критерии для определения наилучшего. Например,
источник
Используйте один вызов метода с несколькими утверждениями. Вот почему:
Когда вы тестируете HandleItem (a), вы проверяете, что метод перевел элемент в правильное состояние. Вместо «одно утверждение на тест», подумайте «одна логическая концепция на тест».
Вопрос: Если CreateNewItem завершается неудачно, но другие два метода успешны, означает ли это, что HandleItem завершился успешно? Я думаю, нет.
С несколькими утверждениями (с соответствующими сообщениями) вы будете точно знать, что не удалось. Обычно вы тестируете метод несколько раз для нескольких входов или состояний ввода, чтобы не избежать нескольких утверждений.
ИМО, эти вопросы обычно являются признаком чего-то другого. Это признак того, что HandleItem не является чем-то, что вы можете «модульно протестировать», так как кажется, что оно просто делегирует другим методам. Когда вы просто проверяете, что HandleItem правильно вызывает другие методы, он становится скорее кандидатом в интеграционный тест (в этом случае у вас все еще будет 3 утверждения).
Возможно, вы захотите сделать общедоступными другие 3 метода и протестировать их самостоятельно. Или даже извлекая их в другой класс.
источник
Используйте 2-й подход. При первом подходе, если тест не пройден, вы сразу не поймете, почему, потому что это может быть одна из 3-х функций, которая не прошла. При втором подходе вы сразу узнаете, где возникла проблема. Вы можете поместить повторяющийся код в вашу функцию настройки теста.
источник
ИМХО, вы должны протестировать три части этого метода отдельно, чтобы вы более точно знали, где что-то идет не так, когда они делают, избегая при этом повторения одной и той же части вашего кода дважды.
источник
Я не думаю, что есть веские основания для написания отдельных методов тестирования для вашего варианта использования. Если вы хотите получить результаты от всех трех переменных условий, вы можете протестировать все три и распечатать их ошибки, объединяя их в
string
и убедившись, что строка еще пуста после того, как вы завершили тестирование. Храня их все в одном методе, ваши условия и сообщения об ошибках документируют ожидаемое постусловие метода в одном месте, а не разбивают его на три метода, которые могут быть позже разделены.Это означает, что в вашем отдельном тесте будет больше кода, но если у вас так много постусловий, что это проблема, вы, вероятно, захотите реорганизовать свои методы тестирования, чтобы в
HandleItem
любом случае протестировать отдельные методы внутри .источник