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

Вот сканарио:

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

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

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

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

Тогда возникает вопрос: что люди делают в таких случаях, чтобы сделать тесты менее хрупкими? Один из вариантов, который я имею в виду, - запустить собственный SQL, который выполняет тот же запрос (поведенчески - он не обязательно должен быть точно таким же, как запрос, сгенерированный спящим режимом), чтобы получить ожидаемое число, а затем запустить версию DAO, чтобы увидеть если совпадает. Таким образом, поведение запроса всегда может быть реализовано в исходном собственном SQL, и у вас всегда будут правильные числа.

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

A.

ОБНОВЛЕНИЕ:

Что касается предложений hsqldb/h2/derby, я знаком с ними, но компания пока не готова пойти по этому пути, и делать это по частям только на одном тестовом примере будет нецелесообразно.

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

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

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

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


person Ashkan Aryan    schedule 21.09.2011    source источник


Ответы (3)


Я согласен с Андреем и Бедвиром, что лучший подход в долгосрочной перспективе — создать базу данных hsqldb специально для тестирования. Если у вас нет возможности сделать это, то ваше решение кажется подходящим. Вы не можете протестировать все, но и не хотите ничего тестировать. Я использовал этот подход несколько раз для тестирования веб-сервисов на базе данных интеграции и т. д. Но помните, что эту базу данных также необходимо поддерживать, если вы добавляете новые столбцы и т. д.

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

Ты говоришь:

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

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

У него есть проблемы, когда он попадает в базу данных? Hibernate, как правило, создает sql, соответствующий заданным вами критериям и диалекту базы данных, поэтому, опять же, любая проблема связана с критериями.

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

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

Итак, в своих тестах я создаю еще одно соединение с базой данных (jdbc) для получения информации. Я выполняю SQL, чтобы получить количество строк и т. д., или проверить, произошла ли вставка.

Я думаю, что ваш подход является вполне верным.

person Matthew Farwell    schedule 21.09.2011
comment
большое спасибо. Да, вы абсолютно правы в своих вопросах относительно проведения тестов на правильном уровне и того, что мы здесь не тестируем спящий режим или его API критериев. Я пытался проиллюстрировать, что простое тестирование того, что критерии созданы определенным образом, было бы бесполезным, и, как вы сказали, нам нужно будет протестировать всю цепочку от критериев до структуры и базы данных. Это именно то, о чем я думал, и ваши комментарии очень помогают в этом! ваше здоровье. - person Ashkan Aryan; 21.09.2011

Одним из подходов может быть использование базы данных в памяти, такой как Apache Derby или HSQLDB и предварительно заполнить ее данными перед началом тестирования с помощью DBUnit.

ОБНОВЛЕНИЕ. Вот хороший статья о подходе.

person Andrey Adamovich    schedule 21.09.2011
comment
Спасибо, я знаком с HyperSQL db, dbunit и liquibase и много раз использовал их в прошлом. Однако это уровень работы, на выполнение которого у меня нет разрешения в настоящее время в рамках небольшого проекта, над которым мы работаем. - person Ashkan Aryan; 21.09.2011
comment
Сделайте это в обеденное время или приходите на час раньше. Установите и запустите его на своей машине, а затем продемонстрируйте своему боссу, желательно с тестом, который выявит недавнюю ошибку. - person blank; 21.09.2011
comment
Настройка hsqldb, создание конфигурации гибернации и добавление методов setUp/tearDown для создания пустой базы данных и направления ваших модульных тестов на это не займет слишком много времени. Единственное, что может занять больше времени, — это создание наборов данных DBUnit. Но вы можете использовать либо некоторые из ваших реальных баз данных для извлечения данных из них с помощью DBUnit, либо использовать какой-либо генератор данных для создания данных. - person Andrey Adamovich; 21.09.2011
comment
@ Андрей Адамович, это не займет много времени, но это большой устаревший проект, и я не уверен, что делать его по частям для новых методов - лучший способ. Но опять же, все, что я буду делать, в любом случае будет только для нового кода, так что можно подумать о том, чтобы сделать это правильно. Я посмотрю, смогу ли я бегать с ним! - person Ashkan Aryan; 21.09.2011
comment
@Ashkan: похоже, вы пытаетесь погасить технический долг, на который начислили довольно много процентов. Поговорите с PO и упомяните ей/ему, что с приложением становится все труднее работать, и небольшие инвестиции в тестовую инфраструктуру окупятся в краткосрочной и долгосрочной перспективе. В краткосрочной перспективе, потому что все, что вы будете производить, потенциально будет более высокого качества и будет содержать меньше ошибок. - person Augusto; 21.09.2011
comment
@Augusto Да, верно. Кодовая база довольно старая (9 лет, если быть точным), но за эти годы она прошла через множество этапов рефакторинга и проверки техническим отделом, а также обновлений платформы и т. д. Я предложил это, и они действительно хотят это сделать, так что это только вопрос времени, прежде чем мы займемся этим. (кстати, я занимался этой кодовой базой меньше месяца или около того ;-)) - person Ashkan Aryan; 21.09.2011

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

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

person blank    schedule 21.09.2011
comment
спасибо смотрите мои комментарии к @Andrey Adamovich ниже. Оба ваших предложения имеют смысл, но я, возможно, не смогу внести это изменение в общую структуру того, как все делается здесь прямо сейчас. - person Ashkan Aryan; 21.09.2011