Symfony Unit test доступ к Doctrine

no_alex

Новичок
Только начал изучать Symfony, поэтому сразу прошу прощения за возможно "тупой вопрос".

Суть в следующем:
- внутри созданного мною bundle есть класс, который я объявил как сервис (это не контроллер);
- в этом сервисе у меня идёт работа с Doctrine;
- с помощью параметров в конфиге я прописал чтобы в конструктор этого сервиса автоматически передавался объект Doctrine (\Doctrine\Bundle\DoctrineBundle\Registry);
Когда вызывал этот сервис из какого-либо контроллера (с помощью метода get) всё работало нормально.

Теперь встала задача написать Unit test к этому сервису. И я зашёл в тупик как организовать здесь работу с Doctrine.
Хотелось-бы, если это возможно, получить 3 способа решения этой задачи:
1) Получать объект этого сервиса способом аналогичным тому, что я использовал в контроллере - через какой-либо специальный метод (я не нашёл такого метода в классе \PHPUnit_Framework_TestCase, от которого я наследовался), так чтобы все параметры конфига подтягивались автоматически.
2) Создавать объект Doctrine в классе Unit test (согласно указанным в основном конфиге параметрам) и передавать в тестируемый сервис через конструктор или специальный метод;
3) Создавать объект Doctrine внутри тестируемого сервиса (согласно указанным в основном конфиге параметрам), так чтобы вообще не было необходимости дополнительно передавать этот объект.

Подскажите, возможны ли эти 3 способа и как их реализовать?
 

Вурдалак

Продвинутый новичок
Наверняка у этого Registry есть выделенный интерфейс, он и должен быть указан в type hinting в конструкторе. Далее либо stub (final class StubRegistry implements RegistryInterface), либо mock ($this->getMockForAbstractClass(RegistryInterface::class) ) в зависимости от ситуации.

Но вообще я бы не рекомендовал пихать в bundle что-то не Symfony-специфичное. Ровно как и завязываться на Doctrine.
 

keltanas

marty cats
1. Не стоит очень сильно увлекаться тестированием. Тесты должны иметь необходимый и достаточный объем, чтобы выявлять ощибки. А писать тесты до идеала можно бесконечно.
2. Если пишешь Unit-тест, то уже само слово unit подразумевает, что ты не будет тестировать в нем доктрину и СУБД, а будешь тестировать только бизнес-логику модуля (unit). Конечно, зайти можно очень далеко и тестировать все и вся. Но, таким образом будешь только бесконечно писать и исправлять тесты. На функционал времени будет оставаться очень мало.
3. Если хочешь тестировать свою систему с точки зрения работы пользователя, то попробуй посмотреть в сторону поведенческого тестирования. Тест будет выглядеть буквально как: "Зайти на страницу, выполнить список действий, увидеть правильный (или не правильный) результат.". Посмотри на Behat. Он удобен, приятен. Тут можно посмотреть примеры использования.
 

no_alex

Новичок
Перелопатил весь интернет и нигде не нашел "независимого способа" получения этого объекта (\Doctrine\Bundle\DoctrineBundle\Registry).
Везде натыкаюсь только на вызов из конструктора метода: $this->getDoctrine().

Через конструкцию new пока тоже не пойму можно ли создать этот объект, т.к. в него первым аргументом надо передать аргумент "ContainerInterface $container" и я пока не пойму где этот объект взять...
 

Вурдалак

Продвинутый новичок
Перелопатил весь интернет и нигде не нашел "независимого способа" получения этого объекта (\Doctrine\Bundle\DoctrineBundle\Registry).
Везде натыкаюсь только на вызов из конструктора метода: $this->getDoctrine().

Через конструкцию new пока тоже не пойму можно ли создать этот объект, т.к. в него первым аргументом надо передать аргумент "ContainerInterface $container" и я пока не пойму где этот объект взять...
Тебе не нужен для тестирования класс \Doctrine\Bundle\DoctrineBundle\Registry вообще.
 

no_alex

Новичок
а будешь тестировать только бизнес-логику модуля (unit)
Да именно бизнес-логику хочу проверить, но у меня она на данном этапе пока неразрывно связана с одной простой таблицей в БД и хотелось-бы всё-же решить эту задачу...
 

keltanas

marty cats
@no_alex, значит это уже не бизнес-логика, а логика приложения. И эта задача не решается модульным тестированием.
Тебе нужен функциональный или поведенческий тест.
Нет ничего хуже, чем решать задачи не подходящими для них инструментами.
 

no_alex

Новичок
Спасибо за совет!
Попробую сейчас смотреть в эту сторону.
 

Вурдалак

Продвинутый новичок

fixxxer

К.О.
Партнер клуба
От этого бехата веет за милю хипстерством каким-то, как по мне.

What is behavior-driven development, you ask? It’s the idea that you start by writing human-readable sentences
Ну ведь совсем не так. :) Это все поддерживается какой-то иллюзией, что, дескать, это будет понятно нетехническим людям, менеджерам. Вы хоть раз видели, чтобы им такие вещи были вообще интересны? Я нет.

Я предпочитаю codeception, который не навязывает никакой идеологии.
 

Вурдалак

Продвинутый новичок
От этого бехата веет за милю хипстерством каким-то, как по мне.
Возможно просто Gherkin не самый удачный язык для спецификаций и в будущем будет какая-то более интересная альтернатива (а-ля DaSpec).

Мне нравится идея executable specifications, потому что никто и никогда не может гарантировать, что требования, описанные где-то в wiki являются актуальными. И они обязательно через какое-то время перестанут быть таковыми. Требуется своего рода single source of truth. Gherkin-сценарии можно, например, вставлять в качестве примеров в реальную доку, которая «для менеджеров».

Что до codeception, то я так и не понял, там вообще можно, например, прогонять тесты в разных контекстах (web, API, domain)? Все эти примеры с $guy->click() меня убивают.
 

fixxxer

К.О.
Партнер клуба
никто и никогда не может гарантировать, что требования, описанные где-то в wiki являются актуальными
Это очень хорошо, когда они вообще есть в сколь-либо вменяемом виде. Если у вас есть, я прям даже завидую. :)

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

Все эти примеры с $guy->click() меня убивают.
Да, я это тоже не особо понимаю. Какой-то UI-driven testing. Иногда, конечно, именно это и нужно, но довольно редко.

можно, например, прогонять тесты в разных контекстах (web, API, domain)?
Можно вот так сделать, например.
 

Вурдалак

Продвинутый новичок
Совсем без wiki странно: откуда новый менеджер будет брать информацию о текущих бизнес-требованиях? :)

Хотя у нас это тоже сложно назвать вменяемыми доками, я лично почти не пользуюсь.

Кстати, минимизировать расхождения реального поведения и ожидаемого можно, если вести доки прямо в репозитории проекта в каком-нибудь markdown. И из них уже генерировать и выкладывать где-то.
 
Последнее редактирование:

fixxxer

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

Кстати, минимизировать расхождения реального поведения и ожидаемого можно, если вести доки прямо в репозитории проекта в каком-нибудь markdown. И из них уже генерировать и выкладывать где-то.
Вот, здесь нужен именно общий источник, и выполнение bdd-тестов на основе спек прямо из вики. (Либо односторонняя синхронизация - скажем, вполне реально генерировать "человекочитаемые" спецификации из тестов, написанных на PHP, прогнав их через php-parser. :))

Это хорошая идея, но я редко видел, чтобы на нее делали упор. Все больше разговоров о том, что вот мы тут напишем сценарии на человекопонятном языке, а менеджеры их будут щастливо читать (видимо, прямо из репозитория, лол). Какая-то хипстерская утопия.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Ну ведь совсем не так. :) Это все поддерживается какой-то иллюзией, что, дескать, это будет понятно нетехническим людям, менеджерам. Вы хоть раз видели, чтобы им такие вещи были вообще интересны? Я нет.
Если бы это было так, все бы писали на PowerShell вместо баша )
 

Вурдалак

Продвинутый новичок
Вот, здесь нужен именно общий источник, и выполнение bdd-тестов на основе спек прямо из вики. (Либо односторонняя синхронизация - скажем, вполне реально генерировать "человекочитаемые" спецификации из тестов, написанных на PHP, прогнав их через php-parser. :))
Ну вот как раз Behat и будет тем же самым. Там ведь можно писать обычным текстом, см. http://docs.behat.org/en/v3.0/quick_intro_pt1.html
Feature: Product basket
In order to buy products
As a customer
I need to be able to put interesting products into a basket

Rules:
- VAT is 20%
- Delivery for basket under £10 is £3
- Delivery for basket over £10 is £2

Scenario: Buying a single product under £10
Given there is a "Sith Lord Lightsaber", which costs £5
When I add the "Sith Lord Lightsaber" to the basket
Then I should have 1 product in the basket
And the overall basket price should be £9
Тут просто появляется желание заюзать markdown и кажется лучше наоборот: писать обычную доку в markdown, а потом вставлять отдельные сценарии-примеры в доку.
 

keltanas

marty cats
@Вурдалак, возможно.
Посмотрел по диагонали DsSpec. Мне кажется что Геркин лучше читабелен. Python style такой. А MD лучше читается после парсинга в HTML )). Но возможно дело привычки.
Кстати, может Геркин в HTML парсить? ))

@fixxxer
Мне наоборот codeception кажется более хипстерским и менее продуманным. На behat писать тесты гораздо приятнее, и вывод результатов информативнее.
CC более простой для вхождения, но из-за этого возможностей выстрелить себе в ногу больше.
Например:
PHP:
$data = $I->grabDataFromResponseByJsonPath('$.data')[0];
$I->assertEquals(100500, $data['id']);
$I->assertEquals('Ololo', $data['title']);
вместо
PHP:
$I->seeResponseContainsJson([
  'data' => [
      'id' => 100500,
      'title' => 'Olololo'
  ]
]);
На Бехате такого не напишешь.
 
  • Like
Реакции: WMix

fixxxer

К.О.
Партнер клуба
Может быть, может быть.

В общем-то против инструмента я ничего не имею, меня раздражает hype вокруг, напоминающий agile-сектантов со скрам-тренерами. :)
 
Сверху