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

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

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

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

Если вы нашли «неназванный», то … пост. Один пост за анти-шаблон, пожалуйста, чтобы подсчет голосов за что-то.

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

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

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

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

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

JUnit Antipatterns

Местный герой

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

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

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


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

Цепная банда

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

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

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

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

Тихий Ловец – Келли?
Тест, который проходит, если исключение выбрано .. даже если фактически происходит исключение, отличное от того, что было предусмотрено разработчиком.
См. Также: Секретный улавливатель

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

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


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

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

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

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

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

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


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

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

Тест без имени – Ник Пьелл

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

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

Медленный тыквы

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

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

Бабочка

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

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

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

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

Возможно, супер установлен для анти-шаблона « Подождите и посмотри » и « Спящий ».

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

Ждать и смотреть

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

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

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

Нельзя путать с The Sleeper функцию Wait and See anti-pattern.

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

Гигант

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

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

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

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

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

Спящий, он же гора Везувий – Ник Пелоу

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

«The Sleeper» не следует путать с анти-шаблоном « Подождите и посмотрите ».

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

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

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

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

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

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

сегодня битком:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Doppelgänger

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

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

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

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

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

Все испытания

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

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

Линейный нападающий

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

Покрытие-против-достижимости-кода

Interesting Posts

Комбинаторный «N выбирает R» в Java-математике?

Поиск физического локального пути, связанного с папкой общего доступа UNC

Отобразить список компьютеров в локальной сети в Linux

Почему расчетная ширина и высота в пикселе строки в Tkinter различаются между платформами?

Как разрешены круговые #includes?

Можно ли оценить время смерти hdd?

Преобразование строки в формате dd / mm / yyyy в Datetime

Инструмент для определения файловой системы на съемных носителях

«Кто в сети» с помощью «Разработка в рельсах»

Перемещение проекта в другую папку в Eclipse

Как заставить IE открывать JavaScript как текст

jquery UI dialog: как инициализировать без заголовка?

Как запустить class из Jar, который не является основным classом в его файле манифеста

jquery fancybox 2.0.3 – предотвратить закрытие клика за пределами fancybox

Использование scanf () в программах на C ++ быстрее, чем использование cin?

Давайте будем гением компьютера.