Подтвердить что ты не робот

Данные базы данных, необходимые для тестирования интеграции; созданных вызовами API или использованием импортированных данных?

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

Основное правило для модульных тестов заключается в том, что они должны быть автономными, и это может быть достигнуто путем изоляции класса из его зависимостей. Существует несколько способов сделать это, и это зависит от того, вводите ли вы свои зависимости с помощью IoC (в мире Java мы имеем Spring, EJB3 и другие фреймворки/платформы, которые предоставляют возможности впрыска) и/или если вы издеваетесь над объектами (для Java у вас JMock и EasyMock), чтобы отделить проверяемый класс от его зависимостей.

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

  • Как минимум в веб-приложениях, состояние часто сохраняется в базе данных. Мы могли бы использовать те же инструменты, что и для модульных тестов для обеспечения независимости от базы данных. Но по моему скромному мнению, я думаю, что бывают случаи, когда не использовать базу данных для тестов интеграции слишком много насмехается (но не стесняйтесь не соглашаться, а не использовать базу данных вообще, когда-либо, также является верным ответом, поскольку это делает вопрос неуместным).
  • Когда вы используете базу данных для тестов интеграции, как вы заполняете эту базу данных данными? Я вижу два подхода:
    • Сохраните содержимое базы данных для теста интеграции и загрузите его перед началом теста. Если он хранится как дамп SQL, вам будет интересно узнать файл базы данных, XML или что-то еще.
    • Создайте необходимые структуры базы данных по вызовам API. Эти вызовы, вероятно, разделены на несколько методов в вашем тестовом коде, и каждый из этих методов может завершиться неудачей. Это можно рассматривать как ваш тест интеграции, имеющий зависимости от других тестов.

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

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

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

4b9b3361

Ответ 1

Я предпочитаю создавать тестовые данные с помощью вызовов API.

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

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

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

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

Еще одна вещь, связанная с интеграцией тестирования базы данных, - это проверка того, что обновление с предыдущей схемы базы данных работает правильно. Для этого вы можете прочитать книгу Рефакторинг баз данных: Эволюционная разработка баз данных или в этой статье: http://martinfowler.com/articles/evodb.html

Ответ 2

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

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

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

Ответ 3

Почему эти два подхода определяются как исключительно?

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

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

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

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

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

Ответ 4

Обычно я использую SQL-скрипты для заполнения данных в обсуждаемом вами сценарии.

Это прямолинейно и очень легко повторяемо.

Ответ 5

Я делаю оба, в зависимости от того, что мне нужно проверить:

  • Я импортирую статические тестовые данные из сценариев SQL или дампов БД. Эти данные используются при загрузке объектов (десериализация или сопоставление объектов) и в тестах SQL-запросов (когда я хочу знать, вернет ли код правильный результат).

    Кроме того, у меня обычно есть некоторые базовые данные (config, value to name lookup tables и т.д.). Они также загружаются на этом этапе. Обратите внимание, что эта загрузка представляет собой один тест (наряду с созданием БД с нуля).

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

Конечно, есть исключения из правила:

  • Я также создаю большое количество строк в тестах производительности.
  • Иногда мне приходится фиксировать результат unit test (иначе тест будет слишком большим).

Ответ 6

Я использовал DBUnit, чтобы делать снимки записей в базе данных и хранить их в формате XML. Затем мои модульные тесты (мы назвали их интеграционными тестами, когда им нужна база данных), можно стереть и восстановить из файла XML в начале каждого теста.

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

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

Очевидно, что эти тесты были медленнее, чем чистые модульные тесты.

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

Ответ 7

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

По возможности я предпочитаю использовать фактическую базу данных. Часто запросы (написанные на языке SQL, HQL и т.д.) В классах CRUD могут возвращать неожиданные результаты при столкновении с реальной базой данных. Лучше сбросить эти проблемы на ранней стадии. Часто разработчики пишут очень тонкие модульные тесты для CRUD; испытывая только самые доброкачественные случаи. Использование фактической базы данных для вашего тестирования может протестировать всевозможные угловые случаи, о которых вы, возможно, даже не знали.

Считая, что могут быть другие проблемы. После каждого теста вы хотите вернуть свою базу данных в известное состояние. Это моя текущая работа, которую мы используем в базе данных, выполняя все инструкции DROP, а затем полностью воссоздавая все таблицы с нуля. Это очень медленный процесс в Oracle, но может быть очень быстрым, если вы используете базу данных памяти, такую ​​как HSQLDB. Когда нам нужно очистить определенные проблемы Oracle, мы просто изменим URL-адрес базы данных и свойства драйвера, а затем запустим Oracle. Если у вас нет такой возможности переносимости базы данных, тогда у Oracle также есть какая-то функция моментального снимка базы данных, которая может быть использована специально для этой цели; откат всей базы данных до некоторого предыдущего состояния. Я уверен, что другие базы данных.

В зависимости от того, какие данные будут в вашей базе данных, API или подход загрузки могут работать лучше или хуже. Когда у вас есть структурированные данные со многими отношениями, API-интерфейсы сделают вашу жизнь более легкой, чтобы я сделал отношения между вашими данными ясными. Вам будет сложнее сделать ошибку при создании набора тестовых данных. Как упоминалось другими плакатами, инструменты рефакторинга могут позаботиться о некоторых изменениях в структуре ваших данных автоматически. Часто я считаю полезным придумать тестовые данные, сгенерированные API, как составляющие сценарий; когда пользователь/система выполнил шаги X, Y Z, а затем тесты пройдут оттуда. Эти состояния могут быть достигнуты, потому что вы можете написать программу, которая вызывает тот же API, который будет использовать ваш пользователь.

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

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

Ответ 8

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

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

Причиной для этого во внешней программе было: 1. Я мог бы повторно запустить тесты с помощью тестовых измененных данных, то есть убедиться, что мои тесты прошли несколько раз, а изменения данных, сделанные в результате испытаний, были действительными. 2. Я мог бы при необходимости очистить БД и начать новый старт.

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