behat в php с использованием behat и mink

Post on 29-Nov-2014

4.154 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

BDD в PHP с использованием

Behat и Mink

About me

• Symfony developer at KnpLabs

• twitter: @tyomo4ka

• GitHub: tyomo4ka

Happy Awesome Developers

Agenda

• BDD

• Gherkin DSL

• Behat

• Mink

• BDD workflow

Зачем тестировать?

• Безопасный рефакторинг• Отсутствие регрессий• Более качеcтвенная архитектура• Уменьшение числа багов• Степень зрелости разработчика?

Behavior Driven Development

TDD

• TDD не очень удачое название

• Если мы пишем тесты перед кодом, мы все равно думаем об архитектуре

• Design Driven Development?

TDD и BDD

• Также пишем тесты перед кодом

• При TDD мы фиксируем в тестах архитектуру приложения или его частей

• При BDD мы фиксируем в тестах поведение приложения или его частей

• Описательная часть: спецификация или пользовательские сценарии

Spec BDD

• Добавляем описательную часть к тестам

• Получаем не тесты, а спецификации объектов

• Тестирование системы изнутри

• Используем вместо юнит тестов и интеграционых тестов

Story (Scenario) BDD

• Вместо тестов описываем шаги, которые нужно выполнить для достижения определнного результата

• Шаги должны легко читаться, в идеале это должны быть простые предложения

• Тестирование системы снаружи

• Замена функциональным тестам

Gherkin DSL

Feature: Customer login In order to view protected data As a customer I need to be able to login

Background: Given customers are registered: | username | password | blocked | | active@user.com | password | no | | blocked@user.com | password | yes |

Scenario: Successful login Given I am on page "Login" When I fill in "Username" with "active@user.com" And I fill in "Password" with "password" And I press "Submit" Then I should be on page "Personal profile" And I should see "Successful login"

Feature: Название функционала In order to ... Ценность функционала As a ... Выгодополучатель I need ... Краткое описание функционала

Background: Given ... Начальное состояние системы

Scenario: Название сценария Given ... Начальное состояние And ... Начальное состояние When ... Выполняем шаг And ... Выполняем шаг Then ... Проверяем результат And ... Проверяем результат

Behat

Зачем?

• A php framework for testing your business expectations

Установка

• PHP 5.3

• Composer

• PHAR

• Git

Инициализация

• behat --init

• features/ directory

• features/bootstrap/ directory

• features/bootstrap/*Context.php

• behat.yml

features/*.feature

• Gherkin DSL

• behat --story-syntax --lang=LANG

[Feature|Business Need|Ability]: Internal operations In order to stay secret As a secret organization We need to be able to erase past agents' memory

Background: Given there is agent A And there is agent B

Scenario: Erasing agent memory Given there is agent J And there is agent K When I erase agent K's memory Then there should be agent J But there should not be agent K

[Scenario Outline|Scenario Template]: Erasing other agents' memory Given there is agent <agent1> And there is agent <agent2> When I erase agent <agent2>'s memory Then there should be agent <agent1> But there should not be agent <agent2>

[Examples|Scenarios]: | agent1 | agent2 | | D | M |

Feature:  Listing  developers    As  a  Visitor    I  want  to  browse  through  developers  list

   Background:        Given  the  site  has  following  users:        |  name            |        |  knplabs      |        |  fos              |        Given  the  site  has  following  bundles:        |  username    |  name              |  description  |  lastCommitAt  |  score  |  trend1  |        |  knplabs      |  TestBundle  |  test  desc      |-­‐1  day                |  10        |  15          |        |  fos              |  UserBundle  |  user  desc      |-­‐2  days              |  20        |  5            |

   Scenario:  Listing  developers        When  I  go  to  "/"        And  I  follow  "Developers"        Then  I  should  see  "2  developers  using  Symfony2"        And  I  should  see  "knplabs"  developer        And  I  should  see  "fos"  developer

Context

• POPO

• Описание шагов• Хуки• Subcontexts

• Closures для описания шагов и хуков

       public  function  __construct($kernel)        {                $this-­‐>useContext('symfony_doctrine',  new  SymfonyDoctrineContext());                $this-­‐>useContext('solr',  new  SolrContext());                $this-­‐>useContext('mink',  new  MinkContext());                $this-­‐>useContext('api',  new  ApiContext());        }

Steps definition

• @Given, @When, @Then

• Если шаг не выбросил исключение, значит он завершился успешно

• Нет своих асершенов, но легко можно использовать асершены из PHPUnit

       /**          *  @Given  /^the  bundles  have  following  keywords:$/          */        public  function  theBundlesHaveFollowingKeywords(TableNode  $table)        {                $entityManager  =  $this-­‐>getEntityManager();

               foreach  ($table-­‐>getHash()  as  $row)  {                        if  (isset($this-­‐>bundles[$row['bundle']]))  {                                $bundle  =  $this-­‐>bundles[$row['bundle']];                                $keyword  =  $entityManager

-­‐>getRepository('Knp\Bundle\KnpBundlesBundle\Entity\Keyword')-­‐>findOrCreateOne($row['keyword']);

                               $bundle-­‐>addKeyword($keyword);                                $entityManager-­‐>persist($bundle);                        }                }

               $entityManager-­‐>flush();        }

Hooks

• BeforeStep/AfterStep

• BeforeScenario/AfterScenario

• BeforeFeature/AfterFeature

• BeforeSuite/AfterSuite

• Hooks can be tagged

       /**          *  @BeforeScenario          *          *  @return  null          */        public  function  buildSchema($event)        {                $metadata  =  $this-­‐>getMetadata();

               if  (!empty($metadata))  {                        $tool  =  new  SchemaTool($this-­‐>getEntityManager());                        $tool-­‐>dropSchema($metadata);                        $tool-­‐>createSchema($metadata);                }        }

TableNode

• getRows

• getHash

• getRowsHash

• getRowLines

• getRowAsString

• getNumeratedRows

Scenario: Given the following people exist: | name | email | phone | | Aslak | aslak@email.com | 123 | | Joe | joe@email.com | 234 | | Bryan | bryan@email.org | 456 |

/** * @Given /the following people exist:/ */public function thePeopleExist(TableNode $table){    $hash = $table->getHash();    foreach ($hash as $row) {        // $row['name'], $row['email'], $row['phone']    }}

PyStringNode

• Опеределение длинного теста в несколько строчек

Scenario: Given a blog post named "Random" with: """ Some Title, Eh? =============== Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet, consectetur adipiscing elit. """

/** * @Given /a blog post named "([^"]+)" with:/ */public function blogPost($title, PyStringNode $markdown){    $this->createPost($title, $markdown->getRaw());}

Backgrounds

• Общие шаги для всех сценариев• Позволяется избавиться от дублирования шагов в каждом сценарии

   Background:        Given  the  site  has  following  users:        |  name            |        |  knplabs      |        |  fos              |        Given  the  site  has  following  bundles:        |  username    |  name              |  description  |  lastCommitAt  |  score  |  trend1  |        |  knplabs      |  TestBundle  |  test  desc      |-­‐1  day                |  10        |  15          |        |  fos              |  UserBundle  |  user  desc      |-­‐2  days              |  20        |  5            |

MetaSteps

• Объединяем несколько шагов в один

• Помогает избавиться от дублирования шагов

• Тесты запускаются по цепочке

• Возвращаем массив состоящий из шагов, которые необходимо выполнить

/** * @Given /I entered "([^"]*)" and expect "([^"]*)"/ */public function complexStep($number, $result){    return array(        new Step\Given("I have entered \"$number\""),        new Step\When("I press +"),        new Step\Then("I should see \"$result\" on the screen")    );}

ScenarioOutlines

• Помогает избавиться от дублирования сценариев

• Предоставляет удобный интерфейс для описания набора тестов и ожидаемых результатов

Scenario Outline: Given I have entered <number1> And I have entered <number2> When I add Then The result should be <result> Examples: | number1 | number2 | result | | 10 | 12 | 22 | | 5 | 3 | 8 | | 5 | 5 | 10 |

Tags

• Тэги в сценариях• Тэги в хуках• behat --tags "@orm,@database"

• behat --tags "@orm&&@database"

• beaht --tags "-@database"

Запуск сценариев

• behat features/

• behat features/single.feature

• behat features/single.feature:10-20

• behat --name=”Feature name”

• behat --tags @tag1,@tag2

• behat --profile test

Profiles

• Настройки форматтеров• Настройка контекстов• Настройки тэгов• Настройки экстеншенов• Настройка путей к файлам

# behat.ymldefault:    context:        class: Your\Custom\Contextwip:    filters:        tags: "@wip"    formatter:        name: progressci:    formatter:        name: junit        parameters:            output_path: /var/tmp/junit

Система экстеншенов

• Mink Extension

• Symfony2 Extension

• Behatch Extension

• Doctrine DataFixtures Extension

• Gearman Extension

• Write your own

Mink

Зачем?

• Слой абстракции для использования различных эмуляторов браузера

• Приемочное тестирование web-приложений

Установка

• PHP 5.3

• Composer

• PHAR

• Git

Drivers

• Goutte

• Zombie

• Selenium

• Selenium2

• Sahi

Session

• Через сессию можно получить доступ к остальным объектам: страница, статус код, куки, заголовки и т. д.

• Несколько сессий запущенных одновременно

Selectors

• Named

• CSS

• XPath

• find*

• Traversing

NodeElement

• Можем манипулировать элементом найденным по одному из селекторов

• Посмотреть аттрибуты, текст

• Эмулировать события браузера• Манипулировать элеметами формы, ввести текст в инпут, выбрать чекбокс, прикрепить файл и т. д.

Mink + Behat

• Mink Extension for Behat

• Mink может быть использован отдельно от Behat

• Минимум конфигурации

BDD workflow

• Обсуждение функционала

• Составление User stories

• Подготовка сценариев на Gherkin DSL

• Пишем недостающие Step definitions

• Пишем функционал, юнит тесты, и т. д.

• Проверяем DoD

Спасибо за внимание!

top related