Всегда ли хрупкие модульные тесты - это плохо?

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
14
0
5 053
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

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

Ответ принят как подходящий

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

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

Модульные тесты должен будут хрупкими - должен их легко сломать. Если они не ломаются, то это вообще не модульные тесты; это комментарии к коду.

...

или я упускаю суть вопроса?


Редактировать: Я должен уточнить свой предыдущий ответ.

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

Я не согласен, исправление хрупких тестов требует значительного обслуживания. Одна из целей модульного тестирования - сократить время обслуживания. У UnitTest должна быть только одна логическая причина отказа.

Restuta 03.12.2010 19:41

@Restuta Цель модульных тестов - обеспечить единообразие их поведения или методов. Обеспечение согласованности защищает от ошибок. Раннее обнаружение этих ошибок приводит к меньшим затратам на обслуживание. Не путайте цель с эффектом.

Sled 02.06.2011 19:34

@Restuta Я думаю, что автор имел в виду, что модульные тесты ломаются по неправильным причинам. Тесты должны сломаться только в том случае, если ваш тестируемый метод работает неправильно, если тесты легко ломаются из-за других изменений / зависимостей, тогда они «хрупкие».

Artem Goutsoul 01.12.2015 10:01

@Artem Goutsoul согласен, это мое понимание.

Restuta 03.12.2015 01:41

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

Arne Vogel 26.02.2019 20:22

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

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

Определенным "запахом" случайно-хрупкого теста является использование в тесте функции sleep ().

Я бы сказал, что ваши тесты должны моделировать работу сокета или потока с помощью имитаций. Проверка фактической связи сокетов - это интеграционный тест. Модульный тест должен проверить, что реализация работает, как ожидалось, при условии, что связь через сокеты работает. Вы говорите, что использование «сна» - это признак запаха, но перед этим вы говорите использовать другие устройства «ожидания», так что же это такое? Я думаю, что любое использование «ждущих» устройств является признаком того, что этот тест действительно должен быть интеграционным тестом, а его поведение должно быть разделено на модульный тест с фиксациями. Мой 2c.

Brad Cunningham 02.09.2010 21:51

Под устройствами ожидания я подразумеваю любой механизм без опроса - в идеале обратные вызовы или мьютекс ожидания. Или select ();) В целом я согласен с тем, что mocks обязательно следует использовать везде, где это возможно.

metao 13.09.2010 10:54

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

initialed85 16.03.2020 19:44

Да, хрупкость тестов - это всегда плохо. Но, похоже, это одна из тех вещей, с которыми мы должны жить, чтобы полностью протестировать наши классы. Многие классы не могут быть протестированы, как черные ящики, которые принимают некоторый ввод и возвращают некоторый вывод, как вы могли видеть с Math.cos (). Большинство из них имеют побочные эффекты для других классов или сущностей в системе, и вы должны проверить, правильно ли класс манипулировал этими сущностями. Это означает, что тест должен знать детали реализации тестируемого класса, что создает хрупкие классы.

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

Когда изменение кода, которое должно быть «внутренним» по отношению к классу (то есть без изменения API), приводит к сбою теста, есть две возможности:

  1. В коде есть новая ошибка, ИЛИ
  2. Код правильный, тест требует исправления

Попробуйте уменьшить №2. Это «хрупкие» тесты.

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

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

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

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

Другие вопросы по теме