Behat BDD, FUNCTIONAL TESTS & SELENIUM (IN DRUPAL!) s Hallo! - - PowerPoint PPT Presentation

behat
SMART_READER_LITE
LIVE PREVIEW

Behat BDD, FUNCTIONAL TESTS & SELENIUM (IN DRUPAL!) s Hallo! - - PowerPoint PPT Presentation

Behat BDD, FUNCTIONAL TESTS & SELENIUM (IN DRUPAL!) s Hallo! > Lead of the Symfony documentation team > KnpLabs US - Symfony consulting, training & kumbaya > Writer for KnpUniversity.com: PHP & Symfony


slide-1
SLIDE 1

Behat

BDD, FUNCTIONAL TESTS & SELENIUM (IN DRUPAL!)

♥’s

slide-2
SLIDE 2

> Lead of the Symfony documentation team
 > KnpLabs US - Symfony consulting, training & kumbaya > Writer for KnpUniversity.com:

PHP & Symfony screencasts packed with puns, unrelated (but entertaining) illustrations and coding challenges!

> Husband of the much more talented @leannapelham

knpuniversity.com twitter.com/weaverryan

Hallo!

slide-3
SLIDE 3

Plan, Work, Miscommunicate, Panic, Put out Fires, Repeat!

aka Project Work!

slide-4
SLIDE 4

How the customer explained it

http://www.projectcartoon.com

slide-5
SLIDE 5

How the project leader understood it

http://www.projectcartoon.com

slide-6
SLIDE 6

How the programmer wrote it

http://www.projectcartoon.com

slide-7
SLIDE 7

What the customer really needed

http://www.projectcartoon.com

slide-8
SLIDE 8

What the beta testers received

http://www.projectcartoon.com

slide-9
SLIDE 9

Computer Science?

https://www.flickr.com/photos/diueine/3604050776

slide-10
SLIDE 10

Different roles, different languages, miscommunication

@weaverryan

One

slide-11
SLIDE 11

@weaverryan

Two

Your code and business values may not align

slide-12
SLIDE 12

I've just dreamt up this cool new feature that we should implement! Why? Because it's cool!

slide-13
SLIDE 13

@weaverryan

Three

Over-planning, under-planning, planning...?

slide-14
SLIDE 14 https://www.flickr.com/photos/tambako/4175456498

Getting down with BDD

slide-15
SLIDE 15

Evolution of Test-Driven Development

@weaverryan

slide-16
SLIDE 16

“Behaviour” is a more useful word, than “test”

  • Dan North *

* the santa of behavior-driven development

slide-17
SLIDE 17

@weaverryan

Evolution of Test-Driven Development

≈ Unit Tests ≈ Functional Tests

slide-18
SLIDE 18

Specification BDD

http://www.phpspec.net

@weaverryan

slide-19
SLIDE 19

Scenario-oriented BDD

(Story BDD)

slide-20
SLIDE 20

@weaverryan

Let’s create a single vocabulary and process

Project Managers Developers QA Business Analyst Product Owners

slide-21
SLIDE 21

@weaverryan

  • 1. Define business value for the features

  • 2. Prioritize features by their business

value


  • 3. Describe them with readable scenarios

  • 4. And only then - implement them

Calming the Chaos

slide-22
SLIDE 22

Gherkin

slide-23
SLIDE 23

@weaverryan

Gherkin == a structured language to describe a feature

slide-24
SLIDE 24

Feature: {custom_title} In order to {A} As a {B} I need to {C}

  • {A} - the benefit or value of the feature
  • {B} - the role (or person) who will benefit
  • {C} - short feature description

| The person “writing” this feature - the “I”

slide-25
SLIDE 25

@weaverryan

  • 1. Define business value for the features

  • 2. Prioritize features by their business

value


  • 3. Describe them with readable scenarios

  • 4. And only then - implement them

Calming the Chaos

slide-26
SLIDE 26

Feature: I18n In order to read news in french As a french user I need to be able to switch locale

Read news in French

@weaverryan

slide-27
SLIDE 27

Feature: I18n In order to read news in french As a french user I need to be able to switch locale

The business value

Read news in French

@weaverryan

slide-28
SLIDE 28

Feature: I18n In order to read news in french As a french user I need to be able to switch locale

The person who benefits

+

The “author” of this feature

Read news in French

@weaverryan

slide-29
SLIDE 29

Feature: I18n In order to read news in french As a french user I need to be able to switch locale

Description of the feature, the action the person will take

Read news in French

@weaverryan

slide-30
SLIDE 30
  • 1. Define business value for the features

  • 2. Prioritize features by their business

value


  • 3. Describe them with readable scenarios

  • 4. And only then - implement them

@weaverryan

Calming the Chaos

slide-31
SLIDE 31

Prioritize...

1) Feature: News admin panel 2) Feature: I18n 3) Feature: News list API

slide-32
SLIDE 32

Solution

  • 1. Define business value for the features

  • 2. Prioritize features by their business

value


  • 3. Describe them with readable scenarios

  • 4. And only then - implement them

@weaverryan

slide-33
SLIDE 33

Feature: News admin panel In order to maintain a list of news As a site administrator I need to be able to edit news Scenario: Add new article Given I am on the "/admin/news" page When I click "New Article" And I fill in "Title" with "Learned BDD" And I press "Save" Then I should see "A new article was added"

slide-34
SLIDE 34

Scenarios

Given Defines the initial state of the system for the scenario

Scenario: Add new article Given I am on the "/admin/news" page When I click "New Article" And I fill in "Title" with "Learned BDD" And I press "Save" Then I should see "A new article was added"

slide-35
SLIDE 35

When

Describes the action taken by the person/role

Scenario: Add new article Given I am on the "/admin/news" page When I click "New Article" And I fill in "Title" with "Learned BDD" And I press "Save" Then I should see "A new article was added"

Scenarios

slide-36
SLIDE 36

Then Describes the observable system state after the action has been performed

Scenario: Add new article Given I am on the "/admin/news" page When I click "New Article" And I fill in "Title" with "Learned BDD" And I press "Save" Then I should see "A new article was added"

Scenarios

slide-37
SLIDE 37

And/But Can be added to create multiple Given/When/Then lines

Scenario: Add new article Given I am on the "/admin/news" page When I click "New Article" And I fill in "Title" with "Learned BDD" And I press "Save" Then I should see "A new article was added"

Scenarios

slide-38
SLIDE 38

Example #2

Scenario: List available articles Given there are 5 news articles And I am on the "/admin" page When I click "News Administration" Then I should see 5 news articles

slide-39
SLIDE 39

Gherkin gives us a consistent language for describing features and their scenarios

@weaverryan

slide-40
SLIDE 40

... now let’s turn them into tests!

slide-41
SLIDE 41

http://bit.ly/behatch-t

slide-42
SLIDE 42

@weaverryan

What is Behat?

Behat does one simple thing: ** each line in a scenario is called a “step” Behat “executes” your scenarios, reading each step and calling the function associated with it It maps each step** to a PHP Callback

slide-43
SLIDE 43

Installing Behat Behat is just a library that can be installed easily in any project via Composer

New to Composer? Free screencast cures it! KnpUniversity.com/screencast/composer

slide-44
SLIDE 44

In your project directory...

1) Download Composer

$> curl -s http://getcomposer.org/installer | php

2) Create (or update) composer.json for Behat

$> php composer.phar require --dev behat/behat

slide-45
SLIDE 45

{ “require-dev": { "behat/behat": "^3.1" } }

bit.ly/behat3-composer

slide-46
SLIDE 46

The most important product of the installation is an executable vendor/bin/behat file

slide-47
SLIDE 47
slide-48
SLIDE 48

To use Behat in a project you need:

1) Actual *.feature files to be executed


2) A FeatureContext.php file that holds the PHP callbacks for each step
 3) (optional) A behat.yml configuration file

@weaverryan

slide-49
SLIDE 49

$> php vendor/bin/behat --init

slide-50
SLIDE 50

<?php // features/bootstrap/FeatureContext.php
 
 use Behat\Behat\Context\SnippetAcceptingContext;
 use Behat\Gherkin\Node\PyStringNode;
 use Behat\Gherkin\Node\TableNode;
 
 /**
 * Behat context class.
 */


class FeatureContext implements SnippetAcceptingContext


{
 }


slide-51
SLIDE 51

<?php // features/bootstrap/FeatureContext.php
 
 use Behat\Behat\Context\SnippetAcceptingContext;
 use Behat\Gherkin\Node\PyStringNode;
 use Behat\Gherkin\Node\TableNode;
 
 /**
 * Behat context class.
 */


class FeatureContext implements SnippetAcceptingContext


{
 }


slide-52
SLIDE 52

Pretend you’re testing the “ls” program

slide-53
SLIDE 53

1) Describe your Feature

Feature: ls

features/ls.feature

In order to see the directory structure As a UNIX user I need to be able to list the current directory's contents

slide-54
SLIDE 54

2) Your First Scenario

If you have two files in a directory, and you're running the command - you should see them listed.

slide-55
SLIDE 55

Scenario: List 2 files in a directory Write in the natural voice of “a UNIX user” Given I have a file named "foo" And I have a file named "bar" When I run "ls" Then I should see "foo" in the output And I should see "bar" in the output

features/ls.feature

slide-56
SLIDE 56

3) Run Behat

$> php vendor/bin/behat

slide-57
SLIDE 57

Behat tries to find a method in FeatureContext for each step

slide-58
SLIDE 58

Matching is done with simple wildcards

For each step that doesn’t have a matching method, Behat prints code to copy into FeatureContext

slide-59
SLIDE 59

class FeatureContext extends BehatContext { /** @Given I have a file named :file */
 public function iHaveAFileNamed($file)
 {
 throw new PendingException();
 }
 
 /** @When I run :command */
 public function iRun($command)
 {
 throw new PendingException();
 } // ... }

4) Copy in the new Definitions

Quoted text maps to a method argument

slide-60
SLIDE 60

5) Make the definitions do what they need to

slide-61
SLIDE 61

/** * @Given I have a file named :file */ public function iHaveAFileNamed($file) { touch($file); } /** * @Given I have a directory named :dir */ public function iHaveADirectoryNamed($dir) { mkdir($dir); }

slide-62
SLIDE 62

/** * @When I run :command */ public function iRun($command) { exec($command, $output); $this->output = trim(implode("\n", $output)); } /** * @Then I should see :string in the output */ public function iShouldSeeInTheOutput($string) { if (strpos($this->output, $string) === false) { throw new \Exception(‘Did not see’.$string); ); }

slide-63
SLIDE 63
slide-64
SLIDE 64
slide-65
SLIDE 65

See the full FeatureContext class: http://bit.ly/behat-ls-feature

slide-66
SLIDE 66

Scenario Step Definition Given I have a file named “foo” pattern public function iHaveAFileNamed($file) { do work Pass/Fail: Each step is a “test”, which passes *unless* an exception is thrown touch($file); @Given I have a file named :file

What Behat *does*

slide-67
SLIDE 67

Creating files and directories in FeatureContext is nice...

slide-68
SLIDE 68

but wouldn’t it be really cool to command a browser, fill out forms and check the output?

slide-69
SLIDE 69

Mink

https://www.flickr.com/photos/15016964@N02/5696367600

slide-70
SLIDE 70

Mink!

http://mink.behat.org/

  • A standalone library to use PHP to 


command a “browser”


  • One easy API that can be used to 


command Selenium, Goutte, 
 PhantomJS, etc

@weaverryan

slide-71
SLIDE 71

A sample of Mink

slide-72
SLIDE 72

use Behat\Mink\Driver\GoutteDriver; use Behat\Mink\Session; // change *only* this line to run // in Selenium, etc $driver = new GoutteDriver(); $session = new Session($driver);

slide-73
SLIDE 73

// visit a page $session->visit('http://behat.org'); echo 'URL : '.$session->getCurrentUrl(); echo 'Status: '.$session->getStatusCode();

slide-74
SLIDE 74

$page = $session->getPage(); // drill down into the page $ele = $page->find('css', 'li:nth-child(4) a'); echo 'Link text is: '.$ele->getText(); echo 'href is: '.$ele->getAttribute('href'); // click the link // (you can also fill out forms) $ele->click();

slide-75
SLIDE 75

Mink inside FeatureContext

=>

Dangerous Combo for Functional Testing

slide-76
SLIDE 76

http://mink.behat.org/

Behat Mink Integration

MinkExtension

  • An “Extension” is like a Behat plugin

  • The MinkExtension makes using Mink 


inside Behat a matter of configuration

@weaverryan

slide-77
SLIDE 77

Install Mink & MinkExtension

  • Update composer.json to include:


 > Mink > MinkExtension > Goutte and Selenium2 Drivers for Mink

@weaverryan

slide-78
SLIDE 78

composer require --dev \ behat/mink-extension \ behat/mink-goutte-driver \ behat/mink-selenium2-driver

slide-79
SLIDE 79

{ “require-dev": { "behat/behat": "^3.1", "behat/mink-extension": "^2.2", "behat/mink-goutte-driver": "^1.2", "behat/mink-selenium2-driver": "^1.3" } }

http://bit.ly/behat-mink-composer

slide-80
SLIDE 80

Goal: To easily use Mink inside FeatureContext

slide-81
SLIDE 81

Bootstrap MinkExtension

# behat.yml
 default:
 extensions:
 Behat\MinkExtension:
 goutte: ~
 selenium2: ~
 # The base URL you're testing
 base_url: http://en.wikipedia.org/

@weaverryan

slide-82
SLIDE 82

Extend MinkContext

use Behat\MinkExtension\Context\RawMinkContext;



 /**
 * Behat context class.
 */
 class FeatureContext extends RawMinkContext

@weaverryan

slide-83
SLIDE 83

Access to a Mink Session

class FeatureContext extends RawMinkContext { public function doSomething() { $session = $this->getSession(); $session->visit('http://behat.org'); } // ... }

Our custom definitions can now command a browser!

slide-84
SLIDE 84

More! Add MinkContext

# behat.yml
 default:
 extensions: # ... suites:
 default:
 contexts:


  • FeatureContext

  • Behat\MinkExtension\Context

\MinkContext


Behat now parses definitions from *our* class *and* this MinkContext class

slide-85
SLIDE 85

We inherit a pile of great definitions

the -dl option prints all current definitions Before adding MinkContext:

slide-86
SLIDE 86

After adding MinkContext:

slide-87
SLIDE 87

In other words: We can write some tests for

  • ur app without writing any

PHP code

@weaverryan

slide-88
SLIDE 88

Suppose we’re testing Wikipedia.org

slide-89
SLIDE 89

# features/wikipedia.feature Feature: Search In order to see a word definition As a website user I need to be able to search for a word

These 4 definitions all come packaged with MinkContext

Scenario: Searching for a page that does exist Given I am on "/wiki/Main_Page" When I fill in "search" with "Behavior Driven Development" And I press "searchButton" Then I should see "agile software development"

slide-90
SLIDE 90

Celebration!

slide-91
SLIDE 91

Behat in your application

slide-92
SLIDE 92

Behat in your App

https://www.flickr.com/photos/yoanngd/10669976224

slide-93
SLIDE 93

@weaverryan

Getting “under the hood”

  • Black-box testing: the site lives out on

the web

  • Because of this, we can’t:

a) access/clear/prepare the database b) use any code in our application

slide-94
SLIDE 94

When testing: you should guarantee the starting condition of your environment

slide-95
SLIDE 95

How can we add nodes, add users, and configure permissions from inside Behat?

slide-96
SLIDE 96
  • Install Behat & Mink

  • ??? Gain access to Drupal functionality

from inside FeatureContext

  • Create nodes, users, etc so that you’re

testing against a predictable dataset

@weaverryan

Behat & Drupal

  • PROFIT!
slide-97
SLIDE 97

... there’s a library made by the Drupal community ... Fortunately...

slide-98
SLIDE 98

... which I did not help with ...

slide-99
SLIDE 99

DrupalExtension!

http://bit.ly/drupal-extension

A plugin (extension) for Behat and Drupal

jhedstrom

slide-100
SLIDE 100

@weaverryan

DrupalExtension

2) Build nodes, add users, manage permissions inside Behat 3) Operating within Regions 4) Hooks to load more sentences/ definitions from contrib modules 1) Even more built-in sentences/definitions

slide-101
SLIDE 101

Background:

Given I am logged in as a user with the "administrator" role

Scenario: Edit Node

Given I am viewing a "page" with the title "Cool beans!"

When I click "Edit" in the "Body" region And I fill in the following: | Body | Ipsumm | And I press "Save" Then I should see "Ipsumm" in the "Body" region

# features/node_manage.feature

slide-102
SLIDE 102

# features/node_manage.feature

Background:

Given I am logged in as a user with the "administrator" role

Scenario: Edit Node

Given I am viewing a “page" with the title "Cool beans!"

When I click "Edit" in the "Body" region And I fill in the following: | Body | Ipsumm | And I press "Save" Then I should see "Ipsumm" in the "Body" region

Creates a user and adds a role to it

slide-103
SLIDE 103

Background:

Given I am logged in as a user with the "administrator" role

Scenario: Edit Node

Given I am viewing a "page" with the title "Cool beans!"

When I click "Edit" in the "Body" region And I fill in the following: | Body | Ipsumm | And I press "Save" Then I should see "Ipsumm" in the "Body" region

Creates a “page” node in the database

# features/node_manage.feature

slide-104
SLIDE 104

Background:

Given I am logged in as a user with the "administrator" role

Scenario: Edit Node

Given I am viewing a "page" with the title "Cool beans!"

When I click "Edit" in the "Body" region And I fill in the following: | Body | Ipsumm | And I press "Save" Then I should see "Ipsumm" in the "Body" region

Looks for the text in a CSS region you’ve defined as “Body”

# features/node_manage.feature

slide-105
SLIDE 105

And it’s alive!

slide-106
SLIDE 106

The 3 Modes of the DrupalExtension

1) blackbox: test an external server, no access to the database
 2) drupal: Bootstraps Drupal’s code and calls functions
 3) drush: Interacts with Drupal via drush

slide-107
SLIDE 107

What if my page/test rely

  • n JavaScript
slide-108
SLIDE 108

Behat/Mink does not support testing pages that use JavaScript

slide-109
SLIDE 109

jk!

slide-110
SLIDE 110

Add @javascript

# ... @javascript

Scenario: Edit Node

Given I am viewing a "page" with the title "Cool beans!"

When I click "Edit" in the "Body" region And I fill in the following: | Body | Ipsumm | And I press "Save" Then I should see "Ipsumm" in the "Body" region

slide-111
SLIDE 111

Add @javascript

# ... @javascript

Scenario: Edit Node

Given I am viewing a "page" with the title "Cool beans!"

When I click "Edit" in the "Body" region And I fill in the following: | Body | Ipsumm | And I press "Save" Then I should see "Ipsumm" in the "Body" region

Yep, that’s all you do!

slide-112
SLIDE 112

Download and start Selenium

$> wget http://selenium- release.storage.googleapis.com/2.53/selenium- server-standalone-2.53.0.jar $> java -jar selenium-server-standalone-2.53.0.jar

slide-113
SLIDE 113

Re-run the tests

slide-114
SLIDE 114

Yes, add only 1 line of code to run a test in Selenium

slide-115
SLIDE 115

Bonus!

Mink directly via PHPUnit? See BrowserTestBase **and (the new) JavascriptTestBase

@weaverryan

slide-116
SLIDE 116

It’s Simple!

https://www.flickr.com/photos/dtelegraph/5907116936

slide-117
SLIDE 117

1) Install Behat

http://knpuniversity.com/screencast/behat

slide-118
SLIDE 118

... and learn more about what you can do with Mink: http://mink.behat.org/

2) Write features for your app!

slide-119
SLIDE 119

3) high-five your teammates

https://www.flickr.com/photos/nickwebb/3904325807

slide-120
SLIDE 120

Ryan Weaver @weaverryan

THANK YOU!