2010-03-06 5 views
13

На работе мы обнаружили, что наш набор тестов дошел до такой степени, что это слишком медленно, чтобы работать многократно, что мне действительно не нравится. Это не менее 5 минут по всему пакету, и более 3 минут - только для объектных тестов данных. Поэтому мне интересно узнать, как люди проводят тестирование.Как вы обрабатываете приложения, которые сильно зависят от баз данных?

На данный момент у нас есть единственный сервер базы данных с живой схемой и схемой _test. Когда тест запускается, он сначала запускает SQL-скрипт, в котором говорится, как заполнять тестовую базу данных (и очищать старые данные, которые могут мешать). Это происходит практически для всех тестов. Из того, что я вижу, это самое большое узкое место в наших тестах - я только что профилировал один тест, и для настройки базы данных требуется около 800 мс, а затем каждый последующий тест проходит около 10 мс.

Я пытался найти какое-то решение, и вот что я нашел до сих пор:

  • Есть тест схема заселена один раз, и откатить изменения в конце каждого теста.

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

  • Mock база данных, где это возможно

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

  • Выполнить ту же систему, но использовать отвалы и RamFs

    Вместо запуска большого запроса SQL мы вместо того, чтобы загрузить дамп базы данных. Тест-сервер будет работать на разделе RAMFS и, надеюсь, принесет некоторые преимущества по скорости.

    Я не могу проверить это, потому что я на OSX, и из того, что я вижу, нет поддержки ramfs.

Есть некоторые другие варианты вокруг, как с помощью SQLite, но это не вариант для нас, как мы зависим от некоторых специфических расширений PostgreSQL.

Halp! :)

+8

«сильно зависимый» всегда является плохим словом, когда дело доходит до тестирования. Сделайте свое приложение не сильно зависимым от вещей, и внезапно становится более надежным * и * легче тестировать.Только уровень абстракции базы данных должен нуждаться в тестировании против реальной базы данных; остальная часть вашего приложения может быть протестирована против слоя поддельной абстракции. – jrockway

ответ

7

В Working Effectively with Legacy Code, Майкл Перья пишет (стр. 10)

Юнит тесты быстро бегать. Если они не работают быстро, это не модульные тесты.

Другие виды тестов часто маскируются как единичные тесты. Тест не является единичным тестом, если:

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

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

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

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

Не откладывайте свои интеграционные тесты и забывайте о них! Автоматизируйте их выполнение и отчетность о результатах. Если вы используете сервер непрерывной интеграции, добавьте еще один проект, который ничего не делает, кроме как периодически запускает тесты.

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

+0

Конечно, я не понимаю эту теорию. Проблема, с которой я столкнулась, сводится к теории на практике. У нас около 20 объектов данных, каждый из которых должен попасть в базу данных. Это само по себе требует добавить достаточно много времени на тестовый прогон (эти объекты данных являются единственным местом, где мы формируем и отправляем SQL-запросы). Я думаю, если бы они попали в базу данных, а все остальное использовало макетные аксесуары данных, мы смотрим на некоторые сбережения. – ocharles

7

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

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

Редактировать

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

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

Отредактируй второй

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

+0

Уверен, но в какой-то момент нам нужно проверить, что внутри взаимодействует с реальной базой данных, и все еще проблема в том, как заставить их быстро работать – ocharles

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