В чем разница между интеграцией и юнит-тестами?
===============================================

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

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

 По сути, эти тесты стали интеграционными, потому что теперь они тестируют интеграцию этих двух классов, или это просто модульный тест, охватывающий 2 класса?

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

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

Редактироват Спасибо за все отличные ответы всем! Я думаю, что из разных ответов ясно, что грань между юнит-тестами и интеграционными тестами определенно размыта, и, возможно, немного педантично пытаться выяснить, какие из них и на чем стоит сосредоточиться (спасибо @Rob Cooper ). Кроме того, извините, но я не собираюсь принимать какой-либо ответ, потому что слишком многие слишком хороши, и это действительно кажется весьма субъективным.

 

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

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

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

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

 Это не важно.

 Тестирование важно, F.I.R.S.T важно, расщепление определений - пустая трата времени, которое только вводит новичков в тестирование.



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



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

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

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



 которые тестирует белый ящик класса. Любые зависимости, которые требуются классу, заменяются на поддельные (mocks).

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

 Я бы не назвал интеграционные тесты Контроллера, если только одна из их зависимостей не является реальной (то есть не фиктивной) (например, IFormsAuthentication).

 Разделение двух типов тестов полезно для тестирования системы на разных уровнях. Кроме того, интеграционные тесты, как правило, долговечны, а модульные тесты должны быть быстрыми. Различие в скорости выполнения означает, что они выполняются по-разному. В наших процессах разработки модульные тесты запускаются при регистрации (это хорошо, потому что они очень быстрые), а интеграционные тесты запускаются один / два раза в день. Я стараюсь запускать интеграционные тесты как можно чаще, но, как правило, попадание в базу данных / запись в файлы / замедление работы rpc's / etc.

 Это поднимает еще один важный момент: модульные тесты должны избегать ударов ввода-вывода (например, диск, сеть, дБ). В противном случае они сильно замедляются. Требуется немного усилий, чтобы спроектировать эти зависимости ввода-вывода - я не могу признать, что я был верен правилу «модульные тесты должны быть быстрыми», но если да, то преимущества гораздо большей системы становятся очевидными очень быстро .



 его черно-белый. Ответственность более 1, это интеграционный тест.

 По тесту на утку (выглядит, крякает, вяло, это утка), это всего лишь модульный тест с более чем одним новым объектом.

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



**Unit тесты используют макеты**

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



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



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

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



   
есты @Unit: доступ к базе данных является поддельным. Методы кода проверяются.



 

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

 **Интеграционные тесты** - это следующий шаг: он взял один или несколько компонентов и убедился, что они работают вместе, как и должнка компоненты работают индивидуально, но когда вы вводите HTML в свой HtmlEditControl, он каким-то волшебным образом знает, действителен он или нет ..

 Хотя это действительно подвижная строка ... Я бы лучше сосредоточился на том, чтобы заставить этот чертов код работать на полную остановку ^ \_ ^



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

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

 Технически вы все равно не можете пройти модульный тест только на один класс. Что если ваш класс состоит из нескольких других классов? Это автоматически делает это интеграционным тестом? Я так не думаю.



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

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



[Unit Testing](https://en.wikipedia.org/wiki/Unit_testing) - это метод тестирования, который проверяет правильность работы отдельных блоков исходного кода.

 [Интеграционное тестирование](https://en.wikipedia.org/wiki/Integration_testing) - это фаза тестирования программного обеспечения, при которой отдельные программные модули объединяются и тестируются как группа.

 [Wikipedia](https://en.wikipedia.org/wiki/Unit_testing) определяет единицу как наименьшую тестируемую часть приложения, которая в Java / C # является методом. Но в вашем примере с классами Word и Sentence я, вероятно, просто напишу тесты для предложения, так как, скорее всего, излишне использовать  [Издеваться](https://en.wikipedia.org/wiki/Mock_object) word class для проверки класса предложений. Таким образом, предложение будет моей единицей, а слово - деталью реализации этой единицы.



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

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

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



 если хотите. Обычно выполняется одним разработчиком.

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

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



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

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

 Все это говорит вам, работает ли общая часть. Если это не удается: он не говорит вам точно, где это происходит.

 Единичные тесты Это действительно специфические типы тестов. Они говорят вам, работает ли одна конкретная вещь или нет. Ключ к этому типу тестов в том, что он тестирует только одну конкретную вещь, предполагая, что все остальное работает просто отлично. Это ключевой момент.

Пример Давайте уточним этот момент на примере:

 В качестве примера возьмем машину. **Интеграция** тест для автомобиля: например, машина едет в Woop Woop и обратно? Если это произойдет, вы можете с уверенностью сказать, что автомобиль работает с общей точки зрения. Это интеграционный тест. Если он выходит из строя, вы не представляете, где он на самом деле выходит из строя: это радиатор, трансмиссия, двигатель или карбюратор? Ты понятия не имеешь. Это может быть что угодно.**Модульный тес** для автомобиля: двигатель работает? Это тестирование предполагает, что все остальное в машине работает просто отлично. Таким образом, если этот конкретный модульный тест не пройден: вы можете быть уверены, что проблема заключается в двигателе, поэтому вы можете быстро изолировать и устранить проблему. Использование заглушек Предположим, что ваш автомобильный интеграционный тест не пройден. Он не едет успешно в Эчуку. В чем проблема

 Теперь давайте предположим, что в вашем двигателе используется специальная система впрыска топлива и что этот тест двигателя также не прошел. Другими словами, как тест на интеграцию, так и тест двигателя не прошли. Где тогда проблема? (Дайте себе 10 секунд, чтобы получить ответ.)

 Проблема с двигателем или системой впрыска топлива?

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



 эти тесты стали интеграционными, потому что теперь они тестируют интеграцию этих двух классов? Или это всего лишь модульный тест, охватывающий 2 класс

 Думаю, да и да. Ваш юнит-тест, охватывающий 2 класса, стал интеграционным тестом.

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

 Пример реальной разницы может быть следующим: 1) Массив из 1 000 000 элементов легко тестируется модулем и работает нормально. 2) BubbleSort легко тестируется модулем на фиктивном массиве из 10 элементов, а также отлично работает. 3) Интеграционное тестирование показывает, что что-то не так хорошо.

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



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

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

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

 Скажем, у вас есть метод где-то вроде этого:

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

 Нет сомнений: если тест пройден, вы можете утверждать, что поставляете работающую функцию. Это то, что вы можете назвать Business Value.

 Если вы хотите написать модульный тест для`DoSomething` Вы должны притвориться (используя некоторые макеты), что остальные классы и методы работают (то есть, что все зависимости, которые использует метод, работают правильно) и утверждать, что ваш метод работает.

 На практике вы делаете что-то вроде:

 Вы можете сделать это с помощью Dependency Injection, с помощью некоторого Factory Method или любой Mock Framework или просто путем расширения тестируемого класса.

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

 Функция не будет работать, потому что`Log` сломан, не потому что`[Do your job with someInput]` не выполняет свою работу. И кстати,`[Do your job with someInput]` несет полную ответственность за этот метод.

 Также предположим, что`Log` используется в 100 других функциях, в 100 других методах 100 других классов.

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

 Это очень полезная информация: я знаю, что у меня сломан продукт. Это также очень запутанная информация: она ничего не говорит мне о том, где проблема. Он сообщает мне симптом, а не основную причину.

Еще,`DoSomething`одульный тест @ зеленый, потому что он использует фальшивку`Log`, построенный, чтобы никогда не ломаться. И да: это явно ложь. Это сообщение сломанной функции работает. Чем это может быть полезно?

(Если`DoSomething()`одульный тест @ не пройден, убедитесь:`[Do your job with someInput]` есть ошибки.)

 Предположим, это система со сломанным классом:![]()

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

![]()

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

![]()

 Теперь сравните два сценария.

 Та же ошибка сломает только один юнит-тест.

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

Различи Интеграционные тесты говорятчт не работает. Но они бесполезны в догадываюсь где проблема может быть.

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

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

 Этот ответ в основном является кратким изложением того, что я написал здесь: [Единые тесты лгут, поэтому я люблю их](https://arialdomartini.wordpress.com/2011/10/21/unit-tests-lie-thats-why-i-love-them/).



Природа твоих тестов **модульный тес** модуля X - это тест, который ожидает (и проверяет) проблемы только в модуле X.

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

 Подумайте о характере ваших тестов в следующих терминах:

**Сокращение риско**: Для этого и нужны тесты. Только комбинация юнит-тестов и интеграционных тестов может дать вам полное снижение риска, потому что, с одной стороны, модульные тесты по своей сути могут не проверять правильное взаимодействие между модулями, а с другой стороны, интеграционные тесты могут использовать функциональность нетривиального модуля лишь в небольшой степени. **Попытка написания текста**: Интеграционные тесты могут сэкономить усилия, так как вам может не понадобиться писать заглушки / подделки / mocks. Но модульные тесты также могут сэкономить усилия, когда реализовать (и поддерживать!) Эти заглушки / фальшивки / mocks оказывается проще, чем конфигурировать настройку теста без них. **Задержка выполнения теста**: Интеграционные тесты, включающие в себя тяжелые операции (такие как доступ к внешним системам, таким как БД или удаленные серверы), как правило, медленные (er). Это означает, что модульные тесты могут выполняться гораздо чаще, что сокращает усилия по отладке в случае неудачи, потому что вы лучше представляете, что вы изменили за это время. Это становится особенно важным, если вы используете разработку через тестирование (TDD). **Отладочные усилия**: Если интеграционный тест не пройден, но ни один из модульных тестов не сработал, это может быть очень неудобно, поскольку в нем задействовано так много кода, чтоможе содержать проблему. Это не большая проблема, если вы ранее изменили только несколько строк, но поскольку интеграционные тесты выполняются медленно, возможно, вы сделалин запускай их в такие короткие промежутки времени ... Помните, что интеграционный тест все еще может быть заглушен / подделан / издеватьсянескольк его зависимостей. Это обеспечивает достаточное промежуточное положение между юнит-тестами и системными тестами (наиболее комплексные интеграционные тесты, тестирование всей системы).

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