Единичное тестирование Каталог анти-шаблонов

anti-pattern: должно присутствовать как минимум два ключевых элемента, чтобы формально отличить фактический анти-шаблон от простой дурной привычки, плохой практики или плохой идеи:

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

Проголосуйте за анти-шаблон TDD, который вы видели "в дикой природе", когда-то слишком много.
Сообщение в блоге Джеймса Карра и Связанное обсуждение testdrivendevelopment yahoogroup

Если вы нашли "неназванный" один, отправьте его тоже. Одно сообщение для анти-шаблона, чтобы подсчитать количество голосов.

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

Ответ 1

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

Ответ 2

The Free Ride/Piggyback - Джеймс Карр, Тим Оттингер
Вместо того, чтобы записывать новый тестовый метод для тестирования другой/отдельной функции/функциональности, новое утверждение (и его соответствующие действия, то есть шаги действия от AAA) проходит в существующем тестовом случае.

Ответ 3

Счастливый путь

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

JUnit Antipatterns

Ответ 4

Локальный герой

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

Скрытая зависимость

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


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

Ответ 5

Chain Gang

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

Вы часто видите это в тестах базы данных. Вместо выполнения отката в teardown() тесты фиксируют свои изменения в базе данных. Еще одна распространенная причина заключается в том, что изменения в глобальном состоянии не завертываются в блоки try/finally, которые очищаются, если тест завершился с ошибкой.

Ответ 6

The Mockery
Иногда насмешка может быть хорошей и удобной. Но иногда разработчики могут потерять себя и свои усилия, чтобы издеваться над тем, что не тестируется. В этом случае unit test содержит так много mocks, stubs и/или подделок, что тестируемая система даже не тестируется вообще, а данные, возвращаемые из mocks, проверяются.

Источник: сообщение Джеймса Карра.

Ответ 7

The Silent Catcher - Келли?
Тест, который проходит, если исключение выбрано.. даже если исключение, которое на самом деле происходит, отличается от того, что было предусмотрено разработчиком.
Смотрите также: Тайный улавливатель

[Test]
[ExpectedException(typeof(Exception))]
public void ItShouldThrowDivideByZeroException()
{
   // some code that throws another exception yet passes the test
}

Ответ 8

Инспектор
A unit test, который нарушает инкапсуляцию в целях достижения 100% -ного охвата кода, но знает о том, что происходит в объекте, что любая попытка рефакторирования нарушит существующий тест и потребует, чтобы любые изменения отражались в unit test.


'как проверить мои переменные-члены, не делая их общедоступными... только для модульного тестирования?

Ответ 9

Чрезмерная установка - Джеймс Карр
Тест, требующий огромной настройки, чтобы даже начать тестирование. Иногда несколько сотен строк кода используются для подготовки среды для одного теста с несколькими объектами, что может затруднить реальное выяснение того, что тестируется из-за "шума" всей настройки. (Src: Сообщение Джеймса Карра)

Ответ 10

Анальный зонд

Тест, который должен использовать безумные, незаконные или иным образом нездоровые способы выполнения своей задачи: Чтение частных полей с использованием Java setAccessible (true) или расширения класса для доступа к защищенным полям/методам или для помещения теста в определенный пакет для доступа к глобальным полям/методам пакетов.

Если вы видите этот шаблон, тестируемые классы используют слишком много скрытых данных.

Разница между этим и Инспектором заключается в том, что тестируемый класс пытается скрыть даже те вещи, которые вам нужно проверить. Поэтому ваша цель состоит не в том, чтобы достичь 100% -ного охвата тестирования, а в том, чтобы иметь возможность вообще что-либо протестировать. Подумайте о классе, который имеет только частные поля, метод run() без аргументов и никаких геттеров вообще. Невозможно проверить это, не нарушая правил.


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

Аарон Дигулла: Я согласен. Возможно, эта запись действительно лучше подходит для вики "JUnit HOWTO", а не для антипаттера. Комментарии?

Ответ 11

Тест без имени - Nick Pellow

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

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

Ответ 12

Медленная игра

A unit test, который работает невероятно медленно. Когда разработчики пинают это, у них есть время, чтобы пойти в ванную комнату, схватить дым или, что еще хуже, отбросить тест, прежде чем они вернутся домой в конце дня. (Src: Сообщение Джеймса Карра)

a.k.a. тесты, которые не будут запускаться так часто, как они должны

Ответ 13

Бабочка

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

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

Ответ 14

Подождите и посмотрите

Тест, который запускает некоторый код настройки, а затем должен "ждать" определенное количество времени, прежде чем он сможет "видеть", если тестируемый код функционирует так, как ожидалось. Метод testMethod, который использует Thread.sleep() или эквивалент, является, безусловно, тестом "Подождите и посмотрите".

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

Такой тест может также быть Local Hero, поскольку он будет FAIL при запуске на более медленном поле или перегруженном CI-сервере.

Нельзя путать Wait и See anti-pattern с The Sleeper.

Ответ 15

Тест мерцания (Источник: Ромилли Кокинг)

Тест, который иногда изредка терпит неудачу, а не в определенное время, и, как правило, из-за условий гонки в тесте. Обычно возникает при тестировании асинхронного, например JMS.

Возможно, супер установлен в Wait and See 'anti-pattern и The Sleeper' анти-модель.

Сбой сборки, ну, просто запустите сборку еще раз. - Анонимный разработчик

Ответ 16

Неправильно Shared Fixture - Тим Оттингер
Несколько тестовых примеров в испытательном оборудовании даже не используются или не нуждаются в установке/разрыве. Частично из-за инерции проявителя для создания нового тестового прибора... проще просто добавить еще один тестовый пример в кучу

Ответ 17

Гигантский

A unit test, что, хотя он действительно тестирует тестируемый объект, может охватывать тысячи строк и содержать много тестов. Это может быть индикатором того, что тестируемая система представляет собой объект Бога (сообщение Джеймса Карра).

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

Ответ 18

Я верю, когда увижу несколько мигающих графических интерфейсов
Нездоровая фиксация/одержимость тестированием приложения через его графический интерфейс "как реальный пользователь"

Тестирование бизнес-правил через графический интерфейс это ужасная форма сцепления. Если вы пишете тысячи тестов через графический интерфейс пользователя, а затем изменить свой графический интерфейс, тысячи тестов ломаются.
Скорее, проверьте только GUI-объекты через графический интерфейс пользователя и GUI для фиктивной системы вместо реальной системы, когда вы запускаете эти тесты. Тестирование бизнес-правил через API что не связано с графическим интерфейсом. - Боб Мартин

"Вы должны понимать, что видение - это верить, но также знать, что вера видит". - Денис Уэйтли

Ответ 19

Спящий, ака Везувий - Ник Плейн

Тест, который предназначен для FAIL в определенное время и в будущем. Это часто вызвано неправильной проверкой границ при тестировании кода, который использует объект Date или Calendar. Иногда тест может потерпеть неудачу, если он запускается в очень определенное время суток, например, в полночь.

"Спящий" не следует путать с "Подождите и посмотрите анти-шаблон.

Этот код будет заменен задолго до 2000 года. Многие разработчики в 1960 году

Ответ 20

Кукушка - Фрэнк Карвер
A unit test, который сидит в тестовом примере с несколькими другими и имеет тот же (потенциально длительный) процесс установки, что и другие тесты в тестовом примере, но затем отбрасывает некоторые или все артефакты из установки и создает свои собственные.
Продвинутый Симптом: Неправильно Shared Fixture

Ответ 21

Мертвое дерево

Тест, в котором был создан заглушка, но тест на самом деле не написан.

Я действительно видел это в нашем производственном коде:

class TD_SomeClass {
  public void testAdd() {
    assertEquals(1+1, 2);
  }
}

Я даже не знаю, что об этом думать.

Ответ 22

добрался до сегодняшнего дня:

Влажный пол:
Тест создает данные, которые где-то сохраняются, но при завершении теста он не очищается. Это приводит к тому, что тесты (те же тесты или, возможно, другие тесты) терпят неудачу при последующих тестовых прогонах.

В нашем случае тест оставил файл, лежащий в директории temp, с разрешениями пользователя, который запускал тест в первый раз. Когда другой пользователь попытался протестировать на одной машине: стрела. В комментариях к сайту Джеймса Карра, Joakim Ohlrogge называл это "Sloppy Worker", и это было частью вдохновения для "щедрых остатков". Мне нравится мое имя для него лучше (менее оскорбительно, более знакомо).

Ответ 23

The Secret Catcher - Фрэнк Карвер

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

[Test]
public void ShouldNotThrow()
{
   DoSomethingThatShouldNotThrowAnException();
}

Ответ 24

Тест сорок футов *

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

Ответ 25

Тест Тьюринга

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

Привет, глупо. - Самый умный компьютер в мире для нового ученика (из старого комикса Amiga).

Ответ 26

Экологический вандал

Тест 'unit', который для различных "требований" начинает выходить в его среду, используя и устанавливая переменные среды/порты. Выполнение двух из этих тестов одновременно вызовет исключения "недоступный порт" и т.д.

Эти тесты будут прерывистыми, и разработчики оставляют такие вещи, как "просто запустите его снова".

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

Ответ 27

Doppelgänger

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

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

Я посмотрел ему в лицо... мое лицо! Это было похоже на зеркало, но замерзло.

Ответ 28

Мать-курица - Фрэнк Карвер
Необходима общая настройка, которая делает гораздо больше, чем реальные тестовые примеры. Например, создавая всевозможные сложные структуры данных, заполненные, по-видимому, важными и уникальными значениями, когда тесты только утверждают для наличия или отсутствия чего-либо.
Продвинутый Симптом: Неправильно Shared Fixture

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

Ответ 29

Тест Все это

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

Я сталкивался с этим так много раз, тесты, которые нарушают это правило, по определению являются кошмаром для поддержания.

Ответ 30

Нападающий линии

В первых тестах взглядов все охватывает, а инструменты покрытия кода подтверждают его на 100%, но на самом деле тесты только попадают в код без каких-либо анализов вывода.

coverage-vs-reachable-code