Руководство по модульному тестированию - PullRequest
23 голосов
/ 20 сентября 2008

Кто-нибудь знает, где найти рекомендации и рекомендации для модульного тестирования? Я хотел бы иметь что-то, что касается следующих типов тем (например):

  • Должны ли тесты быть в том же проекте, что и логика приложения?
  • Должны ли я иметь тестовые классы для отражения моих логических классов или у меня должно быть только столько тестовых классов, сколько мне нужно?
  • Как мне назвать мои тестовые классы, методы и проекты (если они идут в разных проектах)
  • Должны ли тестироваться частные, защищенные и внутренние методы или только те, которые являются общедоступными?
  • Должны ли разделяться единичные и интеграционные тесты?
  • Есть ли хорошая причина не иметь 100% тестовое покрытие?

Что я не спрашиваю о том, что я должен быть?

Лучше всего подойдет онлайн-ресурс.

Ответы [ 7 ]

21 голосов
/ 20 сентября 2008

Я бы порекомендовал Книгу Кента Бека по TDD.

Кроме того, вам нужно перейти на сайт Мартина Фаулера . У него много хорошей информации о тестировании.

Мы очень хорошо разбираемся в TDD, поэтому я отвечу на вопросы в этом свете.

Должны ли тесты находиться в том же проекте, что и логика приложения?

Обычно наши тесты хранятся в одном и том же решении, но мы разбиваем тесты на отдельные библиотеки DLL / проекты, которые отражают библиотеки DLL / проекты, которые они тестируют, но поддерживают пространства имен, в которых тесты находятся в подпространстве имен. Пример: Common / Common.Tests

Должны ли у меня быть тестовые классы для зеркалирования моих логических классов или у меня должно быть только столько тестовых классов, сколько мне нужно?

Да, ваши тесты должны быть созданы до создания каких-либо классов, и по определению вы должны тестировать только один модуль в отдельности. Поэтому у вас должен быть тестовый класс для каждого класса в вашем решении.

Как мне назвать мои тестовые классы, методы и проекты (если они идут в разных проектах)

Я хотел бы подчеркнуть, что поведение - это то, что тестируется, поэтому я обычно называю тестовые классы после SUT. Например, если бы у меня был класс User, я бы назвал тестовый класс следующим образом:

public class UserBehavior

Должны быть названы методы для описания ожидаемого поведения.

public void ShouldBeAbleToSetUserFirstName()

Проекты могут быть названы так, как вы хотите, но обычно вы хотите, чтобы было достаточно очевидно, какой проект он тестирует. Смотрите предыдущий ответ об организации проекта.

Должны ли тестироваться частные, защищенные и внутренние методы или только те, которые являются общедоступными?

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

Должны ли разделяться единичные и интеграционные тесты?

Да, модульные тесты должны быть изолированы от приемочных и интеграционных тестов. Разделение проблем относится и к испытаниям.

Есть ли веская причина не иметь 100% тестовое покрытие?

Я бы не стал зацикливаться на 100% охвате кода. 100% покрытие кода подразумевает некоторый уровень качества в тестах, но это миф. Вы можете пройти ужасные тесты и при этом получить 100% покрытие. Вместо этого я бы положился на хороший менталитет Test First. Если вы всегда пишете тест, прежде чем писать строку кода, вы обеспечите 100% охват, чтобы он стал спорным.

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

3 голосов
/ 20 сентября 2008

Ответ Джоша прав - только одно уточнение:

Причина, по которой я отделяю модульные тесты от интеграционных и приемочных, - это скорость. Я использую TDD. Мне нужна мгновенная обратная связь о строке кода, которую я только что создал / изменил. Я не могу этого добиться, если я использую полные наборы интеграционных и / или приемочных тестов - тестов, которые работают с реальными дисками, реальными сетями и очень медленными и непредсказуемыми внешними системами.

Не пересекайте балки. Плохие вещи произойдут, если вы это сделаете.

3 голосов
/ 20 сентября 2008

Хороший вопрос. Мы органически выросли, и я подозреваю, что лучший способ - это так. Там есть немного "Это зависит ...".

Мы производим тесты в том же проекте, в под-пространстве имен, называемом «UnitTes»

Наши тестовые классы отражают логический класс, чтобы упростить отслеживание того, где находятся тесты относительно того, что они тестируют

Классы названы так же, как логический класс, который они тестируют, методы - для сценария, который они тестируют.

Мы пишем тесты только для открытых и внутренних методов (test находятся в одном проекте) и стремимся к 95% охвату класса.

Я предпочитаю не проводить различий между «единицей» и «интеграцией». Много времени будет потрачено на то, чтобы выяснить, что есть ... что за сумка! Тест - это тест.

100% слишком сложно достичь постоянно. Мы стремимся к 95%. Также уменьшается отдача от того, сколько времени потребуется, чтобы получить эти последние 5% и что он действительно поймает.

Это мы и то, что подходит окружающей среде и темпам. Вы можете варьировать. Подумайте о своем окружении и о личностях, которые в этом участвуют.

Я с нетерпением жду, что скажут другие об этом!

1 голос
/ 27 сентября 2008

Должны ли тесты быть в том же проекте, что и логика приложения?

Это зависит. В любом случае есть компромиссы.

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

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

Насколько эти различные затраты имеют значение, зависит от проекта, поэтому универсального ответа нет.

Должны ли я иметь тестовые классы для отражения моих логических классов или у меня должно быть только столько тестовых классов, сколько мне нужно?

номер

У вас должны быть тестовые классы, которые допускают хорошо продуманный тестовый код (то есть минимальное дублирование, четкое намерение и т. Д.).

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

Как мне назвать мои тестовые классы, методы и проекты (если они идут в разных проектах)

Вы должны назвать их так:

  • каждый класс испытаний и метод испытаний имеют четкую цель, а
  • так, чтобы кто-то, ищущий определенный тест (или тесты для определенного модуля), мог легко его найти.

Должны ли тестироваться частные, защищенные и внутренние методы или только те, которые являются общедоступными?

Часто непубличные методы должны быть проверены. Это зависит от того, получаете ли вы достаточно уверенности от простого тестирования общедоступного интерфейса, или от того, что модуль, который вы действительно хотите тестировать, не является общедоступным.

Следует ли разделить единичные и интеграционные тесты?

Это зависит от вашего выбора среды (ов) тестирования. Делайте то, что лучше всего работает с вашими средами тестирования и делает так, чтобы:

  • и модульные, и интеграционные тесты, относящиеся к коду кода, легко найти,
  • легко запустить только юнит-тесты,
  • легко запустить только интеграционные тесты,
  • Все тесты легко запустить.

Есть ли веская причина не иметь 100% тестовое покрытие?

Да, есть веская причина. Строго говоря, «100% тестовое покрытие» означает, что каждая возможная ситуация в вашем коде выполняется и тестируется. Это практически неосуществимо практически для любого проекта.

Если вы просто берете «100% тестовое покрытие», чтобы означать, что каждая строка исходного кода выполняется набором тестов в какой-то момент, то это хорошая цель, но иногда в неловких местах бывает всего пара строк это трудно достичь с помощью автоматизированных тестов. Если стоимость ручной проверки этой функциональности периодически меньше, чем стоимость прохождения искажений для достижения этих пяти последних строк, то это веская причина не иметь 100% покрытия линии.

Вместо простого правила о том, что у вас должно быть 100% покрытие линии, побуждайте ваших разработчиков обнаруживать любые пробелы в вашем тестировании и находить способы исправления этих пробелов, независимо от того, покрыто ли количество линий или "покрыто" Улучшается Другими словами, если вы измеряете покрытые линии, то вы улучшите покрытие линий - но на самом деле вы хотите улучшить качество. Так что не забывайте, что покрытие линий - это просто грубое приближение качества.

1 голос
/ 20 сентября 2008

Что касается вашего последнего вопроса, то, по моему опыту, "хорошая" причина не настаивать на 100% охвате тестами состоит в том, что для получения последних нескольких процентных пунктов требуются непропорциональные усилия, особенно в больших кодовых базах. Таким образом, нужно решить, стоит ли тратить ваше время, когда вы достигнете этой точки убывающей отдачи.

1 голос
/ 20 сентября 2008

В заказе:

  • Нет, обычно лучше включать их в отдельный проект; если вы не хотите запускать диагностику во время выполнения.
  • Идеальным является 100% покрытие кода, что означает каждую строку кода в каждой подпрограмме в каждом классе.
  • Я иду с ClassnameTest, ClassnameTest.MethodNameTestnumber
  • Все.
  • Я бы сказал, что да, поскольку интеграционные тесты не нужно запускать, если модульные тесты не пройдены.
  • Простые свойства, которые просто устанавливают и получают поле, проверять не нужно.
1 голос
/ 20 сентября 2008

Настоятельно рекомендую прочитать Разработка через тестирование: на примере и Разработка через тестирование: практическое руководство Слишком много вопросов для отдельной темы

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