Как смоделировать БД для тестирования (Java)? - PullRequest
62 голосов
/ 30 мая 2009

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

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

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

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

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

Я ищу способ имитации БД, фиктивной БД, используя файловую систему или просто виртуальную память. Я подумал, что, возможно, есть инструмент / пакет Java, который позволяет просто создать (используя интерфейс кода) макет БД для каждого теста, с имитированными таблицами и строками, с проверкой 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-запросы довольно просты и не должны отличаться от одной платформы к другой.

Ответы [ 14 ]

40 голосов
/ 30 мая 2009

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

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

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

14 голосов
/ 14 сентября 2017

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

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

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

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

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

«Эти тесты, конечно, не быстрые» - тесты БД, как правило, медленнее, чем обычные тесты. Медленные тесты не идеальны.

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

  • Первые DI-фреймворки (например, Spring) предлагают способ запуска только некоторой части вашего приложения. если вы пишете свое приложение с хорошим разделением логики, связанной с БД и без БД, то в своем тесте вы можете запустить только часть БД
  • каждый дБ имеет множество опций настройки, что делает его менее долговечным и намного быстрее. это идеально подходит для тестирования. пример postgres
  • вы также можете поместить всю базу данных в tmpfs

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

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

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

  • подготовить один набор данных для всех тестовых случаев. тогда вы должны поддерживать это и рассуждать об этом. обычно это отделено от кода. у него есть килобайты или мегабайты. это очень важно видеть на одном экране, понимать и рассуждать. это вводит связь между тестами. потому что, когда вам нужно больше строк для теста А, ваш count(*) в тесте Б дает сбой. он только растет, потому что даже когда вы удаляете некоторые тесты, вы не знаете, какие строки использовались только этим тестом
  • каждый тест готовит свои данные. Таким образом, каждый тест является полностью независимым, читаемым и легко рассуждаемым. это раздражает? ИМХО, совсем нет! это позволяет очень быстро писать новые тесты и в будущем сэкономит вам массу работы

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

хм ... не совсем. Основной принцип - проверить, генерирует ли ваше программное обеспечение желаемый результат в ответ на конкретный вход. так что если вы звоните dao.insert 542 раза, а затем ваш dao.count возвращает 542, это означает, что ваше программное обеспечение работает, как указано. если вы хотите, вы можете вызвать commit / drop кеш между ними. Конечно, иногда вы хотите протестировать свою реализацию вместо контракта, а затем проверить, изменил ли ваш дао состояние базы данных. но вы всегда тестируете sql A, используя sql B (вставка против выбора, последовательность next_val против возвращенного значения и т. д.). да, у вас всегда будет проблема «кто будет тестировать мои тесты», и ответ таков: никто, так что будьте проще!

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

  1. testcontainers поможет вам предоставить реальный дБ.

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

    минусов:

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

    минусы:

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

10 голосов
/ 30 мая 2009

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

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

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

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

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

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

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

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

10 голосов
/ 30 мая 2009

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

6 голосов
/ 30 мая 2009

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

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

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

4 голосов
/ 30 мая 2009

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

См:

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

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

3 голосов
/ 30 мая 2009

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

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

1 голос
/ 02 апреля 2018

Вы можете HSQLDB для тестирования в памяти дБ. Запустить базу данных в памяти и запустить на ней тесты довольно просто.
http://hsqldb.org/

1 голос
/ 31 октября 2013

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

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

1 голос
/ 11 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...