Почему я должен и модульный тест и веб-тест (а не просто веб-тест)? - PullRequest
16 голосов
/ 07 октября 2008

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

Однако, если у вас другое мнение, я бы хотел знать:

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

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

Ответы [ 12 ]

22 голосов
/ 07 октября 2008

Покрытие кода гарантирует, что я нажму каждый функциональный фрагмент кода

«Удар» не означает означает «Тестирование»

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

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

  1. Страница загружена правильно из кэша, но фактическая база данных была повреждена
  2. Страница загружала каждый элемент из базы данных, но отображала только первый элемент - казалось, что все в порядке, несмотря на то, что он полностью потерпел неудачу в производстве, потому что это заняло слишком много времени
  3. На странице отображалось действительное число, которое на самом деле было неверным, но оно не было взято, потому что 1000000 легко принять за 100000
  4. По совпадению на странице отображалось действительное число - 10x50 - это то же самое, что и 25x20, но одно неверное
  5. Страница должна была добавить запись журнала в базу данных, но она не видна пользователю, поэтому ее не видели.
  6. Аутентификация была обойдена, чтобы заставить веб-тесты действительно работать, поэтому мы пропустили явную ошибку в коде аутентификации.

Легко придумать еще сотни примеров подобных вещей.

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

9 голосов
/ 07 октября 2008

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

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

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

5 голосов
/ 07 октября 2008

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

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

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

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

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

2 голосов
/ 17 февраля 2009

Еще один аспект - простите несколько идеальную среду, в которой это находится:

Предположим, у вас есть 3 компонента, которые наконец-то должны работать вместе. Каждый из них может быть индивидуально полностью протестирован на модуле (что бы это ни значило) с 5 юнит-тестами. Это дает 5 + 5 + 5 = 15 модульных тестов для полного охвата.

Теперь, если у вас есть интеграционный / веб / комбинированный тест, который тестирует все компоненты вместе, вам понадобится (вспомните идеальный мир для этого абстрактного сценария) 5 * 5 * 5 = 125 тесты, которые тестируют все перестановки приводят к тому же результату, что и 15 тестовых примеров выше (учитывая, что вы можете даже запускать все перестановки, иначе будет непроверенное / неуказанное поведение, которое может укусить вас позже при расширении компонентов).

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

2 голосов
/ 07 октября 2008

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

Если вы пишете модульные тесты в стиле TDD, вы, вероятно, не будете делать столько ненужного кода, потому что сосредоточитесь на крошечных шагах и будете делать только необходимое.

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

А сами юнит-тесты послужат излишней документацией того, что система делает и чего не делает.

Это лишь несколько примеров преимуществ, которые я заметил, применяя TDD к моей работе.

2 голосов
/ 07 октября 2008

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

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

1 голос
/ 07 октября 2008

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

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

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

Исправлять ошибки всегда дороже, чем раньше. Всегда.

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

1 голос
/ 07 октября 2008

Почти как сказал Дейкстра: модульные тесты можно было использовать только для того, чтобы показать, что в программном обеспечении есть дефекты, а не для того, чтобы доказать, что оно без дефектов. Таким образом, в общем случае однократное попадание в каждый путь кода (и получение 100% покрытия) не имеет ничего общего с тестированием - оно просто помогает устранить битрот.

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

Гораздо проще написать модульный тест, который запускает конкретную ошибку, чем написать сквозной (веб) тест, который выполняет ТОЛЬКО это и не выполняет кучу совершенно не относящегося к делу кода (что также может потерпите неудачу и испортите анализ основных причин).

1 голос
/ 07 октября 2008

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

Например, если у вас был веб-тест, который отправлял Ajax-запрос обратно в службу на сервере, которая затем обращалась к базе данных, которая затем не выполнялась. Это был Javascript, сервис, бизнес-логика или база данных, которая вызвала проблему?

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

0 голосов
/ 07 октября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...