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



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



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



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




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


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


    • сохраните содержимое базы данных для интеграционного теста и загрузите его перед началом теста. Если он хранится как дамп SQL, файл базы данных, XML или что-то еще было бы интересно узнать.

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




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



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



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

637   8  

8 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

это прямо вперед и очень легко повторяется.

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

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

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

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

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

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

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

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

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

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

Comments

    Ничего не найдено.