2014-12-13 1 views
2

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

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

фон

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

Пример сценарий

Вы юнит-тесты, которые проверяют определенное имя файла возвращаются, такими как fileName.txt. Всюду в вашем коде этот файл ссылается на константу IMPORTANT_FILENAME, поэтому изменение имени файла не влияет на ваше приложение. Вы решили изменить имя файла с «fileName.txt» на «NewFileName.txt». Ваше приложение работает нормально, как и должно быть, но ваш модульный тест на verify(fileName,'fileName.txt') терпит неудачу. Это грубый пример, но я надеюсь, что вы поняли. Дело здесь в том, что когда я нахожу, что обновляю модульные тесты в рабочем приложении, мне кажется, что это красный флаг, который является плохим тестом. Я не могу придумать какой-либо тест, который не подходит для проходящего приложения, которое является хорошим. Но прежде чем использовать это как правило и начать удаление, я хотел бы получить некоторую обратную связь. Вы согласны; модульные тесты не должны терпеть неудачу в проходящем приложении?

Боковое примечание: Я не думаю, что это имеет значение, но я использую Java, Junit и Mockito.

+0

Это зависит от контекста. Почему ваше приложение не работает при сбое компонента? –

+2

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

+0

Я добавлю несколько примеров –

ответ

1

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

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

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

+0

Если вы изменяете реализацию внутри класса, тесты нуждаются или даже не должны терпеть неудачу (например, заменить одну реализацию List на другую). Если в вашем приложении вы заменяете последовательный поиск двоичным поиском: почему при любом тесте не удается выполнить проверку? – laune

+0

@laune Я думаю, что я думаю о более существенных изменениях, чем те, которые вы упомянули, которые я согласен, не должны нарушать никаких хороших тестов. – dkatzel

+0

@dkatzel. Итак, чтобы вернуться к вашему первому предложению, если я изменю свое приложение и оно пройдет, t понять, почему единичный тест должен завершиться неудачей? Это похоже на то, что он победил ее цель. –

0

Хороший тест может завершиться неудачно, если ничто в приложении не сработало или не сработает. Как правило, модульные тесты должны охватывать некоторые аспекты приложения, которое может произойти. Однако, даже если вы можете написать тестовые сценарии, которые охватывают каждый сценарий (большое предположение), может случиться так, что хороший модульный тест не имеет отношения к такому сценарию. Тем не менее, кто знает, может ли кто-то изменить заявку, в которой такой тест будет иметь значение. Предположим, вы реализуете класс Map, но ваше приложение никогда не использует метод remove (Key).Тем не менее, вы внедрили тесты на удаление (ключ). Несмотря на то, что ваше приложение в настоящее время никогда не использует метод remove, кто-то может прийти в какой-то момент и использовать этот метод.

+0

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

+0

@UsmanMutawakil Возможно, тест проверит угловой футляр, а угловой корпус не попал во время ручного тестирования. –

+0

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

2

Для меня основные цели единичных тестов

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

так что если вы измените что-то важное для вашего приложения (т.е. изменение функциональности), и тесты модулей не прерываются, у вас плохие модульные тесты. Может быть, например, единичный тест, чтобы убедиться, что все поля являются частью equals/hashcode. Или могут быть модульные тесты, чтобы утверждать, что определенные классы неизменяемы. Ваши функциональные тесты могут по-прежнему работать, но вы вводите нежелательный код.

Еще одна важная вещь - возможность делать TDD (Test Driven Development).

2

В вашем примере, да, это плохой тест. Если контракт API должен вернуть содержимое IMPORTANT_FILENAME, тест должен быть проверен для этого, а не жестко закодированная строка. В общем случае, если тест не работает, приложение не обязательно обязательно терпит неудачу. Цель модульного теста - не столько обеспечить функциональность приложения, сколько обеспечить выполнение контракта api. Но даже если бы это было так, простые правила логики скажут вам, что «приложение терпит неудачу => тесты сломаны» - не эквивалентен «тесты сломаны => приложение не работает».

+1

У вас есть встречный пример теста, который выходит из строя после изменения кода, но рассматриваемая заявка по-прежнему полностью функциональна, что вы по-прежнему считаете релевантным контрольная работа? –

+1

Несомненно. Рассмотрим тест для функции arcLength (двойной радиус, двойной угол), вычисляющий длину сегмента окружности, который сломан, и возвращает его второй параметр, а не кратный двум. Приложение использует эту функцию для вычисления длин различных дуг окружности с радиусом 1 дюйм и работает нормально. Тест 'assertEquals (4.0, arcLength (2.0, 2.0))' fail, показывая, что функция сломана. – Dima

+1

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

1

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

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

+0

Мне нравится аналог ложной тревоги. –

Смежные вопросы