Чем лучше модульное тестирование, чем просто тестирование всего приложения в целом? - PullRequest
8 голосов
/ 28 апреля 2009

Я не понимаю, какую пользу может принести юнит-тест. Разве тестеру не достаточно протестировать весь вывод в целом, а не выполнять модульные тесты?

Спасибо.

Ответы [ 15 ]

8 голосов
/ 28 апреля 2009

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

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

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

5 голосов
/ 28 апреля 2009

Из моего опыта:

  1. Интеграционное и функциональное тестирование, как правило, более показательно для общего качества системы, чем костюм для модульного тестирования.
  2. Тестирование высокого уровня (функциональное, приемочное) является инструментом обеспечения качества.
  3. Юнит-тестирование - это инструмент разработки . Особенно в контексте TDD, где модульное тестирование становится скорее реализацией проекта, а не гарантией качества.
  4. В результате улучшения дизайна качество всей системы улучшается (косвенно).
  5. Прохождение пакета модульных тестов предназначено для гарантии того, что один компонент соответствует намерениям разработчика (правильность). Приемочный тест - это уровень, который охватывает валидность системы (то есть система делает то, что хочет от нее пользователь).

Резюме:

  • Сначала модульное тестирование подразумевается как инструмент разработки, а затем как инструмент обеспечения качества.
  • Приемочный тест подразумевается как инструмент обеспечения качества.
5 голосов
/ 28 апреля 2009

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

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

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

Сколько денег будет стоить GM отозвать 10000 автомобилей, потому что каталитический нейтрализатор не работает должным образом?

Теперь подумайте, сколько им будет стоить, если они обнаружат, что сразу после того, как эти преобразователи были им доставлены, но за до их посадили в эти 10 000 автомобилей.

Я думаю, вы найдете последний вариант немного дешевле.

Это одна из причин того, почему разработка через тестирование и непрерывная интеграция (иногда) полезны - тестирование проводится постоянно.

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

2 голосов
/ 07 мая 2009

Согласен с большинством ответов. Давайте углубимся в тему скорости. Вот некоторые реальные цифры:

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

  2. Автоматический функциональный тест приводит к 1 или 2 часам . Они работают на упрощенной платформе, но иногда охватывают несколько систем и базу данных - что действительно убивает скорость.

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

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

Я хочу выяснить, что я сломал за 1 или 2 минуты, а не через несколько недель, даже за несколько часов. Отсюда и 10-кратная рентабельность инвестиций в модульные тесты.

2 голосов
/ 28 апреля 2009

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

На вопрос о том, зачем тестировать небольшие участки кода, подумайте: предположим, что ваше гигантское приложение использует классную схему шифрования XOR, которую вы написали, и в конечном итоге руководство продукта изменит требования к тому, как вы генерируете эти зашифрованные строки. Итак, вы говорите: «Черт, я написал процедуру шифрования, поэтому я продолжу вносить изменения. Мне потребуется 15 минут, и мы все пойдем домой и устроим вечеринку». Ну, возможно, вы внесли ошибку во время этого процесса. Но ждать!!! Ваш удобный метод тестирования TestXOREncryption () немедленно сообщает вам, что ожидаемый вывод не соответствует вводу. Бинго, вот почему вы заранее разбили свои юнит-тесты на маленькие «единицы» для тестирования, потому что в вашем гигантском приложении вы бы не поняли это так быстро.

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

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

2 голосов
/ 28 апреля 2009

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

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

2 голосов
/ 28 апреля 2009

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

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

1 голос
/ 28 апреля 2009

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

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

1 голос
/ 28 апреля 2009

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

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

  • Предоставляет невосполнимых документации
  • Возможность изолировать ошибки от конкретных компонентов
  • Проверка инвариантов в коде
  • Обеспечение быстрой, немедленной обратной связи с изменениями в кодовой базе.
1 голос
/ 28 апреля 2009

К этому сложному вопросу нужно подходить, потому что он ставит под сомнение что-то такого огромного размера. Вот мой короткий ответ, однако:

Test Driven Development (или TDD) стремится доказать , что каждая логическая единица приложения (или блок кода) функционирует именно так, как и должна. Делая тесты настолько автоматизированными, насколько это возможно, для повышения производительности, как это может быть вредным?

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

Суть в том, что если что-то в приложении целом ломается, то есть просто смотрит на общий результат / результат, как вы узнаете, откуда оно? Ну, отладка, конечно! Что возвращает вас туда, откуда вы начали. TDD позволяет - с надеждой - обойти этот самый болезненный этап в развитии.

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