Интеграционное тестирование - это может быть сделано правильно?

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

То, что я в настоящее время делаю, пишет тестовый сценарий в классе (это - мое эмпирическое правило: "единица" является классом, и каждый класс имеет один или несколько тестовых сценариев). Я пытаюсь разрешить зависимости при помощи насмешек и тупиков, и это работает действительно хорошо, поскольку каждый класс может быть протестирован независимо. После некоторого кодирования тестируются все важные классы. Я затем "соединяю их проводом" вместе использование контейнера МОК. И здесь я застреваю: Как протестировать, если проводное соединение было успешно, и объекты взаимодействуют способ, которым я хочу?

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

Для создания этого простым было бы три класса: Controller, Repository, OutfileWriter. Каждый из них тестируется в изоляции.

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

5
задан Max 19 May 2010 в 14:26
поделиться

6 ответов

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

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

Есть несколько аспектов, почему это так:

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

* Один пример я только что прочитал в книге Люка Хохмана "За пределами архитектуры программного обеспечения": в приложении, которое применяло сильную антипиратскую защиту, создавая и поддерживая "снимок" идентификаторов компонентов HW на реальной машине, разработчики очень хорошо покрыли код модульными тестами. Затем QA удалось завалить приложение за 10 минут, опробовав его на машине без сетевой карты. Как оказалось, поскольку разработчики работали на Mac, они считали само собой разумеющимся, что на машине есть сетевая карта, MAC-адрес которой может быть включен в снимок...

3
ответ дан 14 December 2019 в 08:44
поделиться

IMO, и у меня нет литературы, чтобы поддержать меня по этому поводу, но ключевое различие между нашими различными формами тестирования заключается в объеме,

  • Модульное тестирование - это тестирование отдельных частей функциональности [обычно метод или класс с отслеживанием состояния]
  • Интеграционное тестирование - это тестирование взаимодействия двух или более зависимых частей [обычно службы и потребителя, или даже подключения к базе данных, или подключения к какой-либо другой удаленной службе]
  • Тестирование системной интеграции - это тестирование сквозная система [частный случай интеграционного тестирования]

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

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

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

К сожалению, это означает, что неожиданные сценарии будут возникать в циклах обеспечения качества [QA], Preproduction [PP] и Production [Prod]. На этом этапе ваши попытки воспроизвести эти сценарии в dev должны попасть в ваши пакеты интеграции и системной интеграции в виде автоматизированных тестов.

Надеюсь, это поможет, :)


ps: pet-peeve # 1: менеджеры или разработчики называют тесты интеграции и системной интеграции «модульными тестами» просто потому, что для их автоматизации использовались nUnit или MsTest ...

4
ответ дан 14 December 2019 в 08:44
поделиться

Вы можете просмотреть "Taming the Beast", презентацию Маркуса Клермонта и Джона Томаса об автоматизированном тестировании AJAX-приложений. YouTube Video

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

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

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

0
ответ дан 14 December 2019 в 08:44
поделиться

Что бы я сделал, чтобы проверить "настоящее" приложение: создание http запрос (вручную или автоматически) с некоторыми идентификаторами из базы данных и затем посмотрите в файловой системе, если файл был записан. Конечно это процесс можно автоматизировать, но все же: Разве это не дублирует логику тестирования?

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

Это то, что называется «интеграция test »?

Да, действительно, это так.

0
ответ дан 14 December 2019 в 08:44
поделиться

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

Class OutFilevalidator {
    function isCorrect(fName, dataList) {
       // open file read data and
       // validation logic
}
0
ответ дан 14 December 2019 в 08:44
поделиться

Управление TDD с BDD покрывает большую часть этого за вас. Вы можете использовать Cucumber / SpecFlow с WatiR / WatiN. Для каждой функции у нее есть один или несколько сценариев, и вы работаете над одним сценарием (поведением) за раз, и когда он проходит, вы переходите к следующему сценарию, пока функция не будет завершена.

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

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

0
ответ дан 14 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: