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

Как имитировать БД для тестирования (Java)?

Я программирую на Java, и мои приложения много используют DB. Следовательно, для меня важно, чтобы я мог легко проверить использование БД.
Что такое тесты БД? Для меня они должны предоставить два простых требования:

  • Проверить синтаксис SQL.
  • Что еще более важно, убедитесь, что данные выбраны/обновлены/вставлены правильно, в зависимости от конкретной ситуации.

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

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

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

Я ищу способ имитировать БД, макетную БД, используя файловую систему или просто виртуальную память. Я подумал, что, возможно, есть инструмент/пакет Java, который позволяет просто построить (используя интерфейс кода) DB mock для каждого теста с имитируемыми таблицами и строками с проверкой SQL и с интерфейсом кода для контроля его статуса (а не с использованием SQL).

Вы знакомы с этим инструментом?


Изменить: Спасибо за ответы! Хотя я просил инструмент, вы также предоставили мне несколько советов относительно проблемы:) Мне потребуется некоторое время, чтобы проверить ваши предложения, поэтому я не могу сказать прямо сейчас, не удовлетворяют ли ваши ответы.

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

public class TestDBMonitor extends TestCase {

    @Override
    public void setUp() throws Exception {

       MockConnection connection = new MockConnection();

       this.tableName = "table1";
       MockTable table = new MockTable(tableName);

       String columnName = "column1";
       ColumnType columnType = ColumnType.NUMBER;
       int columnSize = 50;
       MockColumn column = new MockColumn(columnName, columnType, columnSize);
       table.addColumn(column);

       for (int i = 0; i < 20; i++) {
           HashMap<MockColumn, Object> fields = new HashMap<MockColumn, Object>();
           fields.put(column, i);
           table.addRow(fields);
       }

       this.connection = connection;
    }

    @Test
    public void testGatherStatistics() throws Exception {

       DBMonitor monitor = new DBMonitor(connection);
       monitor.gatherStatistics();
       assertEquals(((MockConnection) connection).getNumberOfRows(tableName),
                    monitor.getNumberOfRows(tableName));
    }

    String tableName;
    Connection connection;
}

Надеюсь, этот код достаточно ясен, чтобы понять мою идею (извините за ошибки синтаксиса, я печатал вручную без моего дорогого Eclipse: P).

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

4b9b3361

Ответ 1

новый ответ на старый вопрос (но все немного продвинулось):

Как имитировать БД для тестирования (Java)?

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

иметь личную тестовую БД довольно невозможно. Вы должны использовать "общедоступную" БД, доступную для всех

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

"Эти тесты уверены, что это не быстро..." - тесты БД имеют тенденцию быть медленнее, чем обычные тесты. Это действительно не идеально для проведения медленных тестов.

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

  • Первые рамки DI (например, spring) предлагают способ запускать только часть вашего приложения. если вы пишете свое приложение с хорошим разделением логики db и не-db, тогда в вашем тесте вы можете запустить только часть db
  • У каждого db есть множество настроек, которые делают его менее прочным и намного быстрее. что идеально подходит для тестирования. пример postgres
  • вы также можете поместить весь db в tmpfs

  • Другая полезная стратегия состоит в том, чтобы иметь группы тестов и отключать тесты db по умолчанию (если они действительно замедляют вашу сборку). таким образом, если кто-то действительно работает на db, ему нужно передать дополнительный флаг в строке cmd или использовать IDE (для этого идеально подходят группы тестирования и настраиваемые селектора тестов)

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

'принимает время ", обсуждалось выше. это раздражает? Я видел два пути:

  • подготовьте один набор данных для всех ваших тестовых примеров. то вы должны поддерживать это и рассуждать об этом. обычно он отделен от кода. он имеет килобайты или мегабайты. это большой, чтобы увидеть на одном экране, постигать и рассуждать. он вводит связь между испытаниями. потому что, когда вам нужно больше строк для теста A, ваш count(*) в тесте B не работает. он растет только потому, что даже когда вы удаляете некоторые тесты, вы не знаете, какие строки использовались только одним тестом
  • каждый тест подготавливает данные. таким образом, каждый тест полностью независим, читаем и легко рассуждаем. это раздражает? imo, совсем нет! это позволяет вам быстро писать новые тесты и сэкономить вам много работы в будущем.

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

Умм... на самом деле. основным принципом является проверка того, генерирует ли ваше программное обеспечение желаемый выход в ответ на определенный вход. поэтому, если вы вызываете dao.insert 542 раза, а затем ваш dao.count возвращает 542, это означает, что ваше программное обеспечение работает как указано. если вы хотите, вы можете вызывать кеш фиксации/удаления между ними. Конечно, иногда вы хотите протестировать свою реализацию вместо контракта, а затем проверить, изменилось ли ваше дао состояние db. но вы всегда проверяете sql A, используя sql B (insert vs select, sequence next_val и возвращаемое значение и т.д.). да, у вас всегда будет проблема "кто будет тестировать мои тесты", и ответ таков: никто, поэтому держите их простыми!

другие инструменты, которые могут вам помочь:

  • testcontainers поможет вам обеспечить real db.

  • dbunit - поможет вам очистить данные между тестами

    минусы:

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

    минусы:

    • бесплатно только для небольших проектов
    • очень молодой проект
  • flyway или liquibase - db. они помогут вам легко создать схему и все структуры на вашем локальном db для тестов.

Ответ 2

Java поставляется с Java DB.

Тем не менее, я бы посоветовал не использовать другой тип БД, чем то, что вы используете в производстве, если вы не проходите через слой ORM. В противном случае ваш SQL может быть не такой кросс-платформенной, как вы думаете.

Также проверьте DbUnit

Ответ 3

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

1) Отделите логику и функции доступа к базе данных из общей бизнес-логики и спрячьте ее за интерфейсом. Причина. Чтобы проверить подавляющее большинство логики в системе, лучше использовать фиктивный/заглушку вместо фактической базы данных в качестве ее более простой. Причина 2: значительно быстрее

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

3) Каждому разработчику потребуется отдельная база данных. Им понадобится автоматизированный способ обновления своей структуры на основе изменений со стороны их товарищей по команде и внедрения данных. См. Пункты 4 и 5.

4) Для управления обновлениями в структуре ваших баз данных используйте инструмент http://www.liquibase.org. Причина: дает вам гибкость в способности изменять существующую структуру и двигаться вперед в версиях

5) Для управления данными используйте инструмент http://dbunit.sourceforge.net/. Настройте файлы сценариев (xml или XLS) для конкретных тестовых примеров и базовых данных и очистите только то, что необходимо для любого тестового примера. Причина: намного лучше, чем вручную вставлять и удалять данные Причина 2: проще для тестировщиков понять, как настроить сценарии Причина 3: Быстрее выполнить это

6) Вам нужны функциональные тесты, которые также имеют DBUnit, такие как данные сценария, но это гораздо более обширные наборы данных и выполнение всей системы. Это завершает этап объединения знаний о том, что a) Пробные тесты запускаются, и, следовательно, логика звучит b) То, что тесты интеграции с базой данных выполняются и SQL верны в результате чего "и система в целом работает вместе как сверху вниз"

Эта комбинация хорошо послужила мне до сих пор для достижения высокого качества тестирования и продукта, а также для поддержания скорости unit test развития и ловкости для изменения.

Ответ 4

Я использовал Hypersonic для этой цели. В основном, это JAR файл (чистая Java-база данных), которую вы можете запускать в своей собственной JVM или в вашей собственной JVM, и во время ее работы у вас есть база данных. Затем вы остановите его, и ваша база данных исчезнет. Я использовал его до сих пор - как базу данных в памяти. Это очень просто начать и остановить через Ant при выполнении модульных тестов.

Ответ 5

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

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

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

Ответ 6

Если вы используете Oracle на работе, вы можете использовать функцию Restore Point в Flashback Database, чтобы вернуть базу данных до времени перед вашими испытаниями. Это позволит устранить любые изменения, которые вы лично внесли в БД.

См:

https://docs.oracle.com/cd/E11882_01/backup.112/e10642/flashdb.htm#BRADV71000

Если вам нужна тестовая база данных для использования с производством/обработкой Oracle, тогда найдите XE, экспресс-версию базы данных Oracle. Это бесплатно для личного использования, с лимитом базы данных размером менее 2 гб.

Ответ 7

Недавно мы переключились на JavaDB или Derby, чтобы реализовать это. Derby 10.5.1.1 теперь реализует представление в памяти, поэтому он работает очень быстро, ему не нужно идти на диск: Derby In Memory Primer

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

Ответ 8

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

Мы установили настоящую СУБД на каждую машину для разработчиков и на нашем постоянном сервере интеграции и тестирования (мы используем Hudson). Я не знаю, каковы ограничения вашей рабочей политики, но довольно легко установить и использовать PostgreSQL, MySQL и Oracle XE. Все они бесплатны для использования в целях развития (даже Oracle XE), поэтому нет разумных оснований для запрещения их использования.

Основная проблема заключается в том, как вы гарантируете, что ваши тесты всегда начинаются с базы данных в согласованном состоянии? Если тесты были доступны только для чтения, никаких проблем. Если вы можете создавать мутирующие тесты, чтобы всегда запускать транзакции, которые никогда не выполняются, не проблема. Но, как правило, вам нужно беспокоиться об обратном обновлении. Для этого вы можете экспортировать исходное состояние в файл, а затем импортировать его обратно после теста (команды Oracle exp и imp shell делают это). Или вы можете использовать контрольную точку/откат. Но более элегантным способом является использование такого инструмента, как dbunit, который хорошо работает для нас.

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

Ответ 9

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

Ответ 10

Попробуйте использовать derby. Это просто и удобно. С Hibernate ваше приложение становится гибким. Испытание на дерби, производство на все, что вам нравится и которому доверяют.

Ответ 11

Я думаю, что для такого DB можно использовать схему Acolyte: https://github.com/cchantep/acolyte.

Он позволяет запускать существующую Java (для тестирования) с помощью соединений, которые вы обрабатываете человеком/обработкой обновлений: возвращает соответствующие результаты, количество обновлений или предупреждение в случае выполнения.

Ответ 12

Хорошо, вы используете любой доступ к ORM Layer для доступа к БД?
Если нет: тогда то, что вы думаете, было бы бесполезно. Какое использование тестирования, когда вы не уверены, что SQL, который вы стреляете, будет работать с вашей БД в процессе производства, так как в тестовых случаях вы используете что-то еще.
Если да: тогда вы можете посмотреть на различные варианты.