#unit-testing #mocking #phpunit
#модульное тестирование #издевательство #phpunit
Вопрос:
Я только недавно начал изучать модульное тестирование с помощью PHPUnit и задавался вопросом, возможно ли издеваться над всей моей базой данных для всех моих тестов. Мои классы моделей (объекты строк таблицы, обернутые для реализации ActiveRecord) внедрены в базу данных, а некоторые модели имеют много уровней других классов моделей, поэтому издевательство над всем этим, похоже, будет проблемой в конце.
Возможно ли заставить PHPUnit использовать данные из CSV-файла в качестве моей базы данных и запускать мои тесты с данными там, не касаясь моего DAO? Я прочитал раздел о тестировании базы данных в PHPUnit, но я не уверен, что это то, чего я хочу, потому что я не столько хочу тестировать базу данных или код, взаимодействующий с базой данных, сколько тот факт, что мои классы моделей очень привязаны к базе данных, и было бы мучительно постоянно издеваться над чем-то. Если бы я мог предоставить ей CSV-файл в качестве моей базы данных, тогда я мог бы просто поместить свои данные в CSV-файл и продолжить работу в обычном режиме.
Не уверен, что я ясно выражаюсь, поэтому, пожалуйста, попросите разъяснений. Если это возможно достичь, то это было бы фантастически. Без этого модульного тестирования этот зверь может быть непрактичным, но я действительно хочу внедрить модульное тестирование в проект.
Спасибо
Ziad
Комментарии:
1. Я считаю, что лучше всего издеваться над самими DAO при тестировании классов, которые их используют. Пока вы можете вручную создавать экземпляры модели для возврата из методов запроса mock DAO, все готово.
Ответ №1:
На мой взгляд, есть несколько преимуществ использования DBUnit для тестирования вашего кода, зависящего от базы данных. Это может относиться или не относиться ко всем, я согласен. Я сам не использовал DBUnit до самого недавнего времени, поскольку обнаружил, что это излишне для небольших проектов, в которых я участвую.
Использование DBUnit отделяет ваши тесты от базы данных. Ваша тестируемая система не должна зависеть от сервера БД для запуска, вам нужна максимально возможная изоляция. Обычно это не имеет большого значения, поскольку многие люди используют модульные тесты для тестирования интеграции, и для этого вы бы предпочли использовать настройки базы данных, которые максимально соответствуют вашей производственной среде.
Еще одна причина, по которой DBUnit является благоприятным, заключается во времени, которое он экономит при написании тестов. Написание тестов — это не та часть программирования, которой я люблю заниматься, и использование mocks, когда это возможно, экономит много времени. Конечно, создать копию вашей базы данных легко, но вам все равно придется создавать сценарии для загрузки тестовых данных, иметь сценарии для сброса тестовых данных между каждым тестовым запуском. Многие тесты будут зависеть от конкретных наборов данных, и это становится сложнее поддерживать по мере добавления тестов. Конечно, вся эта настройка должна быть синхронизирована с вашим реальным приложением по мере его развития. В зависимости от приложения это может занять очень много времени. В некоторых приложениях есть тысячи тестов, и это душераздирающе, когда простое изменение в приложении приводит к тому, что приходится переписывать 20 тестов и их наборы данных.
Как бы то ни было, есть процесс обучения использованию DBUnit, и при первом использовании это может занять немного времени. Как только он установлен для одного теста, это экономит время для последующих. Я не использую это везде, поскольку у меня написано много тестов, которые зависят от реального сервера, но новый код и тесты, которые я пишу, я пытаюсь создать на основе моей первоначальной настройки DBUnit, и ясно видно, что это действительно экономит время в долгосрочной перспективе.
Мои 2 цента, добрый день, друг.
Комментарии:
1. Спасибо за ваш пост. Я начал думать (снова!) о том, как это сделать, используя реальную базу данных, и начал понимать, что возникнут некоторые из упомянутых вами проблем. НО это, похоже, самый простой способ начать, и также нам, возможно, придется ввести много тестовых данных в эту макет базы данных, чтобы сделать ее полезной. Итак, стеф, ты можешь дать мне несколько советов о том, как я могу начать работу с DBUnit? И что более важно для меня, возможно ли вообще увеличить макет базы данных для каждого теста в наборе? Как мне это сделать?
Ответ №2:
Как насчет использования вашей базы данных, но без внесения изменений? Или откат после запуска тестов? Мы используем копию нашего производственного сайта в качестве тестовой среды на отдельном сервере и проводим все наше тестирование там.
Комментарии:
1. Да, после отправки вопроса я начал думать, что, возможно, я подхожу к этому с неправильной точки зрения. Я должен использовать реальную базу данных, но такую, которая настроена только для выполнения тестов. Мне нравится ваша идея отката после тестов. Я посмотрю, смогу ли я заставить это работать. Я все еще хотел бы услышать, что скажут другие модульные тестировщики.
Ответ №3:
Возможно, вы могли бы создать копию базы данных и просто подключиться к этой копии в своих тестовых загрузках?
Я вроде как в такой же ситуации, и это вариант, который я сейчас разрабатываю… Не идеально, но, по крайней мере, первые тесты работают
Комментарии:
1. Да, я согласен и полностью отношусь к «но, по крайней мере, первые тесты работают» 🙂 Но если серьезно, я думаю, что это правильный путь, наряду с откатом, как предложил Дейв.
Ответ №4:
Метод, который работал у меня раньше, заключается в том, чтобы напрямую издеваться над адаптером базы данных и внедрять макет в цепочку зависимостей. Однако это работает только для очень маленьких модулей, поскольку очень сложно заставить макет адаптера возвращать структуру массива, которую вы ожидаете получить из определенного запроса. Если в вызове одного метода задействовано несколько запросов, это вообще не сработает.
Другая тактика, с которой я добился успеха, — это использование DBUnit только для настройки и демонтажа базы данных. Данные прибора хранятся в файле XML или Yaml и импортируются в пустую базу данных перед каждым тестом, обеспечивая известное состояние. Учитывая схему и минимальный набор данных, база данных в памяти будет выполнять тесты достаточно быстро, избегая проблемы с дисковым вводом-выводом.
Наконец, подумайте, нужно ли вам вообще писать тесты для сохранения данных… Если вы тестируете реализацию ActiveRecord, у вас, вероятно, есть несколько тестов, которые подтверждают базовые операции CRUD на уровне библиотеки. То, что вас действительно интересует в тестировании, зависит не от базы данных, а от того, что объекты в памяти ведут себя ожидаемым образом при задании известной начальной точки. Вы можете получить известную отправную точку, создав объект в памяти, вообще не загружая его из базы данных и не сохраняя в ней.
Просто настройте ожидаемое состояние в памяти, создав некоторые объекты, используйте бизнес-логику, запросите конечное состояние и никогда не утруждайте себя вызовом «сохранить»… Или как вы там это назвали. Если все, что вам нужно, это объект, который выглядит как подключение к базе данных для удовлетворения зависимости, у вас есть макет для этого…
Комментарии:
1. Спасибо за ваш вклад, Дэвид. Мне нравится ваше предложение о том, что БД вообще не нужна, я думаю, это идеальная ситуация, когда код написан так, что его можно модульно тестировать без необходимости в БД. К сожалению, наш код не был написан с учетом этого, так что до того, чтобы вообще не нуждаться в DB, вероятно, довольно далеко. Что еще хуже, мне пришлось отложить модульное тестирование на задний план, поскольку появились другие, более срочные вещи. Чувак, это всегда происходит! 🙁