Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Behat - BDD for PHP

Gasol Wu
November 03, 2012

Behat - BDD for PHP

Gasol Wu

November 03, 2012
Tweet

More Decks by Gasol Wu

Other Decks in Programming

Transcript

  1. Behat - BDD for PHP 2012/11/03 Gasol Wu @ PHPConf

    Taiwan 12年11月3⽇日星期六
  2. Agenda • Introduction to BDD • Gherkin Syntax • Behat

    by example • Demo 12年11月3⽇日星期六
  3. BDD • BDD ~= TDD + DDD • Specification as

    Ubiquitous Language • Colloboration between developers and non-techies • “outside-in” methodology driven by business value 12年11月3⽇日星期六
  4. Writing tests is Hard • Where to start • What

    to test and what not to test • How much to test in one go • What to call their tests • How to understand why a test fails 12年11月3⽇日星期六
  5. • Starts at outside by identifying business outcomes • Then

    drills down into the feature set • Each feature is captured as a “story” 12年11月3⽇日星期六
  6. In order to see the directory structure As a UNIX

    user I need to be able to list the current directory's contents Feature: List directory contents 12年11月3⽇日星期六
  7. In order to [meet some goal] As a [role] I

    need/want [a feature] 12年11月3⽇日星期六
  8. Scenario: List 2 files in a directory Given I am

    in a directory "test" And I have a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ 12年11月3⽇日星期六
  9. Given I am in a directory "test" And I have

    a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ 12年11月3⽇日星期六
  10. Given I am in a directory "test" And I have

    a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ Context 12年11月3⽇日星期六
  11. Given (Context) Given there are no users on site Given

    the database is clean Given I am logged in as "Everzet" 12年11月3⽇日星期六
  12. Given I am in a directory "test" And I have

    a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ Context 12年11月3⽇日星期六
  13. Given I am in a directory "test" And I have

    a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ Context Event(s) 12年11月3⽇日星期六
  14. When (Event) When I am on "/some/page" When I fill

    "username" with "everzet" When I fill "password" with "123456" When I press "login" When I call "ls -la" 12年11月3⽇日星期六
  15. Given I am in a directory "test" And I have

    a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ Context Event(s) 12年11月3⽇日星期六
  16. Given I am in a directory "test" And I have

    a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ Context Event(s) Outcome(s) 12年11月3⽇日星期六
  17. Then (Outcome) Then the output should be "hello" Then I

    see something But I don't see something else 12年11月3⽇日星期六
  18. Feature: ls In order to see the directory structure As

    a UNIX user I need to be able to list the current directory's contents Scenario: List 2 files in a directory Given I am in a directory "test" And I have a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ 12年11月3⽇日星期六
  19. Feature: ls In order to see the directory structure As

    a UNIX user I need to be able to list the current directory's contents Scenario: List 2 files in a directory Given I am in a directory "test" And I have a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ 12年11月3⽇日星期六
  20. Gherkin • business-readable DSL for BDD • Spoken 37+ languages,

    including Chinese • .feature extension • line-oriented language 12年11月3⽇日星期六
  21. https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json # language: en Scenario: Regular numbers Given I have

    entered 3 into the calculator And I have entered 2 into the calculator When I press divide Then the result should be 1.5 on the screen # language: de Szenario: Normale Zahlen Gegeben sei ich habe 3 in den Taschenrechner eingegeben Und ich habe 2 in den Taschenrechner eingegeben Wenn ich divide drücke Dann sollte das Ergebniss auf dem Bildschirm 1.5 sein # language: zh-TW 場景: 將兩個數相除 假設我已經在計算機上輸⼊入 3 ⽽而且我已經在計算機上輸⼊入 2 當我按下 divide 那麼螢幕上應該顯⽰示 1.5 # language: ja シナリオ: ふつうの数値 前提 3 を⼊入⼒力 かつ 2 を⼊入⼒力 もし divide を押した ならば 1.5 を表⽰示 12年11月3⽇日星期六
  22. • Inspired by Ruby’s Cucumber • know Gherken • PHP

    5.3+ • Annotation 12年11月3⽇日星期六
  23. “Overall I’ve been really impressed with Behat. I would never

    have imagined that Behat and Mink were going to even compare to Cucumber and Capybara, but it does!!” Brett, Lead Web Developer at BBC 12年11月3⽇日星期六
  24. 1 <?php 2 3 class FeatureContext extends BehatContext 4 {

    5 public function __construct(array $parameters) 6 { 7 // Initialize your context here 8 } 9 10 // 11 // Place your definition and hook methods here: 12 // 13 // /** 14 // * @Given /^I have done something with "([^"]*)"$/ 15 // */ 16 // public function iHaveDoneSomethingWith($argument) 17 // { 18 // doSomethingWith($argument); 19 // } 20 // 21 } 12年11月3⽇日星期六
  25. ls.feature 1 Feature: ls 2 In order to see the

    directory structure 3 As a UNIX user 4 I need to be able to list the current directory's contents 5 6 Scenario: List 2 files in a directory 7 Given I am in a directory "test" 8 And I have a file named "foo" 9 And I have a file named "bar" 10 When I run "ls" 11 Then I should get: 12 """ 13 bar 14 foo 15 """ 12年11月3⽇日星期六
  26. Feature: ls In order to see the directory structure As

    a UNIX user I need to be able to list the current directory's contents Scenario: List 2 files in a directory # features/ls.feature:6 Given I am in a directory "test" And I have a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ 1 scenario (1 undefined) 5 steps (5 undefined) 0m0.019s 12年11月3⽇日星期六
  27. You can implement step definitions for undefined steps with these

    snippets: /** * @Given /^I am in a directory "([^"]*)"$/ */ public function iAmInADirectory($arg1) { throw new PendingException(); } /** * @Then /^I should get:$/ */ public function iShouldGet(PyStringNode $string) { throw new PendingException(); } 12年11月3⽇日星期六
  28. Feature: ls In order to see the directory structure As

    a UNIX user I need to be able to list the current directory's contents Scenario: List 2 files in a directory # features/ls.feature:6 Given I am in a directory "test" # FeatureContext::iAmInADirectory() TODO: write pending definition And I have a file named "foo" # FeatureContext::iHaveAFileNamed() And I have a file named "bar" # FeatureContext::iHaveAFileNamed() When I run "ls" # FeatureContext::iRun() Then I should get: # FeatureContext::iShouldGet() """ bar foo """ 1 scenario (1 pending) 5 steps (4 skipped, 1 pending) 0m0.018s 12年11月3⽇日星期六
  29. FeatureContext::iAmInADirectory() 37 /** 38 * @Given /^I am in a

    directory "([^"]*)"$/ 39 */ 40 public function iAmInADirectory($dir) 41 { 42 $tmpFile = tempnam(sys_get_temp_dir(), '.placeholder'); 43 $tmpDir = dirname($tmpFile) . "/$dir"; 44 $this->dir = $tmpDir; 45 46 if (!file_exists($tmpDir)) { 47 mkdir($tmpDir); 48 } 49 50 chdir($tmpDir); 51 } 12年11月3⽇日星期六
  30. FeatureContext::iHaveAFileNamed() 53 /** 54 * @Given /^I have a file

    named "([^"]*)"$/ 55 */ 56 public function iHaveAFileNamed($file) 57 { 58 touch($this->dir . "/$file"); 59 } 12年11月3⽇日星期六
  31. FeatureContext::iRun() 61 /** 62 * @When /^I run "([^"]*)"$/ 63

    */ 64 public function iRun($command) 65 { 66 exec($command, $output); 67 $this->output = trim(implode("\n", $output)); 68 } 12年11月3⽇日星期六
  32. FeatureContext::iShouldGet 70 /** 71 * @Then /^I should get:$/ 72

    */ 73 public function iShouldGet(PyStringNode $string) 74 { 75 if (strval($string) !== $this->output) { 76 throw new Exception("Actual output is: \n". $this->output); 77 } 78 } 12年11月3⽇日星期六
  33. $ behat Feature: ls In order to see the directory

    structure As a UNIX user I need to be able to list the current directory's contents Scenario: List 2 files in a directory Given I am in a directory "test" And I have a file named "foo" And I have a file named "bar" When I run "ls" Then I should get: """ bar foo """ 1 scenario (1 passed) 5 steps (5 passed) 0m0.03s 12年11月3⽇日星期六
  34. Tags @billing Feature: Verify billing @important Scenario: Missing product description

    @bicker @annoy Scenario: Several products Only execute the features or scenarios with tags matching tag filter expression 12年11月3⽇日星期六
  35. Tables Scenario: Given the following people exist: | name |

    email | phone | | Aslak | [email protected] | 123 | | Joe | [email protected] | 234 | | Bryan | [email protected] | 456 | 12年11月3⽇日星期六
  36. Tables (code) /** * @Given /the following people exist:/ */

    public function thePeopleExist(TableNode $table) { $hash = $table->getHash(); foreach ($hash as $row) { // $row['name'], $row['email'], $row['phone'] } } 12年11月3⽇日星期六
  37. Placeholder Scenario Outline: controlling order Given there are <start> cucumbers

    When I eat <eat> cucumbers Then I should have <left> cucumbers Examples: | start | eat | left | | 12 | 5 | 7 | | 5 | 3 | 2 | 12年11月3⽇日星期六
  38. Behat Extension • Mink - Web acceptance testing • Phabric

    - A DB mockup / fixture creation • Symfony2 - Integration for Symfony • Behatch - provides most common context http://extensions.behat.org/ 12年11月3⽇日星期六