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