Какова ценность проверки при неудачных юнит-тестах?

13

Хотя существуют способы не допустить выполнения модульных тестов, какова ценность проверки при неудачных модульных тестах?

Я буду использовать простой пример: чувствительность к регистру. Текущий код чувствителен к регистру. Допустимый вход в метод - «Cat», и он будет возвращать перечисление Animal.Cat. Однако желаемая функциональность метода не должна учитывать регистр символов. Таким образом, если описанный метод был передан как «cat», он может вернуть что-то вроде Animal.Null вместо Animal.Cat, и модульный тест завершится неудачей. Хотя простое изменение кода сделает эту работу, более сложная проблема может занять несколько недель, но выявление ошибки с помощью модульного теста может быть менее сложной задачей.

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

Какова ценность проверки в модульных тестах, которые осуществляют ошибку до тех пор, пока кто-то не сможет исправить код?

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

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

Джим Г.
источник
Это один из способов увеличить число тестовых покрытий.
JeffO
Если вы уже приложили усилия для написания модульного теста, зачем вам его переписывать, когда вы решаете проблему? Тот факт, что он зарегистрирован, не означает, что его нужно запускать в комплекте. (Вы можете создать категорию для «Известных проблем» и рассматривать эти тесты как список невыполненных заданий / TODO.)
Калеб

Ответы:

17

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

Вместо этого я использую

  • [Ignore("Reason")]атрибут, который делает результат желтым или
  • throw new NotImplementedException()это делает результат серым

Примечание: я использую NUnit для .net. Я не уверен, присутствует ли «серая» функция в других инфраструктурах unittest.

Поэтому мне нравится следующее значение результатов юнит-теста.

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

Все, кроме "красного" может быть проверено.

Чтобы ответить на вопрос: проверка «red-failed-testes» приносит больше вреда, чем значения, но проверка в «yellow-ignored-tests» или «grey-NotImplementedYet-tests» может быть полезна в качестве списка задач.

k3b
источник
проблема, которую я вижу с этим подходом, состоит в том, что проигнорированные тесты, вероятно, никогда не будут исправлены. Вы также можете просто удалить весь тестовый код, в чем будет разница (я немного дерзкий)
Lovis
4
will probably never be fixedэто политическое решение, если вы хотите провести efford в автоматических тестах или нет. С помощью "игнорируемых тестов" у вас есть шанс их исправить. Выбросить «игнорируемые тесты» означает «отказаться от автоматических тестов до тех пор, пока их больше не будет»
k3b
8

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

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

Тисон Т.
источник
5
Но вы никогда не должны регистрироваться в неудачном тесте, так как ваш сервер сборки не должен создавать проект с поврежденным тестом.
CaffGeek
@Chad: сборка и тестирование - это две отдельные части одного автоматизированного шага. Сборка гарантирует, что все компилируется. Тест гарантирует, что результат сборки действителен. Моя интерпретация вопроса не была "я должен проверить код, который не компилируется?" Вместо этого это было, "я должен проверить в тесте, который я знаю, потерпит неудачу?"
unholysampler
1
Я просто добавил, что некоторые серверы непрерывной интеграции запускают тесты, и если они терпят неудачу, они не развертываются. Правильно, как если бы сборка не удалась, код не сработал, и нет смысла развертывать продукт, который, как известно, поврежден.
CaffGeek
@ Чед: Хорошо, я полностью забыл о CI серверах. Это определенно было бы вопросом для рассмотрения. Также стоит уточнить, что мы подразумеваем под «сломанными» тестами; это просто "плохие" тесты или тест не пройден, потому что API каким-то образом изменился?
Tieson T.
Вопрос должен был быть более понятным. Должно быть, тест скомпилируется, но ожидаемый результат не удастся.
6

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

Короче говоря, неудачные юнит-тесты дают команде список «TODO».

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

[* При условии, что модульные тесты действительно проверяют что-то полезное.]

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

Целью модульных тестов является утверждение ожидаемого поведения системы, а не документирование дефектов. Если мы используем модульные тесты для документирования дефектов, то их полезность для подтверждения ожидаемого поведения уменьшается. Ответ на вопрос «Почему этот тест не прошел?» не просто «О, что-то сломано, что я не ожидал, что сломается». Стало неизвестным, ожидаемый или неожиданный сбой теста.

Вот параграф с начала главы 13 « Эффективной работы с устаревшим кодом» :

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

Мэтью Родатус
источник
3

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

ПРИМЕЧАНИЕ. Этот проект должен быть настроен так, чтобы не быть собранным на сервере сборки, если ваш сервер сборки предотвращает проверки, нарушающие сборку (при условии, что вы определяете сломанную сборку как ту, в которой не проходят все тесты)

CaffGeek
источник
+1, хотя нет ответа, если проверить или нет, есть важный аргумент: build server
k3b
Я бы предпочел использовать атрибут, чтобы пометить такой тест, а не перемещать его в отдельный проект.
CodesInChaos
2

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

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

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

unholysampler
источник
Вау ... "Точка модульного тестирования не в том, чтобы иметь 100% -ый успех", ты хочешь сказать, что им не нужно все проходить !?
CaffGeek
2
@Chad: Дело в том, что лучше иметь тесты, которые, как вы знаете, потерпят неудачу, но демонстрируют реальную проблему, а не тестируют, просто чтобы у вас была зеленая галочка в конце ночной сборки / теста.
unholysampler
8
@unholysampler, никогда не ломайте тесты, если только они ЯВНО не помечены как «следует» (находясь в другом проекте). В противном случае они становятся шумом, и вы не знаете, когда тест, который должен пройти, был сломан. Это полностью побеждает цель непрерывной интеграции и проведения
юнит-тестов
2
@Chad: я думаю, что это входит в семантику определений. Исходя из ОП, звучало так, будто он говорил о создании действительного теста, в котором обнаружена ошибка. Однако ошибка имеет низкий приоритет и вряд ли будет исправлена ​​немедленно. Вы - тот, кто начал Непрерывную Интеграцию, которая накладывает гораздо более строгие ограничения на автоматизированный процесс.
unholysampler
4
@unholysampler, CI, или нет CI, дело в том, что когда вы запускаете тесты и привыкли видеть какие-то красные огни, вы к этому привыкли. Итак, когда что-то зеленое становится красным ... откуда ты знаешь?!? Это ужасная практика, и одна из причин, по которой тестирование не может быть принято во многих организациях.
CaffGeek
1

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

SnoopDougieDoug
источник
-3

Как я вижу, TDD завершен с реализацией тестов для незавершенного кода, сначала пишите тесты с атрибутом [ExpectedException] или подобным. Первоначально это должно пройти, поскольку неполный код не будет содержать никакой логики и будет писать новый код Exception (). Хотя сквозное исключение является неправильным, это по крайней мере заставило бы тесты пройти сначала и пригодно для регистрации. Мы можем забыть проигнорированный тест, но можем наверстать упущенное или заполнить неполный код. Когда мы сделаем это, автоматически соответствующий тест, который ожидал исключения, теперь начал бы проваливаться и сигнализировать вам об этом. Это может включать небольшое изменение теста, чтобы избавиться от ExpectException и вместо этого сделать реальные утверждения. CI, Dev, тестеры и клиенты все счастливы и беспроигрышная ситуация?

user211764
источник
1
Это не отвечает на вопрос. Не спрашивать, что такое TDD и зачем проверять ожидаемые исключения.
Энди Визендангер