Как создать единичные тесты с неинформационной базой данных, такими как MySQL в платформе Play, с сбросом в известное состояние?

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

Тестирование по базе данных в базе данных H2

Документация по платформе приложений предлагает запустить модульные тесты для базы данных H2 в памяти, даже если основная база данных, используемая для разработки и производства, использует другое программное обеспечение (то есть MySQL):

app = Helpers.fakeApplication(Helpers.inMemoryDatabase());

Мое приложение не использует сложные функции RDBMS, такие как хранимые процедуры, и большинство случаев доступа к базе данных - это вызовы ebean, поэтому они должны быть совместимы как с MySQL, так и с H2.

Однако в операциях создания таблиц в эволюции используются специфичные для MySQL функции, такие как указание ENGINE = InnoDB , DEFAULT CHARACTER SET = utf8 и т. Д. Я боюсь, что удалю эти проприетарные части CREATE TABLE , MySQL будет использовать некоторые настройки по умолчанию, которые я не могу контролировать, и которые зависят от версии, поэтому для тестирования и разработки приложения основная конфигурация MySQL должна быть изменена.

Кто-нибудь использовал этот подход (делая эволюции совместимыми с MySQL и H2)?

Другие идеи, как это можно решить:

  • Отдельные эволюции для MySQL и H2 (не очень хорошая идея)
  • Какой-то способ заставить H2 игнорировать дополнительные файлы MySQL в create table (режим совместимости MySQL не работает, он по-прежнему жалуется даже на набор символов по умолчанию ). Я не знаю, как.

Тестирование на том же драйвере базы данных, что и основная база данных

Единственным преимуществом базы данных с внутренней памятью H2 является то, что она быстрая, и тестирование на одном и том же драйвере базы данных, чем база данных dev/production, может быть лучше, потому что она ближе к реальной среде.

Как это можно сделать прямо в Play Framework?

Пытался:

Map settings = new HashMap();
settings.put("db.default.url", "jdbc:mysql://localhost/sometestdatabase");
settings.put("db.default.jndiName", "DefaultDS");
app = Helpers.fakeApplication(settings);

Похоже, что эволюция работает здесь, но как лучше всего очистить базу данных перед каждым тестом? Создавая собственный код, который обрезает каждую таблицу? Если это приведет к отбрасыванию таблиц, то будут ли изменения выполняться снова перед следующим тестом или они будут применены один раз для команды play test ? Или один раз за вызов Helpers.fakeApplication() ?

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

23
Вы с этим справились?
добавлено автор uthomas, источник

5 ответы

Во-первых, я бы рекомендовал использовать ту же СУБД для тестирования и производства, поскольку это могло бы избежать некоторых труднодоступных ошибок.

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

Использование DdlGenerator может быть выполнено следующим образом:

    EbeanServer server = Ebean.getServer(serverName);
    ServerConfig config = new ServerConfig();
    DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);

Этот код можно поместить в базовый класс, который вы могли бы наследовать ваши тесты (или внутри пользовательского Runner ), который вы можете использовать с аннотацией @RunWith ).

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

Некоторые ссылки, которые могут быть полезны:

8
добавлено
@mguillermin Не могли бы вы увидеть этот вопрос? stackoverflow.com/questions/20623040/…
добавлено автор pmichna, источник
@pmichna Я ответил на ваш вопрос.
добавлено автор mguillermin, источник
Сделайте ваш код , используя ту же базу данных, что и база данных основных приложений для запуска тестов, или что-то в application.conf тесты автоматически используют отдельную базу данных?
добавлено автор kolen, источник
@mguillermin, могу ли я использовать внешние базы данных в проекте реальной игры? Потому что я слышал, что 2.0 не поддерживает, кроме H2.
добавлено автор Kyle Luke, источник

Я использовал тот же движок базы данных, что и основная база данных, и dbunit для очистки перед каждым тестом.

public class SomeTest {
   //...

    @Before
    public void startApp() throws Exception {
       //Set up connection to test database, different from main database. Config better should be used instead of hard-coding.
        Map settings = new HashMap();
        settings.put("db.default.url", "jdbc:mysql://localhost/somedatabase?characterEncoding=UTF-8&useOldAliasMetadataBehavior=true");
        settings.put("db.default.user", "root");
        settings.put("db.default.password", "root");
        settings.put("db.default.jndiName", "DefaultDS");//make connection available to dbunit through JNDI
        app = Helpers.fakeApplication(settings);
        Helpers.start(app);

        databaseTester = new JndiDatabaseTester("DefaultDS");

        IDataSet initialDataSet = new FlatXmlDataSetBuilder().build(play.Play.application()
                .resourceAsStream("/resources/dataset.xml"));
        databaseTester.setDataSet(initialDataSet);
        databaseTester.onSetup();
    }

    @After
    public void stopApp() throws Exception {
        databaseTester.onTearDown();
        Helpers.stop(app);
    }
}

Мой dataset.xml просто содержит имена таблиц, чтобы сообщить dbunit о пустых таблицах перед каждым тестом. Он также может содержать светильники.

<?xml version="1.0" encoding="UTF-8"?>

  
  

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

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

Я не использую Helpers.running , потому что он использует Runnable и Runnable не может генерировать исключения - очень неудобно для тестов. Но если вы посмотрите код для running() , он просто вызывает Helpers.start() и Helpers.stop() , поэтому я называю эти методы непосредственно в @Before и @After .

Решил не использовать H2 для запуска тестов: да, он работает быстрее, но между ним и MySQL существует слишком большая разница.

5
добавлено

You can also using DB mock, if goal is to validate both your Slick|JPA|Anorm mappings & functions based on.

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

Вы можете взглянуть на Acolyte (acolyte.eu.org), который используется в спецификациях самого Анорма (например, ).

Кто-нибудь использовал этот подход (делая эволюции совместимыми с MySQL и H2)?

I have found an answer for the MySQL specific features: How can I unit test for MySQL database with Play 2.x?

1
добавлено

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

    @Test
public void testDataBase() {
    final HashMap postgres = new HashMap();
    postgres.put("db.default.driver","org.postgresql.Driver");
    postgres.put("db.default.url","jdbc:postgresql://localhost/myDataBase");
    postgres.put("db.default.user", "postgres");
    postgres.put("db.default.password", "password");

    running(fakeApplication(postgres), new Runnable() {

        @Override
        public void run() {

            //Insert Assertions Here
        }
    });
}
1
добавлено
QA — вакансии и аналитика рынка вакансий
QA — вакансии и аналитика рынка вакансий
5 668 участник(ов)

Вакансии и поиск работы в сфере QA. Вопросы: @qa_ru Про деньги: @qa_fin При размещении вакансии указывать: - должность - компанию - требования к кандидату - условия и ЗП хэштеги: #город #типзанятости

QA — русскоговорящее сообщество
QA — русскоговорящее сообщество
3 625 участник(ов)

Общаемся про все виды тестирования и его автоматизацию. Без мата, грубостей и провокаций. События: @qaevents Вакансии: @qa_jobs Автоматизаторы: @qa_automation Слухи про компании: @qa_bad_company

QA juniors
QA juniors
2 720 участник(ов)

Добро пожаловать в чат джуниоров QA! Общаемся обо всём, что связано с тестированием и не только :) В чате царит дружественная атмосфера, поэтому общаемся без мата, грубостей. @qa_automation - автоматизация @serious_tester - для тестировщиков и QA

QA - Bad Company!
QA - Bad Company!
2 602 участник(ов)

Позитив и негатив про компании или курсы, куда не стоит идти работать или учиться, а куда стоит. За пиратский контент - бан. @qa_fin о деньгах Русскоговорящее сообщество: @qa_ru Флудилка: @qaFlood Вакансии: @qa_jobs Финансы: @qa_fin

QA — Автоматизация
QA — Автоматизация
2 434 участник(ов)

1. Обсуждение технологий автоматизированного тестирования 2. Помощь начинающим Ru-сообщество: @qa_ru Джуночат: @qajuniors Вакансии: @qa_jobs Финансы: @qa_fin Митапы и события: @qaevents Паблики: @serious_tester, @automation_remarks, @atinfo

QA - Finance
QA - Finance
1 347 участник(ов)

Чат о деньгах тестировщиков. ЗП, релокейты,оферы. @qa_bad_company - обсуждение компаний/курсов и карьерного роста для QA @qa_automation - авто QA Холивары, политика, религия-бан Реклама, спам, оскорбления - бан Для флуда используйте другой чат

dbGeeks
dbGeeks
545 участник(ов)

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

Разработка СУБД
Разработка СУБД
143 участник(ов)