Возможно, я смогу дать вам представление о нашем опыте, когда мы начали смотреть на модульное тестирование нашего процесса среднего уровня, который включал в себя массу SQL-операций «бизнес-логики».
Сначала мы создали уровень абстракции, который позволил нам «вставить» любое разумное соединение с базой данных (в нашем случае мы просто поддерживали одно соединение типа ODBC).
Как только это было сделано, мы смогли сделать что-то подобное в нашем коде (мы работаем на C ++, но я уверен, что вы поняли):
GetDatabase (). ExecuteSQL («ВСТАВИТЬ В foo (бла, бла)»)
В обычное время выполнения GetDatabase () возвращает объект, который передавал все наши sql (включая запросы), через ODBC напрямую в базу данных.
Затем мы начали изучать базы данных в памяти - в лучшем случае, похоже, SQLite. ( http://www.sqlite.org/index.html ). Это удивительно просто установить и использовать, и позволило нам создать подкласс и переопределить GetDatabase () для пересылки sql в базу данных в памяти, которая была создана и уничтожена для каждого выполненного теста.
Мы все еще находимся на ранних стадиях этого процесса, но пока все выглядит хорошо, однако нам необходимо убедиться, что мы создаем все необходимые таблицы и заполняем их тестовыми данными - однако мы несколько сократили рабочую нагрузку, создав универсальный набор вспомогательных функций, которые могут многое для нас сделать.
В целом, это очень помогло с нашим процессом TDD, поскольку внесение, казалось бы, довольно безобидных изменений для исправления определенных ошибок может иметь довольно странные последствия для других (трудно обнаруживаемых) областей вашей системы - из-за самой природы sql / database.
Очевидно, что наш опыт был сосредоточен вокруг среды разработки C ++, однако я уверен, что вы могли бы получить что-то подобное, работая в PHP / Python.
Надеюсь это поможет.