Comments 28
Вариант с копированием структуры базы напротив, требует много времени на свое выполнение, но зато и выполняется один раз. Т.е. Время его работы не зависит от количества запускаемых тестов.
А у вас не получится тогда ситуация, что тесты периодически что-то меняют в базе данных, и следующий тест может видеть результат предыдущего? Т.е. по-хорошему, тесты должны идти в полной изоляции и не знать о существовании друг друга. И база данных тоже должна очищаться после каждого теста. На этом нельзя халтурить )
Конечно самый удобный по скорости способ это транзакции, но в MySQL нет вложенных транзакций, а значит ваш метод тестирования будет бесполезен, если в самом приложении будет использована транзакция.
Хотелось бы услышать с какими проблемами сталкивались Вы при использовании DbUnit и как их решали.
Со всеми вышеописанными. Решал так:
codeception.com/docs/08-Data
+2
Т.е. решали поднимая каждый дамп для каждого юнит теста? А как тогда решали скорость выполнения тестов? При таком подходе у меня тесты выполнялись около 2-х минут, пришлось отказаться в пользу обычного TRUNCATE и скорость стала приемлемой: несколько десятков секунд.
0
Ну если вам нужна пустая база, возможно truncate помогает. Но лично я решал проблему очистки сразу с наполнением тестовыми данными, и потому что влив дампа, что truncate + заполнение данными занимали примерно одно и то же время.
А решения такие:
— эмулировать вложенные транзакции в приложении. Не так сложно, если не использовать чистый PDO, а какую-то обертку над ним.
— использовать SQLite.
— не использовать транзакции в тестируемом коде.
Но по скорости альтернативы транзакциям нет.
А решения такие:
— эмулировать вложенные транзакции в приложении. Не так сложно, если не использовать чистый PDO, а какую-то обертку над ним.
— использовать SQLite.
— не использовать транзакции в тестируемом коде.
Но по скорости альтернативы транзакциям нет.
0
как это нет вложенных транзакций? mysql 5.0 + innoDb вполне себе позволяют = dev.mysql.com/doc/refman/5.0/en/savepoint.html
0
А вы в приложении всегда сейвпоинтами пользуетесь? Я всегда только commit/rollback.
0
почему всегда? коміті и роллбеки использується только на внешней транзакции, внутри транзакция стартует и откатівается уже сейвпойнтами
0
Это не вложенные (nested transaction) транзакции по определению.
+1
>> транзакция прерывается при выполнении операции Truncate
Я вам больше скажу больше — dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
Поэтому сомнительный это способ
Я вам больше скажу больше — dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
Поэтому сомнительный это способ
0
Не модульные это тесты, а функциональные.
Для себя проблему решил так:
— В модульных тестах, которые запускаются каждые «5 минут», проверяю работу классов с БД стабированием/моканием объектов PDO, mysqli, ORM или своей обёртки для mysql_*. Многословно получается (при использовании PHPUnit), но не проверяю ничего лишнего, в частности работу расширений PHP и СУБД. Грубо говоря, проверяю что вызван метод
— Проверку синтаксиса (прежде всего, судя по количеству фейлов) и логики отдельных запросов проверяю в интеграционных, которые запускаются гораздо реже.
— «Глобальную» работу с БД (несколько запросов, до десятков на страницу) с переходами между страницами проверяю в функциональных/приемочных тестах, которые запускаются крайне редко.
При таком подходе мудрить с оптимизацией времени выполнения тестов с СУБД не приходится.
Для себя проблему решил так:
— В модульных тестах, которые запускаются каждые «5 минут», проверяю работу классов с БД стабированием/моканием объектов PDO, mysqli, ORM или своей обёртки для mysql_*. Многословно получается (при использовании PHPUnit), но не проверяю ничего лишнего, в частности работу расширений PHP и СУБД. Грубо говоря, проверяю что вызван метод
$db_con->query('SELECT * FROM users')
и подставляю в возврат ожидаемый массив. То есть проверяю работу PHP кода и ничего больше.— Проверку синтаксиса (прежде всего, судя по количеству фейлов) и логики отдельных запросов проверяю в интеграционных, которые запускаются гораздо реже.
— «Глобальную» работу с БД (несколько запросов, до десятков на страницу) с переходами между страницами проверяю в функциональных/приемочных тестах, которые запускаются крайне редко.
При таком подходе мудрить с оптимизацией времени выполнения тестов с СУБД не приходится.
+1
Забыли сказать, что для не транзакционного движка вся эта песня с откатами работать не будет.
И что же, вы запускаете тесты на продакшн базе?
Идея плавает на поверхности: завести для тестов еще одну базу данных. Но в этом случае придется поддерживать в актуальном состоянии обе базы данных.
И что же, вы запускаете тесты на продакшн базе?
0
Используя расширение DBUnit следует переопределить метод getConnetction, который, как следует из ...
Опечаточка)
0
Не понимаю людей, которые не путешествуют по России при первой же возможности пытаются тестировать классы, работающие с базой данных. Ну зачем?
PHPUnit создан для тестирования интерфейсов! Я вообще не считаю, что он должен поддерживать тестирование БД.
Ну предположим, будет написан класс, задача которого отправлять запросы к БД используя переданное ему соединение с БД. Ну напишу я запрос, который передам методу этого класса. Протестирую, что с той пачки данных, которая имеется в тестовом окружении, мне вернулись правильные данные. А дальше то что? На живом сайте будет куча данных, других данных и этот тест толком не гарантирует того, что код или запрос рабочий. Индекса не будет, запрос будет тормозить, PHPUnit никогда это не протестирует. Нет, можно, наверное, навставлять костылей, которые и время выполнения запроса потестируют и explain запроса посмотрят, но это уже что-то сложное и не вообразимое в итоге получится.
PHPUnit создан для тестирования интерфейсов! Я вообще не считаю, что он должен поддерживать тестирование БД.
Ну предположим, будет написан класс, задача которого отправлять запросы к БД используя переданное ему соединение с БД. Ну напишу я запрос, который передам методу этого класса. Протестирую, что с той пачки данных, которая имеется в тестовом окружении, мне вернулись правильные данные. А дальше то что? На живом сайте будет куча данных, других данных и этот тест толком не гарантирует того, что код или запрос рабочий. Индекса не будет, запрос будет тормозить, PHPUnit никогда это не протестирует. Нет, можно, наверное, навставлять костылей, которые и время выполнения запроса потестируют и explain запроса посмотрят, но это уже что-то сложное и не вообразимое в итоге получится.
-1
Есть интерфейс для получения 5 последних вопрос из базы данных. И как тестировать без базы данных? Или не тестировать вообще? Последнее это уже признак плохого тестирования.
0
Не тестировать вообще не нужно. Покрывать тестами 100% кода тоже не нужно.
Если я правильно понял суть вопроса, то откройте для себя моки: www.phpunit.de/manual/3.0/en/mock-objects.html
Мок будет подменять экземпляр класса, который общается с БД. А тестировать нужно класс, который возвращает 5 последних вопросов в зависимости от того, что вернула БД, которая в тесте на самом деле мок.
Если я правильно понял суть вопроса, то откройте для себя моки: www.phpunit.de/manual/3.0/en/mock-objects.html
Мок будет подменять экземпляр класса, который общается с БД. А тестировать нужно класс, который возвращает 5 последних вопросов в зависимости от того, что вернула БД, которая в тесте на самом деле мок.
0
Я знаю, что такое моки. Покрывать тестами 100% кода не нужно, но к этому надо стремиться. Вопрос остается в силе. «экземпляр класса, который общается с БД. » и который будет подменяться моком, вы предлагаете не тестировать?
0
Модульными тестами не тестировать, функциональными (фактически их и описывают в топике) много не натестируешь. Как например протестировать, что на сервер mysql упало бетонное перекрытие?
Класс, который возвращает 5 последних вопросов и класс, который общается с БД — в моём понимании это два разных класса. Это я про то, что в предыдущем комментарии было: «Есть интерфейс для получения 5 последних вопрос из базы данных.»
Класс, который возвращает 5 последних вопросов и класс, который общается с БД — в моём понимании это два разных класса. Это я про то, что в предыдущем комментарии было: «Есть интерфейс для получения 5 последних вопрос из базы данных.»
0
Один или два не так важно. Все же один класс останется без тестов?
0
Порой проще использовать тестовые данные и БД чем создавать моки для классов баз данных.
Ибо там такие моки получатся, которые будут включать в себя парсер SQL. Зачем оно надо?
KISS
Ибо там такие моки получатся, которые будут включать в себя парсер SQL. Зачем оно надо?
KISS
0
У меня не получалось моков, которым нужно парсить SQL… Что я делаю не так? :)
Тестирование БД недопустимо именно модульными тестами, потому что они должны выполняться максимально быстро. По крайней мере в TDD и ему подобных.
Ещё вот про dataproviders: www.phpunit.de/manual/3.6/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers. Это если сложности с возвратом кучи разных данных, которые могла бы вернуть БД.
Ну и, если всё таки очень хочется потестировать БД, то стоит почитать эту часть мануала: www.phpunit.de/manual/3.6/en/database.html. Там про датасеты и дататэйблы очень интересно написано.
Тестирование БД недопустимо именно модульными тестами, потому что они должны выполняться максимально быстро. По крайней мере в TDD и ему подобных.
Ещё вот про dataproviders: www.phpunit.de/manual/3.6/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers. Это если сложности с возвратом кучи разных данных, которые могла бы вернуть БД.
Ну и, если всё таки очень хочется потестировать БД, то стоит почитать эту часть мануала: www.phpunit.de/manual/3.6/en/database.html. Там про датасеты и дататэйблы очень интересно написано.
0
Sign up to leave a comment.
PHP Unit. Опыт тестирования классов, работающих с Базой Данных