Должны ли мы всегда проверять ошибки модуля при их исправлении?

29

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

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

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

Zonko
источник
Этот случай ошибки относится к новому дизайну? Для меня частью нового дизайна было бы повышение надежности проекта, так что вы могли бы использовать это для оправдания удаления этого контрольного примера, если этот тип ошибки был связан с ошибкой в ​​первоначальном проекте.
Тимин
Реактор касается чего-то другого, и в новом дизайне все еще возможно немного модифицировать код и повторно ввести ошибку, за которой следит тест. Я полагаю, что альтернативой тесту будет комментарий в коде, говорящий «не трахайся с этим», но это звучит как неправильная вещь: p
Zonko
1
если это слишком сложно для юнит-теста, включите его в интеграционный тест
ratchet freak
Похоже, это требует интеграционного теста, а не модульного теста. Исходя из того, что ты так издеваешься. Общее правило, которое я видел, состоит в том, что вы не тестируете код, который общается с компонентами вне вашей кодовой базы (общение с базой данных, чтение из файловой системы и т. Д.), Что также похоже на то, что он делает.
Лукас

Ответы:

27

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

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

Telastyn
источник
Я бы добавил больше акцента на это и констатировал бы, что в идеальном мире это будет считаться ошибкой только в том случае, если существует неуспешный модульный тест, но +1 для курсива и с учетом того, что потребности бизнеса должны преобладать.
Джошуа Дрейк
2
ну, в конце концов, в конечном итоге все сводится к балансу между временем, необходимым для поддержания теста, и временем, которое понадобится нубу для обнаружения и исправления ошибки, если она повторится снова.
Зонко
Я также предпочел бы обобщить тест, чтобы он не просто тестировал прерывание и повторную попытку задания, когда оно достигает одного определенного состояния, но скорее тестировал прерывание и повторную попытку в каждом состоянии, в котором может быть задание.
Old Pro
+1 за «так как прерывания из-за ошибок, как правило, имеют больше накладных расходов, чем просто разработка и сопровождение модульного теста».
Питер К.
16

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

Карл Манастер
источник
7

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

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

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

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

Томас Оуэнс
источник
5

Да, ты должен.

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

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

CodeART
источник