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

6,569 views

Published on

Published in: Technology
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,569
On SlideShare
0
From Embeds
0
Number of Embeds
1,385
Actions
Shares
0
Downloads
27
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

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

  1. 1. BDD в PHPс использованием Behat и Mink
  2. 2. About me• Symfony developer at KnpLabs• twitter: @tyomo4ka• GitHub: tyomo4ka
  3. 3. Happy Awesome Developers
  4. 4. Agenda• BDD• Gherkin DSL• Behat• Mink• BDD workflow
  5. 5. Зачем тестировать?• Безопасный рефакторинг• Отсутствие регрессий• Более качеcтвенная архитектура• Уменьшение числа багов• Степень зрелости разработчика?
  6. 6. Behavior Driven Development
  7. 7. TDD• TDD не очень удачое название• Если мы пишем тесты перед кодом, мы все равно думаем об архитектуре• Design Driven Development?
  8. 8. TDD и BDD• Также пишем тесты перед кодом• При TDD мы фиксируем в тестах архитектуру приложения или его частей• При BDD мы фиксируем в тестах поведение приложения или его частей• Описательная часть: спецификация или пользовательские сценарии
  9. 9. Spec BDD• Добавляем описательную часть к тестам• Получаем не тесты, а спецификации объектов• Тестирование системы изнутри• Используем вместо юнит тестов и интеграционых тестов
  10. 10. Story (Scenario) BDD• Вместо тестов описываем шаги, которые нужно выполнить для достижения определнного результата• Шаги должны легко читаться, в идеале это должны быть простые предложения• Тестирование системы снаружи• Замена функциональным тестам
  11. 11. Gherkin DSL
  12. 12. 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"
  13. 13. Feature: Название функционала In order to ... Ценность функционала As a ... Выгодополучатель I need ... Краткое описание функционала Background: Given ... Начальное состояние системы Scenario: Название сценария Given ... Начальное состояние And ... Начальное состояние When ... Выполняем шаг And ... Выполняем шаг Then ... Проверяем результат And ... Проверяем результат
  14. 14. Behat
  15. 15. Зачем?• A php framework for testing your business expectations
  16. 16. Установка• PHP 5.3• Composer• PHAR• Git
  17. 17. Инициализация• behat --init• features/ directory• features/bootstrap/ directory• features/bootstrap/*Context.php• behat.yml
  18. 18. features/*.feature• Gherkin DSL• behat --story-syntax --lang=LANG
  19. 19. [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 Ks 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 |
  20. 20. 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
  21. 21. Context• POPO• Описание шагов• Хуки• Subcontexts• Closures для описания шагов и хуков
  22. 22.        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());        }
  23. 23. Steps definition• @Given, @When, @Then• Если шаг не выбросил исключение, значит он завершился успешно• Нет своих асершенов, но легко можно использовать асершены из PHPUnit
  24. 24.        /**          *  @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(KnpBundleKnpBundlesBundleEntityKeyword) -­‐>findOrCreateOne($row[keyword]);                                $bundle-­‐>addKeyword($keyword);                                $entityManager-­‐>persist($bundle);                        }                }                $entityManager-­‐>flush();        }
  25. 25. Hooks• BeforeStep/AfterStep• BeforeScenario/AfterScenario• BeforeFeature/AfterFeature• BeforeSuite/AfterSuite• Hooks can be tagged
  26. 26.        /**          *  @BeforeScenario          *          *  @return  null          */        public  function  buildSchema($event)        {                $metadata  =  $this-­‐>getMetadata();                if  (!empty($metadata))  {                        $tool  =  new  SchemaTool($this-­‐>getEntityManager());                        $tool-­‐>dropSchema($metadata);                        $tool-­‐>createSchema($metadata);                }        }
  27. 27. TableNode• getRows• getHash• getRowsHash• getRowLines• getRowAsString• getNumeratedRows
  28. 28. 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]    }}
  29. 29. PyStringNode• Опеределение длинного теста в несколько строчек
  30. 30. 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());}
  31. 31. Backgrounds• Общие шаги для всех сценариев• Позволяется избавиться от дублирования шагов в каждом сценарии
  32. 32.    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            |
  33. 33. MetaSteps• Объединяем несколько шагов в один• Помогает избавиться от дублирования шагов• Тесты запускаются по цепочке• Возвращаем массив состоящий из шагов, которые необходимо выполнить
  34. 34. /** * @Given /I entered "([^"]*)" and expect "([^"]*)"/ */public function complexStep($number, $result){    return array(        new StepGiven("I have entered "$number""),        new StepWhen("I press +"),        new StepThen("I should see "$result" on the screen")    );}
  35. 35. ScenarioOutlines• Помогает избавиться от дублирования сценариев• Предоставляет удобный интерфейс для описания набора тестов и ожидаемых результатов
  36. 36. 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 |
  37. 37. Tags• Тэги в сценариях• Тэги в хуках• behat --tags "@orm,@database"• behat --tags "@orm&&@database"• beaht --tags "-@database"
  38. 38. Запуск сценариев• behat features/• behat features/single.feature• behat features/single.feature:10-20• behat --name=”Feature name”• behat --tags @tag1,@tag2• behat --profile test
  39. 39. Profiles• Настройки форматтеров• Настройка контекстов• Настройки тэгов• Настройки экстеншенов• Настройка путей к файлам
  40. 40. # behat.ymldefault:    context:        class: YourCustomContextwip:    filters:        tags: "@wip"    formatter:        name: progressci:    formatter:        name: junit        parameters:            output_path: /var/tmp/junit
  41. 41. Система экстеншенов• Mink Extension• Symfony2 Extension• Behatch Extension• Doctrine DataFixtures Extension• Gearman Extension• Write your own
  42. 42. Mink
  43. 43. Зачем?• Слой абстракции для использования различных эмуляторов браузера• Приемочное тестирование web- приложений
  44. 44. Установка• PHP 5.3• Composer• PHAR• Git
  45. 45. Drivers• Goutte• Zombie• Selenium• Selenium2• Sahi
  46. 46. Session• Через сессию можно получить доступ к остальным объектам: страница, статус код, куки, заголовки и т. д.• Несколько сессий запущенных одновременно
  47. 47. Selectors• Named• CSS• XPath• find*• Traversing
  48. 48. NodeElement• Можем манипулировать элементом найденным по одному из селекторов• Посмотреть аттрибуты, текст• Эмулировать события браузера• Манипулировать элеметами формы, ввести текст в инпут, выбрать чекбокс, прикрепить файл и т. д.
  49. 49. Mink + Behat• Mink Extension for Behat• Mink может быть использован отдельно от Behat• Минимум конфигурации
  50. 50. BDD workflow
  51. 51. • Обсуждение функционала• Составление User stories• Подготовка сценариев на Gherkin DSL• Пишем недостающие Step definitions• Пишем функционал, юнит тесты, и т. д.• Проверяем DoD
  52. 52. Спасибо за внимание!

×