Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Laravel
Code

Laravel, BDD и вы: начинаем работу

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Laravel, BDD And You.
Laravel, BDD and You: The First Feature

Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)

Добро пожаловать в эту серию статей о разработке приложений Laravel с использованием подхода, основанного на поведении (BDD). Полный стек BDD может казаться сложным и пугающим. Сколько есть разных разработчиков, столько же существует различных способов сделать это.

В этой серии я расскажу вам о том, как использовать Behat и PhpSpec для разработки приложения Laravel с нуля.

По BDD есть много ресурсов, но конкретных материалов по Laravel трудно найти. Поэтому в этой серии мы сосредоточимся больше на аспектах, связанных с Laravel, и меньше на общем материале, который вы можете прочитать в многих других местах.

Описание поведения

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

Когда мы это сделаем, что мы ожидаем получить?

Нам не разрешается писать какой-либо код до тех пор, пока у нас не будет неудачного, красного шага, или пока если мы не реорганизуем существующий код.

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

Мы будем писать истории и специфиации на четырех разных уровнях:

1. Приемочный

В большинстве случаев наш функциональный набор будет служить нашим приемочным уровнем. То, как мы будем описывать наши функции в нашем функциональном наборе, будет очень похоже на то, как мы будем писать истории принятия (используя Фреймворк с браузером) и, таким образом, создадим много дублирования.

Пока истории описывают поведение с точки зрения клиента, они являются приемочными историями. Мы будем использовать Symfony DomCrawler для проверки вывода нашего приложения. Позже в этой серии мы можем обнаружить, что нам нужно протестировать реальный браузер, который также может запускать JavaScript. Тестирование через браузер добавляет некоторые новые проблемы, так как нам нужно убедиться, что мы загружаем нашу среду тестирования при запуске тестов.

2. Функциональные

В нашем функциональном наборе у нас будет доступ к приложению Laravel, что очень удобно. Прежде всего, это позволяет легко различать среды. Во-вторых, так как нам не нужно переходить в браузер, то это делает наш тестовый набор намного быстрее. Всякий раз, когда мы хотим внедрить новую функцию, мы напишем историю в нашем функциональном пакете с использованием Behat.

3. Интеграция

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

4. Unit

Наши модульные тесты будут написаны на PhpSpec и будут тестировать изолированные небольшие единицы ядра приложения. Все наши сущности, объекты-значения и т.д. будут иметь спецификации.

Пример использования 

На протяжении этой серии, начиная со следующей статьи, мы будем строить систему для отслеживания времени. Мы начнем с описания поведения извне, написав функции Behat. Внутреннее поведение нашего приложения будет описано с помощью PhpSpec.

Вместе эти два инструмента помогут нам чувствовать себя комфортно с качеством используемого нами приложения. В первую очередь мы будем писать функции и спецификации на трех уровнях:

  1. функциональный
  2. Интеграционный
  3. Модульный


В нашем функциональном наборе тестов мы будем обходить HTTP-ответы нашего приложения в режиме headless, что означает, что мы не будем открывать браузер. Это упростит взаимодействие с Laravel.

Позже, если мы закончим с более сложным интерфейсом и, возможно, придется протестировать и некоторый JavaScript, мы можем добавить специальный набор для приемочных тестов. Эта серия статей все еще в процессе создания, поэтому не стесняйтесь оставлять свои предложения в разделе комментариев.

Наши настройки

Обратите внимание, что для этого урока я предполагаю, что у вас установлена новая версия Laravel (4.2). Вы также используете Laravel Homestead, и это то, что я использовал, когда писал этот код.

Прежде чем мы приступим к реальной работе, давайте убедимся, что у нас есть Behat и PhpSpec. Во-первых, хотя мне нравится делать чистку всякий раз, когда я начинаю новый проект laravel и удаляю то, что мне не нужно:

Если вы удалите эти файлы, обязательно обновите файл composer.json соответственно:

И, конечно же:

Теперь мы готовы задействовать инструменты BDD, которые нам нужны. Просто добавьте раздел require-dev к вашему composer.json:

Вы можете подумать: «Почему мы пытаемся использовать PHPUnit?»? Мы не собираемся писать старые добрые тестовые примеры PHPUnit в этой серии, но их утверждения - удобный инструмент вместе с Behat. Мы увидим это позже в этой статье, когда мы напишем нашу первую функцию.

Не забудьте обновить свои зависимости после изменения composer.json:

Мы почти закончили установку и настройку. PhpSpec работает из коробки:

Но для Behat нужно сделать быстрый запуск с параметром --init, чтобы все настроить:

Первая команда создала новый класс FeatureContext, где мы можем написать определения шагов, необходимые для наших функций:

Написание нашей первой функции

Наша первая функция будет очень простой: мы просто убедимся, что наша новая установка Laravel приветствует нас на главной странице. Я добавил довольно глупый Given шаг вместе с Given I am logged in,  что показывает, насколько легко взаимодействовать с Laravel в наших функциях.

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

Идем дальше и создаем файл welcome.feature и помещаем его в features/functional:

Поместив функциональные методы в каталог functional, позже нам будет легче управлять нашими наборами. Мы не хотим чтобы интеграционному набору тестов, которые не требуют использования Laravel, пришлось ждать медленного функционального набора.

Мне нравится держать вещи красивыми и чистыми, поэтому я считаю, что у нас должен быть специальный контекст функции для нашего функционального пакета, который может дать нам доступ к Laravel. Вы можете просто скопировать существующий файл FeatureContext и изменить имя класса на LaravelFeatureContext. Для этого нам также нужен файл конфигурации behat.yml.

Создайте его в корневом каталоге проекта и добавьте следующее:

Я думаю, что YAML здесь очень понятен. Наш функциональный пакет будет искать функции в каталоге functional и запускать их через LaravelFeatureContext.

Если мы попытаемся запустить Behat в этот момент, он укажет нам реализовать необходимые определения шагов. Мы можем заставить Behat добавить пустые методы заглушки в LaravelFeatureContext с помощью следующей команды:

И теперь, как вы можете видеть из вывода, мы готовы начать выполнение первого из наших шагов: Given I am logged in.

Тестовый кейс PHPUnit, поставляемый с Laravel, позволяет нам делать такие вещи, как $this->be($ user), что позволяет залогинить определенного пользователя. В конечном счете, мы хотим иметь возможность взаимодействовать с Laravel, как если бы мы использовали PHPUnit, поэтому давайте продолжим и напишем код определения шага «we wish we had»:

Конечно, это не сработает, так как Behat понятия не имеет о том, что касается Laravel, но я покажу вам, как легко заставить Behat и Laravel работать вместе.

Если вы посмотрите в исходном коде Laravel и найдите класс Illuminate\Foundation\Testing\TestCase, который является классом, из которого наследуется тестовый пример по умолчанию, вы увидите, что, начиная с Laravel 4.2, все перемещено в трейт. ApplicationTrait теперь отвечает за загрузку экземпляра Application, настройку HTTP-клиента и предоставление нам нескольких вспомогательных методов, таких как be().

Это довольно круто, главным образом потому, что это означает, что мы можем просто добавить этот трейт в наши контексты Behat. У нас также есть доступ к AssertionsTrait, но он все еще привязан к PHPUnit.

Когда мы добавляем трейт, нам нужно сделать две вещи. Нам нужно иметь метод setUp(), как тот, который находится в классе Illuminate\Foundation\Testing\TestCase, и нам нужен метод createApplication(), как тот, который используется в тестовом кейсе Laravel по умолчанию. Фактически мы можем просто скопировать эти два метода и использовать их напрямую.

Следует заметить только одно: в PHPUnit метод setUp() будет автоматически вызываться перед каждым тестом. Чтобы достичь этого в Behat, мы можем использовать аннотацию @BeforeScenario.

Добавьте в свой LaravelFeatureContext следующее:

Довольно легко, и посмотрим, что получится, когда мы запустим Behat:

Зеленый первый шаг, что означает, что наша установка работает!

Затем мы можем реализовать шаг When I visit. Это очень просто, и мы можем просто использовать метод call(), который предоставляет ApplicationTrait. Одна строка кода доставит нас туда:

Последний шаг: Then I should see, занимает немного больше, и нам нужно задействовать две зависимости. Для утверждения нам понадобится PHPUnit, и нам понадобится Symfony DomCrawler для поиска текста "You have arrived".

Мы можем реализовать это так:

Это почти тот же код, как если бы вы использовали PHPUnit. Часть filterXpath() немного запутанна, и мы не будем беспокоиться об этом сейчас, так как она немного выходит за рамки этой статьи. Просто доверьтесь мне, что это работает.

И наконец мы запускаем Behat - хорошая новость:

Функция работает так, как ожидалось, и мы видим приветствие.

Вывод

Теперь полный LaravelFeatureContext должен выглядеть примерно так:

Теперь у нас есть действительно хорошая основа для развития, поскольку мы продолжаем разработку нашего нового приложения Laravel с использованием BDD. Надеюсь, я доказал вам, как легко заставить Laravel и Behat вместе работать. 

В этой первой статье мы затронули множество разных тем. Не нужно волноваться, мы будем более подробно рассматривать их, поскольку эта серия статей продолжается. Если у вас есть какие-либо вопросы или предложения, оставьте свой комментарий.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.