В чем разница между модульными, функциональными, приемочными и интеграционными тестами? [закрыто]

799

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

Эндрю
источник
1
См. Также sqa.stackexchange.com/a/23396/8992
Майкл Даррант,
1
Я думаю, что вы забыли включить нагрузочное тестирование!
Обсуждение дешево Показать мне код

Ответы:

1350

В зависимости от того, куда вы смотрите, вы получите несколько разные ответы. Я много читал на эту тему, и вот моя перегонка; опять же, они слегка шерстистые, и другие могут не согласиться.

Модульные тесты

Тестирует наименьшую единицу функциональности, обычно это метод / функцию (например, если дан класс с определенным состоянием, вызов метода x в классе должен вызвать y). Модульные тесты должны быть сосредоточены на одной конкретной функции (например, вызов метода pop, когда стек пуст), должен генерировать InvalidOperationException). Все, к чему это касается, должно быть сделано в памяти; это означает, что тестовый код и тестируемый код не должны:

  • Вызвать (нетривиальных) соавторов
  • Доступ к сети
  • Хит базы данных
  • Используйте файловую систему
  • Раскручивать нить
  • и т.п.

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

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

Интеграционные тесты

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

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

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

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

Функциональные тесты

Функциональные тесты проверяют правильность конкретной функции, сравнивая результаты для данного ввода со спецификацией. Функциональные тесты не касаются промежуточных результатов или побочных эффектов, а только результата (их не волнует, что после выполнения x объект y имеет состояние z). Они написаны для проверки части спецификации, такой как «вызов функции Square (x) с аргументом 2 возвращает 4».

Приемочные испытания

Приемочные испытания, похоже, делятся на два типа:

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

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

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

Вывод

Они все дополняют друг друга. Иногда выгодно сосредоточиться на одном типе или полностью отказаться от них. Основное отличие для меня состоит в том, что некоторые тесты смотрят на вещи с точки зрения программиста, тогда как другие используют ориентацию на клиента / конечного пользователя.

Марк Симпсон
источник
19
+1. @Mark Simpson Можно ли назвать функциональное и приемочное тестирование «системным тестированием»? Где подходят сквозные тесты? (слишком много другого словарного запаса на мой вкус)
Торстен Энгельбрехт
3
@Franz Я говорил о способности и простоте, с которой вы можете уменьшить риск, изолируя блоки кода и тестируя их. Вы правы, хотя язык, который я использовал, был немного свободен, так как тесты не могут доказать, что код не содержит ошибок.
Марк Симпсон
15
Несмотря на голоса избирателей, это совершенно неправильно. Юнит-тесты не проверяют даже «тривиальных» соавторов; любая введенная зависимость должна быть осмеяна. Функциональные тесты не проверяют «поведение»; они проверяют только «функцию», т.е. «f (A) возвращает B». Если побочные эффекты имеют значение, это «поведенческий». Если они включают системные вызовы, они также являются «системными» тестами, как в «поведенческих системных тестах». (См. Testerab @ ниже.) «Приемочные» тесты являются подмножеством «поведенческих системных тестов», которые охватывают полный стек. «Интеграция» тестирует вверх, имитируя фактическое использование; это проверяет, что все зависимости могут быть интегрированы на практике.
cdunn2001
7
@ cdunn2001: не волнуйтесь, конструктивная критика всегда хороша :) Ваш комментарий научил меня нескольким вещам, которых я не знал, и несколько очистил мою терминологию. Я всегда стремлюсь узнавать что-то новое от разработчиков, которые заинтересованы в тестировании. Я помню первый раз, когда я обнаружил блог Мишко Хевери - это было похоже на сокровищницу :)
Марк Симпсон,
11
@MarkSimpson, хотя ваш ответ очень хороший, я хотел бы немного подробнее рассказать о функциональных тестах. Я имею в виду, что в вашем ответе мне сложно различить функциональные и модульные тесты. Я надеюсь, у вас есть время для этого, продолжайте в том же духе!
Андрей Сандулеску
90

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

Недавно я наткнулся на систему именования Google для их тестов, и мне она очень нравится - они обходят аргументы, просто используя Small, Medium и Large. Чтобы решить, к какой категории относится тест, они учитывают несколько факторов: сколько времени требуется для запуска, имеет ли он доступ к сети, базе данных, файловой системе, внешним системам и так далее.

http://googletesting.blogspot.com/2010/12/test-sizes.html

Я полагаю, что разница между Small, Medium и Large для вашего текущего рабочего места может отличаться от Google.

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

testerab
источник
6
+1 для названия Google Test Test, так как это помогает дать некоторое представление о том, почему различные организации / люди имеют разные определения для тестов.
Марк Симпсон
Это также очень хорошая статья, рассказывающая о том,
testerab
63

http://martinfowler.com/articles/microservice-testing/

В блоге Мартина Фаулера говорится о стратегиях тестирования кода (особенно в архитектуре микросервисов), но большинство из них применимо к любому приложению.

Я процитирую из его краткого слайда:

  • Модульные тесты - используйте мельчайшие части тестируемого программного обеспечения в приложении, чтобы определить, ведут ли они себя должным образом.
  • Интеграционные тесты - проверка путей связи и взаимодействия между компонентами для выявления дефектов интерфейса.
  • Тесты компонентов - ограничивают область применения проверенного программного обеспечения частью тестируемой системы, манипулируя системой через внутренние интерфейсы кода и используя удвоенные значения теста, чтобы изолировать тестируемый код от других компонентов.
  • Контрактные тесты - проверяют взаимодействие на границе внешнего сервиса, утверждая, что он соответствует контракту, ожидаемому сервисом-потребителем.
  • Сквозные тесты - убедитесь, что система отвечает внешним требованиям и достигает своих целей, тестируя всю систему от начала до конца.
Максим
источник
Кстати, это отличная статья. Однако я не совсем понимаю, для чего предназначен контрактный тест. Разве они не избыточны в свете тестов компонентов и интеграции?
Wheleph
В некоторых языках (которые использует г-н Фаулер) вы можете реализовать интерфейс, который не отображается при использовании стандартного определения класса, например, void IMyInterface.MyMethod (). Который, в свою очередь, имел бы свои собственные тесты. Хотя в этот момент вы возвращаетесь к BDD. По иронии судьбы, мистер Фаулер тоже захватил землю.
Скарсник
2
это не статья Фаулера, кстати, только что опубликованная там. Контрактные тесты - это тесты, которые проводятся после того, как клиенты начинают использовать ваш сервис, затем вы пишете тесты, которые проверяют, не сломали ли вы что-то для этих конкретных клиентов, то есть изменили API сервиса.
Рафал Лужинский
@wheleph модульные, интеграционные и компонентные тесты говорят в основном о внутренних компонентах программного обеспечения, которые в значительной степени контролируются разработчиком. Проблема в первых трех случаях означает изменение источника для устранения проблемы. - Контрактные тесты касаются того, что вам обещано в функциональности, но вы не сможете изменить непосредственно перед лицом дефекта. Это требует добавления кода поддержки, чтобы обойти эти возможные проблемы, а не просто исправить дефект. - Таким образом, вы работаете над веб-сервисом, возвращающим вам неправильно сформированный json, даже если в спецификации контракта сказано, что он имеет определенную структуру.
Йеми Беду
31

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

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

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

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

1) сверху вниз
2) снизу вверх

шах
источник
Что вы имеете в виду сверху вниз и снизу вверх? Является ли интеграционное тестирование таким же, как сквозное тестирование?
tamj0rd2
18

Это очень просто.

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

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

  3. Приемочные испытания: известны как UAT. И это на самом деле сделано тестером, а также разработчиками, командой менеджеров, авторами, писателями и всеми, кто участвует в этом проекте. Чтобы убедиться, что проект наконец готов к отправке без ошибок.

  4. Интеграционное тестирование. Единицы кода (объясненные в пункте 1) интегрированы друг с другом для завершения проекта. Эти блоки кодов могут быть написаны с использованием другой технологии кодирования или могут иметь разные версии, поэтому разработчики проводят это тестирование, чтобы убедиться, что все блоки кода совместимы с другими, и что нет проблем интеграции.

Ракеш Кумар
источник
1
@OlegTsyba ответ пришел через 4 года после ответа на вопрос.
бентеша
1
Мы никогда не должны начинать ответ с «Это очень просто», особенно если это такая сложная тема, как эта.
milosmns
6

Некоторые (относительно) недавние идеи против чрезмерного насмешки и чистого юнит-тестирования:

cdunn2001
источник
Я новичок в тестировании кода. Модульные тесты кажутся в основном пустой тратой времени. Я думал, что выполняю модульное тестирование, но я проводил интеграционное тестирование, а затем я прочитал о модульном тестировании, и это кажется глупым, может быть, для людей с очень небольшим опытом? Есть шанс, что я упускаю какую-то точку.
PixMach
Если Единица определена широко, значит, вы правильно юнит-тестирование. Я против тестирования деталей реализации. Частный класс не должен быть «модульным». Однако, если у вас есть несколько открытых классов, у вас может возникнуть желание высмеять один во время тестирования другого. Это настоящая дискуссия. Является ли Единица (а) всей вашей библиотекой? (б) каждый публичный класс в библиотеке? Или (в) каждый публичный метод в каждом классе? Я предпочитаю тестировать определенную библиотеку как интегрированный компонент, но имитировать или подделывать внешние зависимости (если они не быстрые и надежные). Так что я думаю, что я с тобой.
cdunn2001
1
@PixMach: на самом деле все наоборот. Отсутствие (хороших) модульных тестов тратит много времени, если вам (или кому-то еще) придется изменить этот код в будущем. Если у вас есть опыт поддержки кода с юнит-тестами и без них, вы поймете разницу. Идея состоит в том, что если тестовый модуль не работает, вы должны точно знать, какая часть кода должна быть исправлена. Неудачные крупномасштабные приемочные / интеграционные тесты часто только говорят вам: это не работает. И тогда вы должны начать отладку старой школы ...
Goodsquirrel
@ Goodsquirrel, это зависит от того, что вы называете «единицей». Это проблема. Плохие тесты будут удалены во время рефакторинга. Хорошие тесты все еще будут полезны. Плохие тесты не добавляют никакой ценности и мешают. Хорошие тесты являются самодокументируемыми и высоко ценятся. Давайте определимся. У меня есть частный метод для возврата значения, если другое значение равно True, в противном случае значение по умолчанию. (Устаревший код.) Должен ли этот метод быть проверен? Я говорю нет. Другой закрытый метод возвращает n-е число Фибоначчи. Это должно быть проверено? Я говорю да.
cdunn2001
1
Самый маленький открытый код. Большая разница.
cdunn2001
5

Я объясню вам это на практическом примере и без теоретических вещей:

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

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

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

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

фахад шейх
источник
1
«Разработчик пишет код. Графический интерфейс еще не реализован. Тестирование на этом уровне проверяет, что функции работают правильно и типы данных верны. Этот этап тестирования называется модульным тестированием». Это не так. GUI на самом деле просто «плагин». Вы уже можете написать тесты E2E для вывода API. (или любой объект ответа, который вы генерируете)
user3790897
4

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

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

функциональный тест, проверяющий индивидуальную функциональность приложения, означает функциональное тестирование

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

малини
источник