2015-04-10 3 views
1

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

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

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

+0

Что вы хотите проверить? Что работает sql или что будет выполнена правильная «версия» sql? –

+0

В принципе, я хочу проверить, что конечный результат тот же. Что делает сама функция, это запрос базы данных для некоторых данных и использование бит логики для этих данных для получения результата. Тем не менее, можно выполнить одну и ту же задачу с помощью другого запроса и другой логики (случай, который я сейчас рассматриваю, - это использование 2 SELECT * по сравнению с SELECT * с LEFT JOIN), поэтому я хочу идеально учитывать что при написании тестов. –

+0

Трудно сказать отсюда, является ли «бит логического кода» общим? Место, куда я попытаюсь добраться, - это sql в каком-то файле ресурсов, выбранном dbms/version. без этого, это будет серьезной болью в задней части. –

ответ

2

Ну, для начала я думаю, что это очень много, что зависит от контекста приложения, набор навыков QA/dev &. Итак, я думаю, что это правильно, возможно, не так.

Сказав, что ...

В моем случае, у меня есть система, в которой чрезвычайно сложная ERP база данных, которые я не контроль, очень много места водителя и мой код зрителя/наблюдатель, а не драйвером этой базы данных. Я не могу и не могу использовать слой ORM, все мое добавленное значение находится в запросах, которые глубоко понимают базовую модель данных базы данных. Обратите внимание также, что я в основном являюсь зрителем этого db, на самом деле мой код имеет доступ только для чтения к первичному db. Он имеет доступ на запись к своей собственной базе данных тегов, в которой используется ORM Django, и тестирование отличается по своей природе тем, что я полагаюсь на ORM.

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

Mock objects? Возможно, насмехались бы, если бы было много законных причин для просмотра/изменения содержимого базы данных со сложными запросами.

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

Многоплатформенные проблемы. Я начал кодирование в postgresql, подстроил свои библиотеки подключений для поддержки Oracle. Удалил модульные тесты и исправил все, что появилось как ошибка. Будет ли абстракция базы данных идентифицировать такие вещи, как обработка предложения LIMIT в Oracle?

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

Испытательная прочность. Один урок, который я изучил на этом пути, - это отделить тест от теста db. Предположим, вы хотите протестировать функцию, которая отображает активных клиентов, которые ничего не заказывали через год. Мой первоначальный подход к тестированию включал ручные поиски в тестовой базе данных, чтобы найти CUST701 в соответствии с условием. Затем вызовите мою функцию и проверьте, является ли CUST701 результирующим набором клиентов, нуждающихся в проверке. Неправильный подход. То, что вы хотите сделать, это написать в своем тесте запрос, в котором находятся активные клиенты, которые ничего не заказывали через год.Никаких жестко закодированных CUST701s, но ваш запрос тестового запроса может быть столь же жестко запрограммирован, как вы хотите - на самом деле, он должен выглядеть как можно меньше запросов к вашему приложению - вы не хотите, чтобы ваш тестовый sql реплицировал то, что потенциально может быть ошибкой в вашем производственном коде. После того, как вы динамически идентифицировали целевого клиента, отвечающего критериям, затем вызовите свой тестируемый код и посмотрите, ожидаются ли результаты. Убедитесь, что ваши инструменты покрытия идентифицируют, когда вам не хватает тестовых сценариев и подключите эти отверстия в тестовом db.

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

Кодеры всегда имели тестовые базы данных. Для меня логично использовать их для тестирования BDD/unit-testing, а не притворяться, что их не существует. Но я нахожусь в основе SQL-кодера, который очень хорошо знает Python, а не эксперт Python, который, как правило, не работает в SQL.

+0

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

+1

Правильно.Это ключевой момент - напишите тестовый запрос, чтобы определить критерии тестирования и ожидания, затем вызовите свой код против этого динамически определенного набора входных параметров. Выполните свои утверждения против динамически ожидаемых ожиданий. Если вы этого не сделаете, вы получите действительно хрупкие тесты, и вы попадете в испытательный лагерь «mock/dont db». –

+0

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

1

Как мне кажется, у меня был неправильный конец палки, у меня была подобная проблема, и, как вы, ОРМ не был вариантом.

Способ, которым я обращался к нему, состоял из простых коллекций объектов передачи данных. Так что новый код, который я написал, не имел прямого доступа к db. Он сделал все с простыми списками объектов. Вся бизнес-логика и ui могут быть протестированы без db.

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

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

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