Является ли модульное тестирование вашего SQL слишком сложным? - PullRequest
24 голосов
/ 08 апреля 2009

На www.sqlservercentral.com есть статья о модульном тестировании вашего SQL.

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

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

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

Ответы [ 12 ]

23 голосов
/ 08 апреля 2009

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

В нескольких случаях я бы предложил протестировать базу данных:

  • Таблицы и представления. Проверьте таблицы и представления, которые, как вы ожидаете, существуют. Убедитесь, что эти таблицы и представления содержат ожидаемые столбцы. Вы также можете проверить, что таблицы, представления или столбцы, которые вы пропустили на этом этапе, на самом деле отсутствуют.

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

  • Триггеры: те же, что и для ограничений, а также триггеры могут использоваться для каскадных эффектов или для преобразования значений и т. Д. Проверьте эти логические пути.

  • Хранимые процедуры: я поддерживаю предостережение против размещения слишком большого количества логики в базе данных, когда логика легче разрабатывается, отлаживается и поддерживается на уровне приложений. Но есть случаи, когда есть веские причины использовать хранимые процедуры. Часто вы видите узкое место в производительности, решая сложную логику в базе данных. Таким образом, хранимые процедуры не исчезают полностью, и их тестирование - хорошая идея.

  • Данные начальной загрузки: таблицы поиска - это пример данных, которые должны присутствовать даже в «пустой» базе данных. Могут быть и другие примеры. Проверьте, что база данных содержит необходимые данные.

  • Запросы. Код вашего приложения содержит запросы SQL. Проверьте их на предмет работоспособности, а также на производительность. Особенно производительность - потому что один и тот же запрос может работать хорошо в один день и стать узким местом на следующий день, так как объем данных изменяется, индексы растут несбалансированными и т. Д.

  • Классы ORM: Как триггеры, классы ORM в вашем приложении могут содержать логику для проверки, преобразования или мониторинга операций базы данных. Они должны быть проверены.

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

12 голосов
/ 08 апреля 2009

Ваш SQL содержит логику. Например, логическое условие проверяет условие WHERE. Можете ли вы придумать, каким образом SQL может быть неправильным? Если да, то имеет ли смысл тестировать SQL, чтобы убедиться, что этих ошибок нет?

(Например, какой-нибудь глупый программист, такой как я, мог случайно напечатать «WHILE» вместо «WHERE» в моем комментарии выше! ... как я. Но позже я это исправил. Так где же мои тесты stackoverflow? !?; -)

10 голосов
/ 08 апреля 2009

Я согласен с System Architect, в наши дни слишком много бизнес-логики проникает в базы данных.

5 голосов
/ 08 апреля 2009

Различают модульные тесты / specs и интеграционные тесты / specs.

Если в ваших классах есть и то, и другое, то вы нарушаете здравый принцип: Разделение проблем .

Ваши тесты должны быть четко определены между модульными тестами для тестирования постоянных невежественных модулей POCO / POJO, таких как объекты, сервисы и интеграционные тесты. Которые для тестирования, где ваше приложение попадает в металл.

Интеграционные тесты должны проверять персистентность, такую ​​как репозитории и единицы реализации для вашего механизма персистентности (RBDMS), Active Directory, Exchange, файловой системы, электронной почты и т. Д.

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

4 голосов
/ 08 апреля 2009

Эта проблема горячо обсуждается. Если вы спросите администратора базы данных, он сочтет лучшим в мире, чтобы все ваши приложения использовали предопределенные хранимые процедуры. Хотя эти дни подходят к концу, с ростом популярности Hibernate и LINQ, вы действительно МОЖЕТЕ использовать базу данных в качестве хранилища информации, и ваш уровень доступа к данным обрабатывает все запросы. Я думаю, что LINQ может сделать все для вас в MS SQL, кроме полнотекстового поиска. Что касается различий в производительности между SPROC и LINQ, то они незначительны. Мой голос - это не код в базе данных, а весь код на уровне доступа к данным, и я тестирую его.

3 голосов
/ 08 апреля 2009

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

Но если у вас есть сложные функции, хранимые процедуры, триггеры и т. Д., То у вас есть много мест, где могут быть ошибки, и тест приложения не покрывает их.

2 голосов
/ 08 июля 2009

Архитектор системы верен. Не следует вставлять бизнес-логику в вашу базу данных, и, следовательно, вы ничего не тестируете модулем.

1 голос
/ 08 апреля 2009

Я не знаю, почему, когда мы попадаем на слой db, вся хорошая практика должна идти в окно. Если в этом слое есть логика, это вдвойне важно. Существует замечательный инструмент, построенный поверх Fitnesse , называемый dbfit , который, кажется, снимает все трудности с модульного тестирования dblayer. Если вы заинтересованы, вы должны взглянуть.

1 голос
/ 08 апреля 2009

Я не делаю TDD непосредственно в моей базе данных, но есть много возможностей, где действительно можно поместить «логику» в базу данных. Ограничения, значения по умолчанию (да, я тоже знаю, что это ограничение), триггеры и т. Д. Часто это лучший способ реализовать некоторую бизнес-логику и обеспечить согласованность базы данных. Большую часть времени я могу убедить себя в правильности некоторых ручных испытаний и оставить все как есть, но я мог видеть, где кто-то может захотеть сделать TDD с этим.

EDIT

Например, я буду использовать значение по умолчанию при вставке и триггер при обновлении, чтобы установить поля «время последнего обновления» при вставке / обновлении. В LINQ я установлю столбец как автоматически сгенерированное значение и сделаю его доступным только для чтения. Для меня это проще, чем добавить обработчик события PropertyChanged, чтобы быть уверенным, что всякий раз, когда изменяется поле в сущности, также изменяется и последнее обновленное время. Я проверяю это? Конечно, но вручную и по факту, хотя я сильно предпочитаю TDD для большинства вещей.

1 голос
/ 08 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...