2009-05-30 3 views
44

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

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

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

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

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

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

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


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

В любом случае, вот лучшее представление о том, что я ищу - Представьте себе класс с именем 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; 
} 

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

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

ответ

2

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

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

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

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

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

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

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

  • Первые каркасы DI (например, весна) предлагают способ запускать только часть вашего приложения. если вы напишете свое приложение с хорошим разделением логики db и не-db, то в вашем тесте вы можете start only the db part
  • У каждого db есть множество настроек, которые делают его менее прочным и намного быстрее. это идеально подходит для тестирования. postgres example
  • вы также можете поместить всю БД в TMPFS

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

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

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

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

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

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

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

  1. testcontainers поможет вам обеспечить реальную дб.

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

    минусы:

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

    минусы:

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

+0

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

7

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

38

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

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

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

+4

+1 для предупреждения об использовании другого SQL-диалекта – Thilo

+0

Это хороший совет. –

+0

+1 для DbUnit - просто отличный инструмент –

0

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

1

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

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

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

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

3

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

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

4

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

См:

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

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

+0

проголосовать, потому что ссылка мертва, если вы ее исправите, я могу изменить свой голос :) –

+1

Ссылка была обновлена ​​и работает. – Martlark

+0

vote changed :) –

10

Существует множество точек зрения о том, как тестировать точки интеграции, такие как соединение с базой данных через 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 корректно , приводящие к ", и система в целом работает вместе как сверху вниз «

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

5

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

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

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

1

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

1

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

1

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

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

Смежные вопросы