TDD с функциями SQL и манипулирования данными


14

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

Тем не менее, большая часть моей работы связана с написанием сложного SQL и последующей обработкой вывода. Как бы вы написали тест, чтобы убедиться, что ваш SQL возвращает правильные данные, например? Затем, скажем, если данные не были под вашим контролем (например, системы сторонних производителей), как вы можете эффективно протестировать свои процедуры обработки без необходимости писать стопки фиктивных данных?

Лучшее решение, которое я могу придумать, - это просмотр данных, которые вместе охватывают большинство случаев. Затем я могу объединить эти представления с моим SQL, чтобы увидеть, возвращает ли он правильные записи, и вручную обработать представления, чтобы увидеть, выполняют ли мои функции и т. Д. То, что они должны. Тем не менее, это кажется чрезмерным и ненадежным; особенно поиск данных для проверки ...


Ответы:


6

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

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

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

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


3

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

Представления, вероятно, были бы трудным способом сделать это, потому что они на самом деле не предоставляют тесту первое автоматическое тестирование одного красного света, зеленого света одного аспекта на тест, которое является предпочтительным в TDD. Также с представлениями вы не можете написать тест перед кодом. Лучшим подходом было бы написать хранимые процедуры, в которых вы можете добавить логику «assert» в процедуру (например, используя операторы «if») для проверки вывода на предмет отказа. Вам нужно протестировать только одну вещь в каждом модульном тесте, чтобы изолировать модуль, и для этого лучше подойдет метод SP. Кроме того, с помощью SP вы можете запускать весь их набор в виде сценариев при разработке исходного кода и позже при тестировании регрессий при рефакторинге.

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

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


Почему вы не можете написать тест для представления, которое еще не было закодировано?
JeffO

Нет, если вы используете представление в качестве механизма для теста, как предложено OP.
Под ключ

1

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

Ожидаемые наборы результатов могут быть сохранены в таблицах базы данных или во внешних файлах / таблицах. Я даже видел использование CHECKSUM или сравнение. Когда вы тестируете view / sproc, вы получите ошибку, так как они не существуют. Затем вы создаете объект с достаточным количеством кода для его выполнения (SELECT -1 как [неправильные_данные];), и вы получите ошибку, поскольку она не соответствует результирующему набору. Как только они совпадают, у вас есть зеленый свет.

Я начал работать с владельцами проектов и просил их макетировать отчеты в электронной таблице и пытаться найти для меня частичные данные (вы можете поместить данные результатов в тестовую таблицу). Сначала был некоторый откат, но они поняли, что я собираюсь создать отчет, и им все равно придется его проверить. Это сэкономило время в долгосрочной перспективе. Если они хотят сделать запрос на изменение, они могут повторить электронную таблицу. Теперь они могут ответить на вопрос: «Как трудно было бы добавить ...?»


1

Если вашей платформой базы данных является SQL Server, есть очень хороший бесплатный инструмент: tSQLt .

tSQLt является структурой модульного тестирования базы данных для Microsoft SQL Server. tSQLt совместим с SQL Server 2005 (требуется пакет обновления 2) и выше во всех выпусках.

Я успешно использовал для проведения тестирования на уровне базы данных.

Вот некоторые из ключевых элементов, которые делают его таким полезным:

  • Способность работать с фальшивыми таблицами и представлениями, что уменьшает обычную настройку
  • Тесты автоматически запускаются в транзакциях (так что их легко перезапускать)
  • Ваши утверждения могут сравнивать таблицы (как реальные, так и поддельные), чтобы вы могли увидеть, легко ли вы изменили какие-либо данные.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.