Сколько стоит каждый модульный тест? - PullRequest
4 голосов
/ 08 июня 2009

Сколько должен проверить каждый из моих юнит-тестов? Например, у меня есть этот тест

[TestMethod]
public void IndexReturnsAView()
{
    IActivityRepository repository = GetPopulatedRepository();
    ActivityController activityController = GetActivityController(repository);
    ActionResult result = activityController.Index();
    Assert.IsInstanceOfType(result, typeof(ViewResult));
}

, а также

[TestMethod]
public void IndexReturnsAViewWithAListOfActivitiesInModelData()
{
    IActivityRepository repository = GetPopulatedRepository();
    ActivityController activityController = GetActivityController(repository);
    ViewResult result = activityController.Index() as ViewResult;
    Assert.IsInstanceOfType(result.ViewData.Model, typeof(List<Activity>));
}

Очевидно, что если первый тест не пройден, то будет ли второй тест, поэтому следует ли объединить эти два теста в один тест с двумя утверждениями? Я чувствую, что чем более детализированы тесты и чем меньше каждый тест проверяет, тем быстрее будет найдено причины сбоев. Однако есть огромное количество очень маленьких тестов, которые могут стоить времени на выполнение всех тестов.

Ответы [ 5 ]

12 голосов
/ 08 июня 2009

Я бы порекомендовал разбить их как можно больше.

Для этого есть много причин, ИМХО, наиболее важными из них являются:

  • Когда один из ваших тестов не пройден, вы хотите быть в состоянии точно определить, что пошло не так, как можно быстрее и безопаснее. Лучше всего добиться этого, если каждый метод тестирования тестирует только одну вещь.

  • Каждый тест должен начинаться с чистого листа. Если вы создаете хранилище один раз, а затем используете его в 2 или более тестах, то вы неявно зависите от порядка этих тестов. Скажем, Test1 добавляет элемент в хранилище, но забывает удалить его. Поведение Test2 теперь будет другим и, возможно, приведет к сбою вашего теста. Единственным исключением из этого являются неизменные данные.

Что касается твоих скоростных проблем, я бы об этом не беспокоился. Для такого простого перебора кода .NET очень быстр, , и вы никогда не сможете заметить разницу. Как только вы выйдете из хруста кода и разберетесь с такими вещами, как базы данных, вы почувствуете проблемы с производительностью, но как только вы это сделаете, вы столкнетесь со всеми проблемами «чистого листа», как описано выше, так что вы можете просто приходится жить с этим (или сделать как можно большую часть ваших данных неизменной).

Удачи в тестировании.

3 голосов
/ 08 июня 2009

Чем более мелкозернистым, тем лучше. Когда в тестовом случае сбой подтверждения, тестовый пример больше не запускается. Последние части дела могут потенциально обнаружить другие ошибки.

Если между тестовыми примерами есть общий код, используйте функции setup / teardown, чтобы позаботиться об этом, не повторяя себя слишком много. Стоимость времени часто ничтожна. Если настройка / демонтаж занимает слишком много времени, вы, вероятно, не проводите модульное тестирование, а проводите более высокоуровневое автоматическое тестирование. В идеале модульные тесты не должны иметь зависимостей между файловой системой, сетью, базой данных и т. Д.

2 голосов
/ 08 июня 2009

Я думаю, что «стандартный» ответ заключается в том, что он должен доходить до того, что в случае ошибки в коде он должен прервать один тест, но не скрывать другие ошибки (не мешать другим тестам запускаться) этот терпит неудачу. Каждый тест проверяет одно, а два теста не проверяют одно и то же. Это идеал, не всегда достижимый. Назовите это руководством.

Как говорится, это действительно искусство. Сначала я бы отложил в сторону проблемы с производительностью и уделил больше внимания удобству обслуживания. Там у вас есть две с половиной до трех строк дублирования. Если дизайн изменится, его будет сложно поддерживать. Дублирование само по себе может быть решено с помощью метода установки и поданного в класс в этом случае, но главное, о чем нужно беспокоиться, это удобство сопровождения.

Тесты должны быть достаточно маленькими, чтобы их можно было обслуживать, было легко понять, и чтобы они (или вы, по прошествии некоторого времени) могли понять, что делает код, и иметь возможность поддерживать тесты. *

0 голосов
/ 20 июля 2009

Подход к количеству тестовых тестов - это определенно то, что вам нужно решить заранее и придерживаться его. Я не верю, что все должны одинаково придерживаться одного и того же подхода, поскольку разные команды и / или проекты имеют разные приоритеты в отношении кодирования, производительности, устранения неполадок, инфраструктуры тестирования и т. Д. Но постоянство всегда поможет:

  1. быстрее выявлять проблемы с Вы заранее знаете, как глубоко копать;
  2. тратить меньше времени на строительство ваши тесты;
  3. использовать тот же набор тестовых вспомогательных классов в то время как выполнение тестов.
  4. запускать тесты достаточно быстро: не слишком быстро и не слишком медленно.
  5. организация тестов (комплекты, пакеты и пр.)

Если вы решите, что производительность важнее, реализуйте более толстые тесты с большим количеством проверок / утверждений. Если вы решите, что устранение неполадок имеет первостепенное значение, изолируйте ваши тесты по мере необходимости. Я не понимаю, почему толстые и хорошо структурированные тесты ошибочны. Такие тесты выполняли бы ту же работу, что и большее количество более тонких тестов, и точно так же.

Конечно, каждый тест по-прежнему должен фокусироваться на конкретной функции / функции, но это не совсем тема этой темы.

0 голосов
/ 08 июня 2009

Модульный тест должен точно проверить то, что описано в вашем техническом проекте с точки зрения функционального проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...