Модульное тестирование каталога Anti-паттернов

203

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

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

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

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

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

Gishu
источник
Аарон, ты, кажется, весь в этом :) Было бы хорошей идеей добавить теги или слоганы в качестве комментариев, чтобы у нас было меньше прокрутки .. что скажете?
Гишу
1
Это идет довольно хорошо .. спасибо, ребята и девочки. Держите их в пути ... один из самых информативных сообщений SO IMHO
Gishu
2
+1 люблю эту ветку !!! И большинство из них настолько правдивы и распространены!
Chii
Хороший поток, почему это сообщество вики хотя ???
Ужасно
2
Потому что это своего рода опрос - вы не захотите собирать репы, просто потому что вы разместили самый распространенный тип анти-паттернов;)
Gishu

Ответы:

70

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

Илья Пройс
источник
67

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

Аарон Дигулла
источник
15
Да, это мой любимый. Я делаю это все время. Ох ... подожди ... ты сказал, что это плохо . :-)
Гидоизм
1
Я не уверен, что это анти-паттерн. Все инварианты должны быть trueпосле каждого возможного вызова мутатора. Таким образом, вы захотите проверить, что каждый инвариант находится trueпосле каждой комбинации мутатора и входных данных, которые вы тестируете. Но вы захотите уменьшить дублирование и убедиться, что вы проверяете все инварианты, включая те, которые в настоящее время не вызывают сбоев теста. Таким образом, вы помещаете их все в функцию checkInvariants()проверки и используете это в каждом тесте. Код изменяется и добавляется еще один инвариант. Вы, конечно, тоже включили это в функцию. Но это фрирайдер.
Raedwald
2
@Raedwald - со временем имя теста перестает соответствовать всем тем, что оно проверяет. Также у вас есть некоторые побои из-за переплетающихся тестов; сбой не указывает на точную причину сбоя. например, канонический пример этого теста будет читать что-то вроде непрозрачного надмножества всех шагов Arrange >> Act >> Assert A >> Act more more >> Assert B >> Act a more more >> Assert C. Теперь в идеале, если A и C сломан, вы должны увидеть 2 теста. В приведенном выше тесте вы увидите только один, затем исправите A и при следующем запуске он скажет вам, что теперь C сломан. Теперь представьте, что 5-6 различных тестов слиты воедино ..
Гишу,
1
«имя теста больше не соответствует всем вещам, которые оно проверяет», только если тест назван для условия публикации, которое было изначально. Если вы называете комбинацию имя-метода, состояние настройки и входные данные (аргументы метода), проблем нет.
Raedwald
«сбой не указывает на точную причину сбоя», ни одна ошибка подтверждения никогда не указывает на причину сбоя. Это требует некоторого углубления в детали реализации: отладка при сбое регрессии, ваше знание состояния разработки для некоторой работы TDD.
Raedwald
64

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

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

Юнит Антипаттерны

геоглиф
источник
Причина: либо преувеличенное ограничение времени, либо откровенная лень. Реорганизованное решение: найдите время написать больше тестов, чтобы избавиться от ложных срабатываний. Последняя причина нуждается в кнуте. :)
Spoike
59

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

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

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

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


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

annakata
источник
Это хороший пример акронима разработчика WOMPC. "Работает на моем ПК!" (обычно говорят, чтобы снять тестеры со спины.)
Йорис Тиммерманс
58

Цепная банда

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

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

Aaron Digulla
источник
этот просто противный .. Пробные тесты должны быть независимым понятием. Но я читал об этом в нескольких местах ... думаю, "популярный TDD" довольно запутан
Гишу
56

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

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

Gishu
источник
2
Я считаю, что причина этого в том, что у вашего тестируемого класса слишком много зависимостей. Рефакторированная альтернатива заключается в извлечении кода, который может быть изолирован.
Spoike
@Spoike; Если вы находитесь в многоуровневой архитектуре, это действительно зависит от роли класса; некоторые слои имеют тенденцию иметь больше зависимостей, чем другие.
krosenvold
Недавно я увидел в одном уважаемом блоге создание фиктивной настройки сущности, которая будет возвращена из фиктивного репозитория. WTF? Почему бы просто не создать экземпляр реальной сущности? Я только что сгорел из-за поддельного интерфейса, где моя реализация создавала исключения NotImplementedException.
Томас Эйд
40

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

[Test]
[ExpectedException(typeof(Exception))]
public void ItShouldThrowDivideByZeroException()
{
   // some code that throws another exception yet passes the test
}
Gishu
источник
Это сложно и опасно (то есть заставляет вас думать, что вы тестировали код, который всегда взрывается при каждом запуске). Вот почему я стараюсь быть конкретным в отношении класса исключений и чего-то уникального в сообщении.
Джошуа Чик
34

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


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

Гишу
источник
2
Причина: абсурдная зависимость от тестирования белого ящика. Существуют инструменты для генерации таких тестов, как Pex в .NET. Реорганизованное решение: вместо этого проверьте поведение, и если вам действительно нужно проверить граничные значения, то пусть автоматические инструменты сгенерируют остальное.
Спойк
1
До того, как появился Moq, мне пришлось отказаться от фальшивых фреймворков в пользу написания своих макетов. Было слишком легко привязать мои тесты к реальной реализации, что делало практически невозможным рефакторинг. Я не могу сказать разницу, кроме как с Moq, я редко делаю такие ошибки.
Томас Эйд
34

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

Gishu
источник
Я понимаю, что чрезмерная настройка теста обычно указывает на а) плохо структурированный код или б) недостаточную насмешку, правильно?
Topher Hunt
Ну, каждая ситуация может быть разной. Это может быть связано с высокой связью. Но обычно это случай чрезмерной спецификации, когда (сценарий ожидания) указывается каждый сотрудник в сценарии - это связывает тест с реализацией и делает их хрупкими. Если вызов сотруднику является случайной деталью теста, его не должно быть в тесте. Это также помогает сделать тест коротким и читабельным.
Гишу
32

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

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

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

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


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

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

Aaron Digulla
источник
разве это не то же самое, что инспектор?
Гишу
1
Хм ... эта строка "тестируемый класс пытается скрыть даже то, что вам нужно проверить" указывает на борьбу за власть между классом и тестом. Если это должно быть проверено ... это должно быть общедоступным как-то .. через поведение / интерфейс класса ... это как-то пахнет нарушением инкапсуляции
Gishu
2
npellow: Maven2 имеет плагин для этого, не так ли?
Аарон Дигулла
1
Это на самом деле не тестовый антипаттерн, это прагматизм для устранения недостатков в тестируемом коде. Конечно, эти недостатки лучше исправить, но это может быть невозможно в случае сторонних библиотек.
Майкл Боргвардт
1
ИДК, у него должен быть какой-то побочный эффект. Я бы проверил побочный эффект. Не уверен, что вы имеете в виду при тестировании стороннего API, я бы сказал, что вам следует обернуть это в свой собственный код, который вы можете протестировать, было использовано правильно, а затем провести интеграционный тест этого кода со сторонним API. Не будет модульного тестирования стороннего кода.
Джошуа Чик
26

Тест без имени - Ник Пеллоу

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

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

npellow
источник
7
Это точно. То, что это немного более полезно, чем тест под названием «TestMethod»
NikolaiDante
8
если только багтрекер не изменится, и вы не потеряете старый трекер и его идентификаторы ошибок ... так что PROJECT-123 больше ничего не значит ...
Chii
25

Медленная тычка

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

так называемые тесты, которые не запускаются так часто, как следовало бы

Gishu
источник
Некоторые тесты выполняются медленно по самой своей природе. Если вы решили не запускать их так часто, как другие, убедитесь, что они, по крайней мере, запускаются на сервере CI как можно чаще.
Крис Вест
Это очевидный вопрос, но каковы наиболее общие способы исправить это?
Topher Hunt
Это изначально кажется полезным, а?
Кев
1
@TopherHunt Обычно тесты медленные, потому что они имеют дорогую зависимость (например, файловая система, база данных). Хитрость заключается в том, чтобы анализировать зависимости, пока вы не увидите проблему, а затем протолкнуть зависимость вверх по стеку вызовов. Я написал пример, в котором мои ученики взяли свой набор юнит-тестов с 77 до 0,01 секунды, исправив их зависимости: github.com/JoshCheek/fast_tests
Джошуа Чик,
20

Бабочка

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

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

оборота Аарон Дигулла
источник
Что такое анти-паттерн здесь: Как выглядит этот тест? Есть ли исправление? Есть ли спорно преимущество кода испытуемого факторизовать зависимость , как System.DateTime.Now, помимо того , что более простые или более детерминированные модульные тесты?
Мерлин Морган-Грэм,
1
В Java примером может быть вызов toString()объекта, который не перезаписывает метод. Это даст вам идентификатор объекта, который зависит от адреса памяти. Или toString()содержит первичный ключ объекта, который изменяется при каждом запуске теста. Есть три способа исправить это: 1. изменить код, который вы тестируете, 2. использовать regexp для удаления переменных частей результатов теста или 3. использовать мощные инструменты для перезаписи системных служб, чтобы они возвращали предсказуемые результаты.
Аарон Дигулла
Основная причина этого анти-паттерна в том, что тестируемый код не заботится о том, сколько усилий он может потратить на его тестирование. Так что каприз разработчика - это крыло бабочки, которое вызывает проблемы в других местах.
Аарон Дигулла
19

Мерцающий тест (Источник: Ромилли Кокс)

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

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

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

Стюарт
источник
@Stuart - обязательно посмотрите видео, описывающее это "Автомобиль заглох - попробуйте сейчас!" videosift.com/video/… Этот шаблон также можно назвать «Попробуй сейчас!» или просто - «Тест
Flakey
1
Однажды я написал тест для PRGN, который обеспечил правильное распределение. Время от времени это может произойти сбой наугад. Пойди разберись. :-)
Крис Вест
1
Разве это не будет хорошим тестом? Если какой-либо тест не пройден, вам нужно отследить источник проблемы. Я боролся с кем-то по поводу теста, который провалился между 9p и полуночью. Он сказал, что это было случайно / периодически. В конечном итоге это было связано с ошибкой, связанной с часовыми поясами. Пойди разберись.
Трентон
@ Кристиан Вест Хансен: ты не мог посеять это?
Эндрю Гримм
@trenton Это хороший тест, если разработчики могут потрудиться отследить его, вместо того, чтобы просто игнорировать его (с чем они могут справиться, поскольку это проходит большую часть времени).
Уилл Шеппард
19

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

Тест, который запускает некоторый настроенный код, а затем должен «подождать» определенное количество времени, прежде чем он сможет «увидеть», работает ли тестируемый код как ожидалось. TestMethod, который использует Thread.sleep () или эквивалентный, - это, безусловно, тест «Жди и смотри».

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

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

Анти-паттерн «Жди и смотри» не следует путать со спящим .

npellow
источник
Хм .. ну я использую что-то вроде этого. как еще я смогу протестировать многопоточный код?
Гишу
@ Гишу, ты действительно хочешь тестировать несколько потоков одновременно? Я пытаюсь просто выполнить модульное тестирование того, что метод run () делает изолированно. Самый простой способ сделать это - вызвать run (), которая будет блокировать вместо start () модульный тест.
npellow
@Gishu использует CountDownLatches, Семафоры, Условия и т.п., чтобы потоки сообщали друг другу, когда они могут перейти на следующий уровень.
Крис Вест
Пример: madcoderspeak.blogspot.com/2008/11/… Brew button evt. Наблюдатель периодически опрашивает и выдает измененные события. В этом случае я добавляю задержку, чтобы потоки опроса могли запускаться до завершения теста.
Гишу
Я думаю, что мультипликационная ссылка не работает.
Эндрю Гримм
17

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

Gishu
источник
1
Может также случиться так, что тестируемый класс пытается сделать слишком много.
Майк Два
16

Гигант

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

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

Gishu
источник
15

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

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

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

Gishu
источник
1
Если вы думали, что прошивать GUI - это неправильно, я видел кого-то, кто написал тест jUnit, который запустил GUI и для продолжения нуждался во взаимодействии с пользователем. Он повесил остальную часть тестового набора. Так много для автоматизации тестирования!
Spoike
Я не согласен. Тестировать GUI сложно, но они также являются источником ошибок. Не проверять их просто лень.
Рэй
3
Дело в том, что вы не должны тестировать GUI, а должны тестировать не только через GUI. Вы можете выполнять тестирование без головы без графического интерфейса. Сохраняйте графический интерфейс настолько тонким, насколько это возможно - используйте аромат MVP - тогда вы можете просто не тестировать его. Если вы обнаружите, что у вас постоянно появляются ошибки в тонком слое GUI, покрывайте его тестами ... но в большинстве случаев я не считаю, что это стоит затраченных усилий. «Проводные» ошибки графического интерфейса обычно легче исправить ...
Гишу
@Spoike: управляемые ручные тесты не являются плохими, и при этом не использует jUnit (или любую другую структуру модульного тестирования), чтобы управлять автоматическим тестированием, которое не является модульными тестами. Вы просто не должны помещать их в один и тот же проект и не относиться к ним как к модульным тестам (например, запускать постоянно или после каждой сборки).
Мерлин Морган-Грэм
1
@ MerlynMorgan-Graham Я согласен, и я не имел в виду, что вы не должны тестировать GUI. Убеждение членов команды в том, что можно совмещать управляемые ручные тесты с автоматическими, беспокоило меня. Позже я узнал, что это был отличный способ заставить всех, кто не привык к TDD, прекратить его использовать. Я считаю, что смешивание функциональных тестов (которые являются нестабильными) с модульными тестами (которые должны быть стабильными) плохо, если вы хотите следовать процессу TDD.
Спойк
14

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

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

«Спящего» не следует путать с анти-паттерном « Жди и смотри ».

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

npellow
источник
Я бы предпочел назвать это дремлющим вулканом :) ... но я знаю, о чем вы говорите ... например, дата, выбранная в качестве будущей даты для теста на момент написания, станет настоящей / прошедшей датой, когда эта дата проходит .. преодолевая испытание Не могли бы вы опубликовать пример ... просто чтобы проиллюстрировать это.
Гишу
@Gishu - +1. Я думал так же, но не мог определиться между ними. Я обновил название, чтобы сделать это немного яснее;)
npellow
11

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

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

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

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

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

Преподобный Гонзо
источник
8
:) - также известный как бэкдор соответствия процессу.
Гишу
1
У нас был пример этого недавно в тесте и тестируемом методе, который неоднократно подвергался рефакторингу. После нескольких итераций тест превратился в вызов тестируемого метода. И поскольку метод теперь возвращает void, не было никаких утверждений, которые могли бы быть утверждены. Таким образом, в основном, тест просто проверял, что метод не вызывает исключения. Не имело значения, действительно ли он делал что-то полезное или правильное. Я нашел это в обзоре кода и спросил: «Так ... что мы здесь тестируем?»
Marvo
11

получил немного этим сегодня:

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

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

Зак Томпсон
источник
Вы можете использовать временную папку-правило junit, чтобы избежать мокрых полов.
DaveFar
Этот вид относится к анти-паттерну непрерывной интеграции. В CI каждый разработчик должен иметь собственное рабочее пространство и ресурсы, а машина для сборки также должна быть его собственной средой. Тогда вы избегаете таких вещей, как проблемы с разрешениями (или, может быть, вы
прячете
11

Кукушка - Фрэнк Карвер
. Модульное тестирование, которое проходит в тестовом наборе с несколькими другими и использует тот же (потенциально длительный) процесс настройки, что и другие тесты в тестовом примере, но затем отбрасывает некоторые или все артефакты из установки и создает свое.
Расширенный Симптом: ненадлежащим образом совместное приспособление

Gishu
источник
10

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

[Test]
public void ShouldNotThrow()
{
   DoSomethingThatShouldNotThrowAnException();
}
Gishu
источник
2
На самом деле это может быть действительным тестом, на мой взгляд - особенно в качестве регрессионного теста.
Илья Пройс
извините, опять перепутали это с Silent catcher ... модульные тесты должны четко указывать намерения о том, что тестируется, а не говорить "это должно работать" .. (+1 тп что-то лучше, чем ничего. особенно если вы находитесь в устаревшей регрессии страна)
Гишу
1
В таких тестах я по крайней мере ловлю Exception и присваиваю его переменной. Тогда я утверждаю, что не ноль.
Томас Эйд
4
Некоторые фреймворки имеют Assert.DoesNotThrow(SomeDelegateType act)утверждение стиля, которое можно использовать специально в подобных случаях. Я нахожу это менее грубым, чем тестовый пример, который завершается успешно, когда конструктор возвращает ненулевое значение, но завершается неудачей, когда конструктор генерирует ошибку. Конструктор никогда не вернет ноль. (Примечание: применяется только к языкам, где конструктор гарантированно возвращает ненулевое значение)
Мерлин Морган-Грэм,
10

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

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

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

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

gcrain
источник
@gcrain .. тесты должны быть детерминированными. ИМО лучшим подходом было бы использовать «общеизвестный в команде» порт для тестирования и очистки до и после теста правильно, чтобы он всегда был доступен ...
Gishu
1
@gishu - проблема не в том, что нет методов setup () и teardown () для обработки этих портов. проблема, например, в том, что сервер CI запущен, и одновременно запускается несколько версий теста, пытающихся использовать одни и те же номера портов, жестко запрограммированные в тесте
gcrain
10

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

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

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

bhumphreys
источник
10

Сорок полюсных испытаний

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

bhumphreys
источник
9

Doppelgänger

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

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

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

оборота Аарон Дигулла
источник
7

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

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

Gishu
источник
7

Тест это все

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

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

thegreendroid
источник
6

Линия нападающий

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

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

оборота Руслан Джаббаров
источник