Тесты, которые в 2-3 раза больше тестируемого кода - PullRequest
30 голосов
/ 06 апреля 2010

Нормально ли иметь тесты, которые намного больше, чем реальный тестируемый код? Для каждой строки кода, которую я тестирую, у меня обычно есть 2-3 строки в модульном тесте. Что в конечном итоге приводит к тому, что тратится огромное количество времени, просто набирая тесты (издевайся, смейся и смейся больше).

Где экономия времени? Вы когда-нибудь избегаете тестов для кода, который выглядит тривиально? Большинство моих методов имеют длину менее 10 строк, и тестирование каждого из них занимает много времени, и, как вы видите, я начинаю сомневаться в написании большинства тестов.

Я не защищаю не юнит-тестирование, мне это нравится. Просто хочу посмотреть, какие факторы люди учитывают, прежде чем писать тесты. Они приходят по стоимости (с точки зрения времени, а значит и денег), поэтому эту стоимость нужно как-то оценить. Как вы оцениваете экономию, созданную вашими юнит-тестами, если вообще когда-либо?

Ответы [ 13 ]

16 голосов
/ 06 апреля 2010

Возможно, вы тестируете не то, что вам нужно, чтобы у каждого метода не было разных тестов.

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

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

Еще одна причина для больших тестов - отсутствие изоляции (a.k.a насмешка), если вам нужно инициализировать сложные объекты, которые требуют много кода, попробуйте вместо этого использовать fakes / mocks.

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

6 голосов
/ 06 апреля 2010

Код модульного теста должен соответствовать тем же рекомендациям, что и рабочий код. Если у вас так много кода модульного теста, он пахнет нарушением принципа СУХОЙ .

Рефакторинг ваших юнит-тестов для использования Методы утилиты тестирования должен помочь уменьшить общий объем юнит-тестов.

2 голосов
/ 06 апреля 2010

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

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

1 голос
/ 06 апреля 2010
  • Если вы тестируете простые (CRUD) операции, вполне логично иметь более длинные тесты
  • В противном случае, я полагаю, вы можете реорганизовать свой код, чтобы повторяющийся код перемещался в отдельные методы
  • Если вы используете Java, вы можете использовать checkstyle (или другие инструменты) для проверки на дублирование кода
1 голос
/ 06 апреля 2010

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

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

Кроме того, учтите время, необходимое для устранения ошибок. Если бы модульные тесты не позволяли появиться определенным ошибкам, которые потребовали бы намного больше времени для отладки и исправления, вы бы поспорили, что TDD продлил вашу разработку?

1 голос
/ 06 апреля 2010

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

  1. Устанавливаем категорию для известных нам проблем (критических, высоких, низких)
  2. Посмотрим, сколько у нас времени, и переставим их путем внутреннего обсуждения1006 *
  3. установить приоритеты
  4. Затем решить проблемы

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

1 голос
/ 06 апреля 2010

Тестирование должно быть о поиске правильного баланса, который зависит от многих различных факторов, таких как:

  • Бизнес-цель (например, «контроллер кардиостимулятора» и «менеджер инвентаря фильмов»)
  • Навыки развития персонала
  • Текучесть кадров (как часто люди добавляются в пул разработчиков)
  • Сложность (программного обеспечения, относящегося к "деловой цели" выше)

Обычно я пишу тесты только для «открытого API» и, таким образом, неявно тестирую любые классы внутренней сборки, используемые для предоставления общедоступной функциональности. Но по мере того, как ваше стремление к надежности и воспроизводимости возрастает, вы также должны добавить дополнительные тесты.

1 голос
/ 06 апреля 2010

Ну,

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

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

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

0 голосов
/ 06 апреля 2010

Тесты, которые в 2-3 раза больше, НЕ являются нормальными.

Использовать вспомогательные классы / методы в тестах.

Ограничить объем испытаний.

Эффективно используйте тестовый прибор.

Эффективно используйте тестовый разрыв.

Эффективно используйте рамки модульного тестирования.

И таких тестов у тебя больше не будет.

0 голосов
/ 06 апреля 2010

В моей практике TDD я склонен видеть, что более крупные тесты (в LOC) проверяют классы, которые ближе к точкам интеграции системы, то есть классы доступа к базе данных, классы веб-служб и классы аутентификации.

Интересным моментом в этих модульных тестах является то, что даже после их написания мне все еще не ясно, работают ли эти классы, что приводит меня к написанию интеграционных тестов с использованием базы данных, веб-службы или службы аутентификации. Только после того, как были установлены автоматизированные интеграционные тесты, я чувствую себя комфортно.

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

-HOWEVER-

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

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

...