Как записать модульные тесты на вызовы базы данных

Spike PHPCoverage . И SimpleTest и PHPUnit может легко быть интегрирован с ним, хотя поддержка PHPUnits там out-of-the-box.

63
задан kdmurray 16 January 2013 в 08:02
поделиться

8 ответов

Что вы тестируете?

Я не понимаю, что есть три возможности:

A. Вы тестируете класс DAO (объект доступа к данным), убеждаясь, что он правильно маршалирует значения / параметры, передаваемые в базу данных, и правильно маршалирует / трансформирует / упаковывает результаты, полученные из базы данных.

В этом случае вы вообще не нужно подключаться к базе данных; вам просто нужен модульный тест, который заменяет базу данных (или промежуточный уровень, например, JDBC, (N) Hibernate, iBatis) на макет.

B. Вы проверяете синтаксическую правильность (сгенерированного) SQL.

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

C. Вы проверяете семантическую правильность вашего SQL, т. Е. То, что для данного базового набора данных ваши операции (доступ / выбор и мутации / вставки и обновления) производят ожидаемый новый набор данных.

Для этого , вы хотите использовать что-то вроде dbunit (который позволяет вам настроить базовый уровень и сравнить набор результатов с ожидаемым набором результатов) или, возможно, полностью провести тестирование в базе данных, используя метод, который я описываю здесь: Best способ тестирования SQL-запросов .

47
ответ дан 24 November 2019 в 16:23
поделиться

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

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

2
ответ дан 24 November 2019 в 16:23
поделиться

Весь смысл модульного теста состоит в том, чтобы протестировать модуль (да) изолированно. Весь смысл вызова базы данных состоит в том, чтобы интегрировать с другим устройством (базой данных). Ergo: нет смысла выполнять вызовы базы данных для модульного тестирования.

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

10
ответ дан 24 November 2019 в 16:23
поделиться

Вы можете выполнить модульное тестирование всего, кроме: queryDA.Fill (resultSet);

Как только вы выполните queryDA.Fill (resultSet) , вы либо вам придется имитировать / подделать базу данных, или вы проводите интеграционное тестирование.

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

Если бы я проводил модульное тестирование этого кода, я бы проверял правильность построения параметров, создает ли построитель команд нужное количество параметров? Все ли они имеют ценность? Правильно ли обрабатываются значения NULL, пустые строки и DbNull?

Фактически заполнение набора данных - это проверка вашей базы данных, который является ненадежным компонентом, выходящим за рамки вашего DAL.

4
ответ дан 24 November 2019 в 16:23
поделиться

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

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

28
ответ дан 24 November 2019 в 16:23
поделиться

Строго говоря, тест, который выполняет запись / чтение из базы данных или файловой системы, не является модульным тестом. (Хотя это может быть интеграционный тест, и он может быть написан с использованием NUnit или JUnit). Юнит-тесты предназначены для тестирования операций одного класса, изолируя его зависимости. Итак, когда вы пишете модульный тест для уровней интерфейса и бизнес-логики, вам вообще не нужна база данных.

Хорошо, но как вы проводите модульное тестирование уровня доступа к базе данных? Мне нравится совет из этой книги: Тестовые шаблоны xUnit (ссылка указывает на главу книги «Тестирование с БД». Ключи следующие:

  • используйте тесты туда и обратно
  • не напишите слишком много тестов в своем приспособлении для тестирования доступа к данным, потому что они будут работать намного медленнее, чем ваши «настоящие» модульные тесты
  • , если вы можете избежать тестирования с реальной базой данных, тест без базы данных
4
ответ дан 24 November 2019 в 16:23
поделиться

Из любви к Богу, не проверяйте действующую, уже заполненную базу данных. Но вы знали это.

В общем, вы уже имеете представление о том, какие данные будет извлекать каждый запрос, аутентифицируете ли вы пользователей, просматриваете ли вы записи в телефонной книге / организационной диаграмме или что-то еще. Вы знаете, какие поля вас интересуют, и вы знаете, какие ограничения существуют для них (например, UNIQUE , NOT NULL и т. Д.). Вы модульно тестируете свой код, который взаимодействует с базой данных, а не с самой базой данных, поэтому подумайте о том, как тестировать эти функции. Если возможно, чтобы поле было NULL , у вас должен быть тест, который проверяет, правильно ли ваш код обрабатывает значения NULL . Если одно из ваших полей является строкой ( CHAR , VARCHAR , TEXT и c), проверьте правильность обработки экранированных символов.

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

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

6
ответ дан 24 November 2019 в 16:23
поделиться

Для того, чтобы сделать это правильно, вам следует использовать некоторую инъекцию зависимостей (DI), а для .NET их несколько. В настоящее время я использую Unity Framework, но есть и другие, более простые.

Вот одна ссылка с этого сайта по этой теме, но есть и другие: Внедрение зависимостей в .NET с примерами?

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

Поскольку вы спрашивали о передовых методах, это будет один, IMO.

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

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

Изменить: Под модульным тестом базы данных я имею в виду это http://msdn.microsoft.com/en-us/library/aa833233%28VS.80%29.aspx

1
ответ дан 24 November 2019 в 16:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: