SlideShare une entreprise Scribd logo
1  sur  63
Télécharger pour lire hors ligne
THE LEADER IN DRUPAL PLATFORM DESIGN AND DEVELOPMENT




Saturday, February 2, 13
TESTING DRUPAL WITH
                           GHOSTS AND GHERKINS
                              USING CASPERJS AND BEHAT TO TEST DRUPAL SITES




Saturday, February 2, 13
STEVEN MERRILL
                           Director of Engineering
                           smerrill@phase2technology.com
                           @stevenmerrill
                           https://github.com/smerrill




Saturday, February 2, 13
ABOUT ME
            • Fan of Jenkins and continuous integration

            • Running Jenkins in production for about 4 years




Saturday, February 2, 13
ABOUT THIS PRESENTATION
            • Originally titled "Testing Your Site With Friendly Ghosts"

            • Developed by Eric Duran and me

            • Thanks, Eric!




Saturday, February 2, 13
A TWITTER EXCHANGE
                           PEOPLE WANT TO TEST THEIR DRUPAL MODULES WITH REAL BROWSERS




Saturday, February 2, 13
“                    Is there precedent for including selenium tests in a
                           #drupal contrib module? #lazyweb




                                                                                  ”
                           @stevector




Saturday, February 2, 13
“                    @stevector https://github.com/ericduran/
                           views_load_more is a neat example of including
                           @casperjs_org tests and running them using @travisci.




                                                                                   ”
                           @stevenmerrill




Saturday, February 2, 13
“                    @stevenmerrill Thanks! That approach looks very viable
                           for the what I want to do (check for text in a CTools
                           modal).




                                                                                    ”
                           @stevector




Saturday, February 2, 13
YOU NEED TO TEST YOUR SITE

Saturday, February 2, 13
SIMPLETEST
            • Let's test complex AJAX in a real browser!




Saturday, February 2, 13
SIMPLETEST
Saturday, February 2, 13
SELENIUM
            • Let's add variables into a test that was recorded by clicking
              around the interface.




Saturday, February 2, 13
SELENIUM
Saturday, February 2, 13
FRIENDLY GHOSTS
            • Website testing tools based around headless WebKit.

            • PhantomJS (https://github.com/ariya/phantomjs)

            • CasperJS (https://github.com/n1k0/casperjs)




Saturday, February 2, 13
FRIENDLY GHOSTS
            • Headless website testing

            • Site scraping

            • Run QUnit




Saturday, February 2, 13
PHANTOMJS
            • Headless Webkit browser

            • Scriptable via a JavaScript API

                  • Write data to the filesystem

                  • Render <canvas> contents

            • Use JavaScript or CoffeeScript



Saturday, February 2, 13
WHY NOT PHANTOMJS?

Saturday, February 2, 13
var page = require('webpage').create();

                     page.open(url1, function(status) {
                         if (status == "fail") phantom.exit();
                         page.open(url2, function(status) {
                             if (status == "fail") phantom.exit();
                             page.open(url3, function(status) {
                                 if (status == "fail") phantom.exit();
                                 page.open(url4, function(status) {
                                     if (status == "fail") phantom.exit();
                                     // Can I stop, now?
                                 });
                             });
                         });
                     });




      PHANTOMJS
Saturday, February 2, 13
var casper = require('casper').create();

                     casper.start(url1);
                     casper.thenOpen(url2);
                     casper.thenOpen(url3);
                     casper.thenOpen(url4);

                     casper.run();




      CASPERJS
Saturday, February 2, 13
THE CASPERJS API
            •       Take actions through a website

            •       Clicking/following links

            •       Filling/submitting forms

            •       Downloading resources

            •       Capturing screenshots

            •       Running DOM assertions




Saturday, February 2, 13
// Search for 'casperjs' from google.com.
                     casper.start('http://google.com/', function() {
                       this.fill('form[action="/search"]',
                         { q: 'casperjs' }, true);});

                     // Search for a 'casperjs' module from d.o.
                     casper.start('http://drupal.org/', function() {
                       this.fill('#search-theme-form',
                         {search_theme_form: 'casperjs',
                           meta_type: 'module'}, true);});



      USING THE CASPERJS API
Saturday, February 2, 13
TESTING
            • You use JavaScript to build sites!

            • Test real JavaScript interactions.

            • Save screenshots or scraped data.

            • Export JUnit XML and hook into Jenkins.




Saturday, February 2, 13
TRAVIS + CASPER AUTOMATED TESTING
            • Host a mirror of your module on GitHub

                  • https://github.com/ericduran/views_load_more

            • Use TravisCI to automate your testing

                  • https://github.com/ericduran/views_load_more/blob/
                    7.x-1.x/.travis.yml

            • Write tests and update your README with the build status!




Saturday, February 2, 13
language: php

                     php:
                       - 5.4

                     mysql:
                       database: drupal
                       username: root
                       encoding: utf8

                     before_script:
                      - mysql -e 'create database drupal;'
                      - pyrus channel-discover pear.drush.org
                      - pyrus install drush/drush
                      - phpenv rehash




      TRAVIS.YML
Saturday, February 2, 13
- wget http://ftp.drupal.org/files/projects/drupal-7.14.tar.gz
                      - tar -xf drupal-7.14.tar.gz
                      - cd drupal-7.14
                      - drush site-install standard --db-url=mysql://root:@localhost/drupal
                     --yes
                      - git clone --quiet --branch casper-test git://github.com/ericduran/
                     views_load_more.git ./sites/all/modules/views_load_more
                      - drush en views_load_more_test --yes
                      - drush cc all --yes




      TRAVIS.YML
Saturday, February 2, 13
- "export PHANTOMJS_EXECUTABLE='phantomjs --local-to-remote-url-
                     access=yes --ignore-ssl-errors=yes'"
                      - "export DISPLAY=:99.0"
                      - "sh -e /etc/init.d/xvfb start"
                      - sleep 3 # give xvfb some time to start
                      - drush runserver --server=builtin 8080 &
                      - sleep 3 # give Web server some time to bind to sockets, etc
                      - cd ..
                      - git clone git://github.com/n1k0/casperjs.git
                      - cd casperjs
                      - git checkout tags/0.6.10
                      - cd ./bin

                     script:
                      - "DISPLAY=:99.0 ./casperjs test ../../test/casperjs/"




      TRAVIS.YML, CONT'D
Saturday, February 2, 13
DEMOS

Saturday, February 2, 13
INSTALLING PHANTOM AND CASPER
                     brew install phantomjs
                     brew install casperjs




Saturday, February 2, 13
PHANTOM/CASPER LINKS
            • http://phantomjs.org/

            • http://casperjs.org/index.html

            • https://github.com/ericduran/friendly-ghosts-examples




Saturday, February 2, 13
API DOCUMENTATION
            • Client Utilities: http://casperjs.org/api.html#client-utils

            • Testing API: http://casperjs.org/api.html#tester

            • Utils: http://casperjs.org/api.html#utils

            • CLI: http://casperjs.org/cli.html




Saturday, February 2, 13
BEHAVIORAL TESTING

Saturday, February 2, 13
BEHAT
            • Behavior driven development framework for PHP 5.3+

            • Uses Symfony components

            • Uses the Gherkin format for feature definitions




Saturday, February 2, 13
MINK
            • Browser testing for Behat

            • Has a pure PHP test browser (Goutte)

            • Can run Selenium or Selenium 2 tests

            • Can farm testing out to Sauce Labs




Saturday, February 2, 13
GHERKIN
            • Business-readable domain specific language

            • Features

            • Scenarios

            • Step Definitions




Saturday, February 2, 13
GHERKIN STEP DEFINITIONS
            •       Given

                  •        Preconditions

            •       When

                  •        Actions

            •       Then

                  •        Assertions




Saturday, February 2, 13
Feature: In order to learn about automated testing tools
              As a DrupalCamp New Jersey attendee
              I want to attend Testing Drupal with Ghosts and Gherkins

                   Scenario: Attending the session
                     Given that the time is 10:30 AM
                      When I enter room Friend 008
                      Then the presenter should be Steven Merrill
                       And the session should be Testing Drupal




      GHERKIN TEST
Saturday, February 2, 13
MINK STEP DEFINITIONS
                  • Navigate to pages

                  • Check HTTP status codes

                  • Fill in forms by label

                  • Click links

                  • Look for text



Saturday, February 2, 13
$ ./bin/behat -dl

       Given /^(?:|I )am on homepage$/
        When /^(?:|I )go to homepage$/
       Given /^(?:|I )am on "(?P<page>[^"]+)"$/
        When /^(?:|I )go to "(?P<page>[^"]+)"$/
        When /^(?:|I )reload the page$/
        When /^(?:|I )move backward one page$/
        When /^(?:|I )move forward one page$/
        When /^(?:|I )press "(?P<button>(?:[^"]|")*)"$/
        When /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/
        When /^(?:|I )fill in "(?P<field>(?:[^"]|")*)"
          with "(?P<value>(?:[^"]|")*)"$/
        When /^(?:|I )fill in "(?P<value>(?:[^"]|")*)"
          for "(?P<field>(?:[^"]|")*)"$/
        When /^(?:|I )fill in the following:$/




      MINK TEST STEPS
Saturday, February 2, 13
When /^(?:|I )select "(?P<option>(?:[^"]|")*)"
            from "(?P<select>(?:[^"]|")*)"$/
          When /^(?:|I )additionally select "(?P<option>(?:[^"]|")*)"
            from "(?P<select>(?:[^"]|")*)"$/
          When /^(?:|I )attach the file "(?P[^"]*)" to "(?P<field>(?:[^"]|")*)"$/
          Then /^(?:|I )should be on "(?P<page>[^"]+)"$/
          Then /^the (?i)url(?-i) should match (?P<pattern>"([^"]|")*")$/
          Then /^the response status code should be (?P<code>d+)$/
          Then /^the response status code should not be (?P<code>d+)$/
          Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)"$/
          Then /^(?:|I )should not see "(?P<text>(?:[^"]|")*)"$/
          Then /^(?:|I )should see text matching (?P<pattern>"(?:[^"]|")*")$/
          Then /^(?:|I )should not see text matching (?P<pattern>"(?:[^"]|")*")$/
          Then /^the response should contain "(?P<text>(?:[^"]|")*)"$/
          Then /^the response should not contain "(?P<text>(?:[^"]|")*)"$/
          Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)"
            in the "(?P<element>[^"]*)" element$/
          Then /^(?:|I )should not see "(?P<text>(?:[^"]|")*)"




      MINK TEST STEPS
Saturday, February 2, 13
Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)"
            in the "(?P<element>[^"]*)" element$/
          Then /^(?:|I )should not see "(?P<text>(?:[^"]|")*)"
          Then /^(?:|I )should not see an? "(?P<element>[^"]*)" element$/
          Then /^the "(?P<field>(?:[^"]|")*)" field
            should contain "(?P<value>(?:[^"]|")*)"$/
          Then /^the "(?P<field>(?:[^"]|")*)" field
            should not contain "(?P<value>(?:[^"]|")*)"$/
          Then /^the "(?P<checkbox>(?:[^"]|")*)" checkbox should be checked$/
          Then /^the "(?P<checkbox>(?:[^"]|")*)" checkbox should not be checked$/
          Then /^(?:|I )should see (?P<num>d+) "(?P<element>[^"]*)" elements?$/
          Then /^print last response$/
          Then /^show last response$/




      MINK TEST STEPS
Saturday, February 2, 13
DOING A REAL MINK TEST
                             https://github.com/phase2/behat-phase2tech




Saturday, February 2, 13
{
                 "require": {
                   "behat/behat": "2.4.*@stable",
                   "behat/mink": "*",
                   "behat/mink-extension": "*",
                   "behat/mink-goutte-driver": "*",
                   "behat/mink-selenium-driver": "*",
                   "behat/mink-selenium2-driver": "*"
                 },
                 "minimum-stability": "dev",
                 "config": {
                   "bin-dir": "bin/"
                 }
            }




      COMPOSER.JSON
Saturday, February 2, 13
default:
                extensions:
                     BehatMinkExtensionExtension:
                         base_url: http://www.phase2technology.com/
                         goutte: ~
                         selenium2:
                           browser: "chrome"
                         javascript_session: selenium2




      BEHAT.YML
Saturday, February 2, 13
Feature: Search
              In order to look for articles on the Phase2 website
              As a website user
              I need to be able to search for articles

                  Scenario:   Searching for responsive design articles
                    Given I   am on "/search"
                     When I   fill in "Enter your keywords" with "Responsive design"
                      And I   press "Search"
                     Then I   should see "Blog Entry"




      GHERKIN TEST WITH MINK
Saturday, February 2, 13
Scenario: Searching for Drupal blog posts
                    Given I am on "/search"
                    When I fill in "Enter your keywords" with "drupal"
                    And I press "Search"
                    Then I should see "Blog Entry"

                  Scenario: Searching for Clojure articles
                    Given I am on "/search"
                    When I fill in "Enter your keywords" with "Clojure"
                    And I press "Search"
                    Then I should not see "Blog Entry"




      GHERKIN TEST WITH MINK
Saturday, February 2, 13
Feature: Search
              In order to look for articles on the Phase2 website
              As a website user
              I need to be able to search for articles

                  Scenario Outline: Searching the website
                    Given I am on "/search"
                    When I fill in "Enter your keywords" with "<keyword>"
                    And I press "Search"
                    Then I should see "<result>"




      GHERKIN TEST WITH MINK
Saturday, February 2, 13
Scenario Outline: Searching the website
                    Given I am on "/search"
                    When I fill in "Enter your keywords" with "<keyword>"
                    And I press "Search"
                    Then I should see "<result>"

                           Examples:
                             | keyword             |   result         |
                             | Drupal              |   Blog Entry     |
                             | smerrill            |   Presentation   |
                             | sharepoint drupal   |   Blog Entry     |




      GHERKIN TEST WITH MINK
Saturday, February 2, 13
IMPLEMENTING YOUR OWN STEPS
            • behat -dl will show all step definitions

            • Steps are written in PHP

            • Place them in your Feature Context

            • Call other steps inline




Saturday, February 2, 13
Feature: Favicon
              In order to have a good user experience
              As a website user
              I need to be able to distinguish the site by its favicon

                  Scenario: The favicon is not missing
                    Given I am on homepage
                     Then the favicon should be found




      GHERKIN TEST WITH A CUSTOM STEP
Saturday, February 2, 13
use BehatBehatContextStep;

       class FeatureContext extends BehatMinkExtensionContextMinkContext {
         /**
           * Initializes context.
           * Every scenario gets it's own context object.
           *
           * @param array $parameters
           *   context parameters (set them up through behat.yml)
           */
         public function __construct(array $parameters) {
         }




      FEATURES/BOOTSTRAP/FEATURECONTEXT.PHP
Saturday, February 2, 13
/**
                 * @Then /^the favicon should be found$/
                 */
                public function theFaviconShouldBeFound() {
                  $favicon_url = "/favicon.ico";
                  if ($favicon_link = $this->getSession()->getPage()
                    ->find('css', 'link[rel="shortcut icon"]')) {
                    $favicon_url = $favicon_link->getAttribute('href');
                  }

                      return array(
                        new StepGiven(sprintf('I go to "%s"', $favicon_url)),
                        new StepThen('the response status code should not be 404'),
                      );
                }
          }


      FEATURES/BOOTSTRAP/FEATURECONTEXT.PHP
Saturday, February 2, 13
DRUPAL BEHAT
                           https://github.com/phase2/behat-drupal-extension




Saturday, February 2, 13
DRUPAL-SPECIFIC BEHAT STEPS
            • Log in (by user/pass or as a test user with a role) or out

            • Run cron

            • Create nodes

            • Install modules

            • Teardown tasks to remove all test entries



Saturday, February 2, 13
default:
         extensions:
           Phase2BehatDrupalExtensionExtension:
             drupal_root: "/var/www/drupal-testing"
             base_url: "http://behat.dev/"




      BEHAT.YML
Saturday, February 2, 13
Feature: Permissions
         In order to control access
         Certain roles need to be restricted from logging in

             Scenario:     Publishers cannot add blog posts
               Given I     am logged in as a user with the "Publisher" role
                When I     go to "/node/add"
                Then I     should see "Article"




      PERMISSIONS.FEATURE
Saturday, February 2, 13
Scenario:     Publishers cannot add blog posts
               Given I     am logged in as a user with the "Publisher" role
                When I     go to "/node/add"
                Then I     should not see "Blog Entry"

             Scenario: Anonymous users may not add content
               Given I am logged out
                When I go to "/node/add"
                Then the response status code should be 403




      PERMISSIONS.FEATURE
Saturday, February 2, 13
RIGHT TOOLS FOR THE JOB

Saturday, February 2, 13
CASPERJS / PHANTOMJS
            • Test writers need to know JavaScript (or CoffeeScript)

            • Interact with a fully-featured browser

            • Use the JavaScript and DOM environment of the browser

            • Save screenshots




Saturday, February 2, 13
BEHAT
            • Tests can be written or read by non-technical stakeholders

            • New step definitions are written in PHP

            • Both APIs and browser-based assertions can be tested

            • You can use a real browser




Saturday, February 2, 13
BOTH TOOLS
            • Integrate well with continuous integration tools

            • Can provide detailed assertion results in JUnit XML format

            • Provide ways to alter variables per environment




Saturday, February 2, 13
GO FORTH AND TEST!

Saturday, February 2, 13
phase2technology.com
                               @phase2tech




Saturday, February 2, 13

Contenu connexe

Tendances

“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.Graham Dumpleton
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsRyan Weaver
 
The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)Olaf Alders
 
Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...
Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...
Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...Puppet
 
A Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficA Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficPhilip Tellis
 
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]Dirk Ginader
 
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksHow to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksCarlos Sanchez
 
Streamline your development environment with docker
Streamline your development environment with dockerStreamline your development environment with docker
Streamline your development environment with dockerGiacomo Bagnoli
 
Docker Demo @ IuK Seminar
Docker Demo @ IuK SeminarDocker Demo @ IuK Seminar
Docker Demo @ IuK SeminarMartin Scharm
 
하루프레스
하루프레스하루프레스
하루프레스Rhio Kim
 
Lights, Camera, Docker: Streaming Video at DramaFever
Lights, Camera, Docker: Streaming Video at DramaFeverLights, Camera, Docker: Streaming Video at DramaFever
Lights, Camera, Docker: Streaming Video at DramaFeverbridgetkromhout
 
Automated reproducible images on openstack using vagrant and packer
Automated reproducible images on openstack using vagrant and packerAutomated reproducible images on openstack using vagrant and packer
Automated reproducible images on openstack using vagrant and packerJan Collijs
 
Bower - A package manager for the web
Bower - A package manager for the webBower - A package manager for the web
Bower - A package manager for the webLarry Nung
 
Freeing the cloud, one service at a time
Freeing the cloud, one service at a timeFreeing the cloud, one service at a time
Freeing the cloud, one service at a timeFrancois Marier
 
우리가 모르는 노드로 할 수 있는 몇가지
우리가 모르는 노드로 할 수 있는 몇가지우리가 모르는 노드로 할 수 있는 몇가지
우리가 모르는 노드로 할 수 있는 몇가지Rhio Kim
 
Aligning Continuous Integration Deployment: Automated Validation of OpenStack...
Aligning Continuous Integration Deployment: Automated Validation of OpenStack...Aligning Continuous Integration Deployment: Automated Validation of OpenStack...
Aligning Continuous Integration Deployment: Automated Validation of OpenStack...Atlassian
 
rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014nvpuppet
 
Gem That (2009)
Gem That (2009)Gem That (2009)
Gem That (2009)lazyatom
 

Tendances (20)

“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
 
The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)
 
Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...
Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...
Puppet Camp Boston 2014: Greenfield Puppet: Getting it right from the start (...
 
Mangling
Mangling Mangling
Mangling
 
A Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficA Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web Traffic
 
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
 
Acceptance tests
Acceptance testsAcceptance tests
Acceptance tests
 
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksHow to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
 
Streamline your development environment with docker
Streamline your development environment with dockerStreamline your development environment with docker
Streamline your development environment with docker
 
Docker Demo @ IuK Seminar
Docker Demo @ IuK SeminarDocker Demo @ IuK Seminar
Docker Demo @ IuK Seminar
 
하루프레스
하루프레스하루프레스
하루프레스
 
Lights, Camera, Docker: Streaming Video at DramaFever
Lights, Camera, Docker: Streaming Video at DramaFeverLights, Camera, Docker: Streaming Video at DramaFever
Lights, Camera, Docker: Streaming Video at DramaFever
 
Automated reproducible images on openstack using vagrant and packer
Automated reproducible images on openstack using vagrant and packerAutomated reproducible images on openstack using vagrant and packer
Automated reproducible images on openstack using vagrant and packer
 
Bower - A package manager for the web
Bower - A package manager for the webBower - A package manager for the web
Bower - A package manager for the web
 
Freeing the cloud, one service at a time
Freeing the cloud, one service at a timeFreeing the cloud, one service at a time
Freeing the cloud, one service at a time
 
우리가 모르는 노드로 할 수 있는 몇가지
우리가 모르는 노드로 할 수 있는 몇가지우리가 모르는 노드로 할 수 있는 몇가지
우리가 모르는 노드로 할 수 있는 몇가지
 
Aligning Continuous Integration Deployment: Automated Validation of OpenStack...
Aligning Continuous Integration Deployment: Automated Validation of OpenStack...Aligning Continuous Integration Deployment: Automated Validation of OpenStack...
Aligning Continuous Integration Deployment: Automated Validation of OpenStack...
 
rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014
 
Gem That (2009)
Gem That (2009)Gem That (2009)
Gem That (2009)
 

Similaire à Testing Drupal with Ghosts and Gherkin

Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013Puppet
 
Node.js x Azure, cli usage, website deployment
Node.js x Azure, cli usage, website deploymentNode.js x Azure, cli usage, website deployment
Node.js x Azure, cli usage, website deploymentCaesar Chi
 
Velocity EU 2012 - Third party scripts and you
Velocity EU 2012 - Third party scripts and youVelocity EU 2012 - Third party scripts and you
Velocity EU 2012 - Third party scripts and youPatrick Meenan
 
Bundling Client Side Assets
Bundling Client Side AssetsBundling Client Side Assets
Bundling Client Side AssetsTimothy Oxley
 
Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...NETWAYS
 
Austin OpenStack Meetup: Chef and OpenStack
Austin OpenStack Meetup: Chef and OpenStackAustin OpenStack Meetup: Chef and OpenStack
Austin OpenStack Meetup: Chef and OpenStackMatt Ray
 
Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...Puppet
 
Deploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoDeploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoAlmir Mendes
 
A Continuous Packaging Pipeline
A Continuous Packaging PipelineA Continuous Packaging Pipeline
A Continuous Packaging PipelineMaciej Pasternacki
 
Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkPatrick LaRoche
 
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com RubyConsegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com RubyFabio Akita
 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudHiro Asari
 
Forget Grunt and Gulp! Webpack and NPM rule them all!
Forget Grunt and Gulp! Webpack and NPM rule them all!Forget Grunt and Gulp! Webpack and NPM rule them all!
Forget Grunt and Gulp! Webpack and NPM rule them all!Derek Willian Stavis
 
Agile Breakfast with Gradle
Agile Breakfast with GradleAgile Breakfast with Gradle
Agile Breakfast with GradleRene Gröschke
 
Getting to Know Grunt by Writing Your Own Plugin
Getting to Know Grunt by Writing Your Own PluginGetting to Know Grunt by Writing Your Own Plugin
Getting to Know Grunt by Writing Your Own PluginJamie Strachan
 

Similaire à Testing Drupal with Ghosts and Gherkin (20)

161208
161208161208
161208
 
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
 
Node.js x Azure, cli usage, website deployment
Node.js x Azure, cli usage, website deploymentNode.js x Azure, cli usage, website deployment
Node.js x Azure, cli usage, website deployment
 
Velocity EU 2012 - Third party scripts and you
Velocity EU 2012 - Third party scripts and youVelocity EU 2012 - Third party scripts and you
Velocity EU 2012 - Third party scripts and you
 
With your bare hands
With your bare handsWith your bare hands
With your bare hands
 
Bundling Client Side Assets
Bundling Client Side AssetsBundling Client Side Assets
Bundling Client Side Assets
 
Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...
 
Austin OpenStack Meetup: Chef and OpenStack
Austin OpenStack Meetup: Chef and OpenStackAustin OpenStack Meetup: Chef and OpenStack
Austin OpenStack Meetup: Chef and OpenStack
 
Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...Building scalable applications while scaling your infrastructure by rhommel l...
Building scalable applications while scaling your infrastructure by rhommel l...
 
Deploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoDeploying Rails Applications with Capistrano
Deploying Rails Applications with Capistrano
 
A Continuous Packaging Pipeline
A Continuous Packaging PipelineA Continuous Packaging Pipeline
A Continuous Packaging Pipeline
 
Sprockets
SprocketsSprockets
Sprockets
 
Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM Talk
 
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com RubyConsegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
 
How we're building Wercker
How we're building WerckerHow we're building Wercker
How we're building Wercker
 
Sprockets
SprocketsSprockets
Sprockets
 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the Cloud
 
Forget Grunt and Gulp! Webpack and NPM rule them all!
Forget Grunt and Gulp! Webpack and NPM rule them all!Forget Grunt and Gulp! Webpack and NPM rule them all!
Forget Grunt and Gulp! Webpack and NPM rule them all!
 
Agile Breakfast with Gradle
Agile Breakfast with GradleAgile Breakfast with Gradle
Agile Breakfast with Gradle
 
Getting to Know Grunt by Writing Your Own Plugin
Getting to Know Grunt by Writing Your Own PluginGetting to Know Grunt by Writing Your Own Plugin
Getting to Know Grunt by Writing Your Own Plugin
 

Plus de Phase2

Phase2 Health and Wellness Brochure
Phase2 Health and Wellness BrochurePhase2 Health and Wellness Brochure
Phase2 Health and Wellness BrochurePhase2
 
A Modern Digital Experience Platform
A Modern Digital Experience PlatformA Modern Digital Experience Platform
A Modern Digital Experience PlatformPhase2
 
Beyond websites: A Modern Digital Experience Platform
Beyond websites: A Modern Digital Experience PlatformBeyond websites: A Modern Digital Experience Platform
Beyond websites: A Modern Digital Experience PlatformPhase2
 
Omnichannel For Government
Omnichannel For Government Omnichannel For Government
Omnichannel For Government Phase2
 
Bad camp2016 Release Management On Live Websites
Bad camp2016 Release Management On Live WebsitesBad camp2016 Release Management On Live Websites
Bad camp2016 Release Management On Live WebsitesPhase2
 
A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8
A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8
A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8Phase2
 
The Future of Digital Storytelling - Phase2 Talk
The Future of Digital Storytelling - Phase2 TalkThe Future of Digital Storytelling - Phase2 Talk
The Future of Digital Storytelling - Phase2 TalkPhase2
 
Site building with end user in mind
Site building with end user in mindSite building with end user in mind
Site building with end user in mindPhase2
 
Fields, entities, lists, oh my!
Fields, entities, lists, oh my!Fields, entities, lists, oh my!
Fields, entities, lists, oh my!Phase2
 
Performance Profiling Tools and Tricks
Performance Profiling Tools and TricksPerformance Profiling Tools and Tricks
Performance Profiling Tools and TricksPhase2
 
NORTH CAROLINA Open Source, OpenPublic, OpenShift
NORTH CAROLINA Open Source, OpenPublic, OpenShiftNORTH CAROLINA Open Source, OpenPublic, OpenShift
NORTH CAROLINA Open Source, OpenPublic, OpenShiftPhase2
 
Drupal 8 for Enterprise: D8 in a Changing Digital Landscape
Drupal 8 for Enterprise: D8 in a Changing Digital LandscapeDrupal 8 for Enterprise: D8 in a Changing Digital Landscape
Drupal 8 for Enterprise: D8 in a Changing Digital LandscapePhase2
 
Riding the Drupal Wave: The Future for Drupal and Open Source Content Manage...
Riding the Drupal Wave:  The Future for Drupal and Open Source Content Manage...Riding the Drupal Wave:  The Future for Drupal and Open Source Content Manage...
Riding the Drupal Wave: The Future for Drupal and Open Source Content Manage...Phase2
 
Site Building with the End User in Mind
Site Building with the End User in MindSite Building with the End User in Mind
Site Building with the End User in MindPhase2
 
The Yes, No, and Maybe of "Can We Build That With Drupal?"
The Yes, No, and Maybe of "Can We Build That With Drupal?"The Yes, No, and Maybe of "Can We Build That With Drupal?"
The Yes, No, and Maybe of "Can We Build That With Drupal?"Phase2
 
User Testing For Humanitarian ID App
User Testing For Humanitarian ID AppUser Testing For Humanitarian ID App
User Testing For Humanitarian ID AppPhase2
 
Redhat.com: An Architectural Case Study
Redhat.com: An Architectural Case StudyRedhat.com: An Architectural Case Study
Redhat.com: An Architectural Case StudyPhase2
 
The New Design Workflow
The New Design WorkflowThe New Design Workflow
The New Design WorkflowPhase2
 
Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)
Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)
Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)Phase2
 
Memorial Sloan Kettering: Adventures in Drupal 8
Memorial Sloan Kettering: Adventures in Drupal 8Memorial Sloan Kettering: Adventures in Drupal 8
Memorial Sloan Kettering: Adventures in Drupal 8Phase2
 

Plus de Phase2 (20)

Phase2 Health and Wellness Brochure
Phase2 Health and Wellness BrochurePhase2 Health and Wellness Brochure
Phase2 Health and Wellness Brochure
 
A Modern Digital Experience Platform
A Modern Digital Experience PlatformA Modern Digital Experience Platform
A Modern Digital Experience Platform
 
Beyond websites: A Modern Digital Experience Platform
Beyond websites: A Modern Digital Experience PlatformBeyond websites: A Modern Digital Experience Platform
Beyond websites: A Modern Digital Experience Platform
 
Omnichannel For Government
Omnichannel For Government Omnichannel For Government
Omnichannel For Government
 
Bad camp2016 Release Management On Live Websites
Bad camp2016 Release Management On Live WebsitesBad camp2016 Release Management On Live Websites
Bad camp2016 Release Management On Live Websites
 
A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8
A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8
A FUTURE-FOCUSED DIGITAL PLATFORM WITH DRUPAL 8
 
The Future of Digital Storytelling - Phase2 Talk
The Future of Digital Storytelling - Phase2 TalkThe Future of Digital Storytelling - Phase2 Talk
The Future of Digital Storytelling - Phase2 Talk
 
Site building with end user in mind
Site building with end user in mindSite building with end user in mind
Site building with end user in mind
 
Fields, entities, lists, oh my!
Fields, entities, lists, oh my!Fields, entities, lists, oh my!
Fields, entities, lists, oh my!
 
Performance Profiling Tools and Tricks
Performance Profiling Tools and TricksPerformance Profiling Tools and Tricks
Performance Profiling Tools and Tricks
 
NORTH CAROLINA Open Source, OpenPublic, OpenShift
NORTH CAROLINA Open Source, OpenPublic, OpenShiftNORTH CAROLINA Open Source, OpenPublic, OpenShift
NORTH CAROLINA Open Source, OpenPublic, OpenShift
 
Drupal 8 for Enterprise: D8 in a Changing Digital Landscape
Drupal 8 for Enterprise: D8 in a Changing Digital LandscapeDrupal 8 for Enterprise: D8 in a Changing Digital Landscape
Drupal 8 for Enterprise: D8 in a Changing Digital Landscape
 
Riding the Drupal Wave: The Future for Drupal and Open Source Content Manage...
Riding the Drupal Wave:  The Future for Drupal and Open Source Content Manage...Riding the Drupal Wave:  The Future for Drupal and Open Source Content Manage...
Riding the Drupal Wave: The Future for Drupal and Open Source Content Manage...
 
Site Building with the End User in Mind
Site Building with the End User in MindSite Building with the End User in Mind
Site Building with the End User in Mind
 
The Yes, No, and Maybe of "Can We Build That With Drupal?"
The Yes, No, and Maybe of "Can We Build That With Drupal?"The Yes, No, and Maybe of "Can We Build That With Drupal?"
The Yes, No, and Maybe of "Can We Build That With Drupal?"
 
User Testing For Humanitarian ID App
User Testing For Humanitarian ID AppUser Testing For Humanitarian ID App
User Testing For Humanitarian ID App
 
Redhat.com: An Architectural Case Study
Redhat.com: An Architectural Case StudyRedhat.com: An Architectural Case Study
Redhat.com: An Architectural Case Study
 
The New Design Workflow
The New Design WorkflowThe New Design Workflow
The New Design Workflow
 
Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)
Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)
Drupal 8, Don’t Be Late (Enterprise Orgs, We’re Looking at You)
 
Memorial Sloan Kettering: Adventures in Drupal 8
Memorial Sloan Kettering: Adventures in Drupal 8Memorial Sloan Kettering: Adventures in Drupal 8
Memorial Sloan Kettering: Adventures in Drupal 8
 

Testing Drupal with Ghosts and Gherkin

  • 1. THE LEADER IN DRUPAL PLATFORM DESIGN AND DEVELOPMENT Saturday, February 2, 13
  • 2. TESTING DRUPAL WITH GHOSTS AND GHERKINS USING CASPERJS AND BEHAT TO TEST DRUPAL SITES Saturday, February 2, 13
  • 3. STEVEN MERRILL Director of Engineering smerrill@phase2technology.com @stevenmerrill https://github.com/smerrill Saturday, February 2, 13
  • 4. ABOUT ME • Fan of Jenkins and continuous integration • Running Jenkins in production for about 4 years Saturday, February 2, 13
  • 5. ABOUT THIS PRESENTATION • Originally titled "Testing Your Site With Friendly Ghosts" • Developed by Eric Duran and me • Thanks, Eric! Saturday, February 2, 13
  • 6. A TWITTER EXCHANGE PEOPLE WANT TO TEST THEIR DRUPAL MODULES WITH REAL BROWSERS Saturday, February 2, 13
  • 7. Is there precedent for including selenium tests in a #drupal contrib module? #lazyweb ” @stevector Saturday, February 2, 13
  • 8. @stevector https://github.com/ericduran/ views_load_more is a neat example of including @casperjs_org tests and running them using @travisci. ” @stevenmerrill Saturday, February 2, 13
  • 9. @stevenmerrill Thanks! That approach looks very viable for the what I want to do (check for text in a CTools modal). ” @stevector Saturday, February 2, 13
  • 10. YOU NEED TO TEST YOUR SITE Saturday, February 2, 13
  • 11. SIMPLETEST • Let's test complex AJAX in a real browser! Saturday, February 2, 13
  • 13. SELENIUM • Let's add variables into a test that was recorded by clicking around the interface. Saturday, February 2, 13
  • 15. FRIENDLY GHOSTS • Website testing tools based around headless WebKit. • PhantomJS (https://github.com/ariya/phantomjs) • CasperJS (https://github.com/n1k0/casperjs) Saturday, February 2, 13
  • 16. FRIENDLY GHOSTS • Headless website testing • Site scraping • Run QUnit Saturday, February 2, 13
  • 17. PHANTOMJS • Headless Webkit browser • Scriptable via a JavaScript API • Write data to the filesystem • Render <canvas> contents • Use JavaScript or CoffeeScript Saturday, February 2, 13
  • 19. var page = require('webpage').create(); page.open(url1, function(status) { if (status == "fail") phantom.exit(); page.open(url2, function(status) { if (status == "fail") phantom.exit(); page.open(url3, function(status) { if (status == "fail") phantom.exit(); page.open(url4, function(status) { if (status == "fail") phantom.exit(); // Can I stop, now? }); }); }); }); PHANTOMJS Saturday, February 2, 13
  • 20. var casper = require('casper').create(); casper.start(url1); casper.thenOpen(url2); casper.thenOpen(url3); casper.thenOpen(url4); casper.run(); CASPERJS Saturday, February 2, 13
  • 21. THE CASPERJS API • Take actions through a website • Clicking/following links • Filling/submitting forms • Downloading resources • Capturing screenshots • Running DOM assertions Saturday, February 2, 13
  • 22. // Search for 'casperjs' from google.com. casper.start('http://google.com/', function() { this.fill('form[action="/search"]', { q: 'casperjs' }, true);}); // Search for a 'casperjs' module from d.o. casper.start('http://drupal.org/', function() { this.fill('#search-theme-form', {search_theme_form: 'casperjs', meta_type: 'module'}, true);}); USING THE CASPERJS API Saturday, February 2, 13
  • 23. TESTING • You use JavaScript to build sites! • Test real JavaScript interactions. • Save screenshots or scraped data. • Export JUnit XML and hook into Jenkins. Saturday, February 2, 13
  • 24. TRAVIS + CASPER AUTOMATED TESTING • Host a mirror of your module on GitHub • https://github.com/ericduran/views_load_more • Use TravisCI to automate your testing • https://github.com/ericduran/views_load_more/blob/ 7.x-1.x/.travis.yml • Write tests and update your README with the build status! Saturday, February 2, 13
  • 25. language: php php: - 5.4 mysql: database: drupal username: root encoding: utf8 before_script: - mysql -e 'create database drupal;' - pyrus channel-discover pear.drush.org - pyrus install drush/drush - phpenv rehash TRAVIS.YML Saturday, February 2, 13
  • 26. - wget http://ftp.drupal.org/files/projects/drupal-7.14.tar.gz - tar -xf drupal-7.14.tar.gz - cd drupal-7.14 - drush site-install standard --db-url=mysql://root:@localhost/drupal --yes - git clone --quiet --branch casper-test git://github.com/ericduran/ views_load_more.git ./sites/all/modules/views_load_more - drush en views_load_more_test --yes - drush cc all --yes TRAVIS.YML Saturday, February 2, 13
  • 27. - "export PHANTOMJS_EXECUTABLE='phantomjs --local-to-remote-url- access=yes --ignore-ssl-errors=yes'" - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" - sleep 3 # give xvfb some time to start - drush runserver --server=builtin 8080 & - sleep 3 # give Web server some time to bind to sockets, etc - cd .. - git clone git://github.com/n1k0/casperjs.git - cd casperjs - git checkout tags/0.6.10 - cd ./bin script: - "DISPLAY=:99.0 ./casperjs test ../../test/casperjs/" TRAVIS.YML, CONT'D Saturday, February 2, 13
  • 29. INSTALLING PHANTOM AND CASPER brew install phantomjs brew install casperjs Saturday, February 2, 13
  • 30. PHANTOM/CASPER LINKS • http://phantomjs.org/ • http://casperjs.org/index.html • https://github.com/ericduran/friendly-ghosts-examples Saturday, February 2, 13
  • 31. API DOCUMENTATION • Client Utilities: http://casperjs.org/api.html#client-utils • Testing API: http://casperjs.org/api.html#tester • Utils: http://casperjs.org/api.html#utils • CLI: http://casperjs.org/cli.html Saturday, February 2, 13
  • 33. BEHAT • Behavior driven development framework for PHP 5.3+ • Uses Symfony components • Uses the Gherkin format for feature definitions Saturday, February 2, 13
  • 34. MINK • Browser testing for Behat • Has a pure PHP test browser (Goutte) • Can run Selenium or Selenium 2 tests • Can farm testing out to Sauce Labs Saturday, February 2, 13
  • 35. GHERKIN • Business-readable domain specific language • Features • Scenarios • Step Definitions Saturday, February 2, 13
  • 36. GHERKIN STEP DEFINITIONS • Given • Preconditions • When • Actions • Then • Assertions Saturday, February 2, 13
  • 37. Feature: In order to learn about automated testing tools As a DrupalCamp New Jersey attendee I want to attend Testing Drupal with Ghosts and Gherkins Scenario: Attending the session Given that the time is 10:30 AM When I enter room Friend 008 Then the presenter should be Steven Merrill And the session should be Testing Drupal GHERKIN TEST Saturday, February 2, 13
  • 38. MINK STEP DEFINITIONS • Navigate to pages • Check HTTP status codes • Fill in forms by label • Click links • Look for text Saturday, February 2, 13
  • 39. $ ./bin/behat -dl Given /^(?:|I )am on homepage$/ When /^(?:|I )go to homepage$/ Given /^(?:|I )am on "(?P<page>[^"]+)"$/ When /^(?:|I )go to "(?P<page>[^"]+)"$/ When /^(?:|I )reload the page$/ When /^(?:|I )move backward one page$/ When /^(?:|I )move forward one page$/ When /^(?:|I )press "(?P<button>(?:[^"]|")*)"$/ When /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/ When /^(?:|I )fill in "(?P<field>(?:[^"]|")*)" with "(?P<value>(?:[^"]|")*)"$/ When /^(?:|I )fill in "(?P<value>(?:[^"]|")*)" for "(?P<field>(?:[^"]|")*)"$/ When /^(?:|I )fill in the following:$/ MINK TEST STEPS Saturday, February 2, 13
  • 40. When /^(?:|I )select "(?P<option>(?:[^"]|")*)" from "(?P<select>(?:[^"]|")*)"$/ When /^(?:|I )additionally select "(?P<option>(?:[^"]|")*)" from "(?P<select>(?:[^"]|")*)"$/ When /^(?:|I )attach the file "(?P[^"]*)" to "(?P<field>(?:[^"]|")*)"$/ Then /^(?:|I )should be on "(?P<page>[^"]+)"$/ Then /^the (?i)url(?-i) should match (?P<pattern>"([^"]|")*")$/ Then /^the response status code should be (?P<code>d+)$/ Then /^the response status code should not be (?P<code>d+)$/ Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)"$/ Then /^(?:|I )should not see "(?P<text>(?:[^"]|")*)"$/ Then /^(?:|I )should see text matching (?P<pattern>"(?:[^"]|")*")$/ Then /^(?:|I )should not see text matching (?P<pattern>"(?:[^"]|")*")$/ Then /^the response should contain "(?P<text>(?:[^"]|")*)"$/ Then /^the response should not contain "(?P<text>(?:[^"]|")*)"$/ Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)" in the "(?P<element>[^"]*)" element$/ Then /^(?:|I )should not see "(?P<text>(?:[^"]|")*)" MINK TEST STEPS Saturday, February 2, 13
  • 41. Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)" in the "(?P<element>[^"]*)" element$/ Then /^(?:|I )should not see "(?P<text>(?:[^"]|")*)" Then /^(?:|I )should not see an? "(?P<element>[^"]*)" element$/ Then /^the "(?P<field>(?:[^"]|")*)" field should contain "(?P<value>(?:[^"]|")*)"$/ Then /^the "(?P<field>(?:[^"]|")*)" field should not contain "(?P<value>(?:[^"]|")*)"$/ Then /^the "(?P<checkbox>(?:[^"]|")*)" checkbox should be checked$/ Then /^the "(?P<checkbox>(?:[^"]|")*)" checkbox should not be checked$/ Then /^(?:|I )should see (?P<num>d+) "(?P<element>[^"]*)" elements?$/ Then /^print last response$/ Then /^show last response$/ MINK TEST STEPS Saturday, February 2, 13
  • 42. DOING A REAL MINK TEST https://github.com/phase2/behat-phase2tech Saturday, February 2, 13
  • 43. { "require": { "behat/behat": "2.4.*@stable", "behat/mink": "*", "behat/mink-extension": "*", "behat/mink-goutte-driver": "*", "behat/mink-selenium-driver": "*", "behat/mink-selenium2-driver": "*" }, "minimum-stability": "dev", "config": { "bin-dir": "bin/" } } COMPOSER.JSON Saturday, February 2, 13
  • 44. default: extensions: BehatMinkExtensionExtension: base_url: http://www.phase2technology.com/ goutte: ~ selenium2: browser: "chrome" javascript_session: selenium2 BEHAT.YML Saturday, February 2, 13
  • 45. Feature: Search In order to look for articles on the Phase2 website As a website user I need to be able to search for articles Scenario: Searching for responsive design articles Given I am on "/search" When I fill in "Enter your keywords" with "Responsive design" And I press "Search" Then I should see "Blog Entry" GHERKIN TEST WITH MINK Saturday, February 2, 13
  • 46. Scenario: Searching for Drupal blog posts Given I am on "/search" When I fill in "Enter your keywords" with "drupal" And I press "Search" Then I should see "Blog Entry" Scenario: Searching for Clojure articles Given I am on "/search" When I fill in "Enter your keywords" with "Clojure" And I press "Search" Then I should not see "Blog Entry" GHERKIN TEST WITH MINK Saturday, February 2, 13
  • 47. Feature: Search In order to look for articles on the Phase2 website As a website user I need to be able to search for articles Scenario Outline: Searching the website Given I am on "/search" When I fill in "Enter your keywords" with "<keyword>" And I press "Search" Then I should see "<result>" GHERKIN TEST WITH MINK Saturday, February 2, 13
  • 48. Scenario Outline: Searching the website Given I am on "/search" When I fill in "Enter your keywords" with "<keyword>" And I press "Search" Then I should see "<result>" Examples: | keyword | result | | Drupal | Blog Entry | | smerrill | Presentation | | sharepoint drupal | Blog Entry | GHERKIN TEST WITH MINK Saturday, February 2, 13
  • 49. IMPLEMENTING YOUR OWN STEPS • behat -dl will show all step definitions • Steps are written in PHP • Place them in your Feature Context • Call other steps inline Saturday, February 2, 13
  • 50. Feature: Favicon In order to have a good user experience As a website user I need to be able to distinguish the site by its favicon Scenario: The favicon is not missing Given I am on homepage Then the favicon should be found GHERKIN TEST WITH A CUSTOM STEP Saturday, February 2, 13
  • 51. use BehatBehatContextStep; class FeatureContext extends BehatMinkExtensionContextMinkContext { /** * Initializes context. * Every scenario gets it's own context object. * * @param array $parameters * context parameters (set them up through behat.yml) */ public function __construct(array $parameters) { } FEATURES/BOOTSTRAP/FEATURECONTEXT.PHP Saturday, February 2, 13
  • 52. /** * @Then /^the favicon should be found$/ */ public function theFaviconShouldBeFound() { $favicon_url = "/favicon.ico"; if ($favicon_link = $this->getSession()->getPage() ->find('css', 'link[rel="shortcut icon"]')) { $favicon_url = $favicon_link->getAttribute('href'); } return array( new StepGiven(sprintf('I go to "%s"', $favicon_url)), new StepThen('the response status code should not be 404'), ); } } FEATURES/BOOTSTRAP/FEATURECONTEXT.PHP Saturday, February 2, 13
  • 53. DRUPAL BEHAT https://github.com/phase2/behat-drupal-extension Saturday, February 2, 13
  • 54. DRUPAL-SPECIFIC BEHAT STEPS • Log in (by user/pass or as a test user with a role) or out • Run cron • Create nodes • Install modules • Teardown tasks to remove all test entries Saturday, February 2, 13
  • 55. default: extensions: Phase2BehatDrupalExtensionExtension: drupal_root: "/var/www/drupal-testing" base_url: "http://behat.dev/" BEHAT.YML Saturday, February 2, 13
  • 56. Feature: Permissions In order to control access Certain roles need to be restricted from logging in Scenario: Publishers cannot add blog posts Given I am logged in as a user with the "Publisher" role When I go to "/node/add" Then I should see "Article" PERMISSIONS.FEATURE Saturday, February 2, 13
  • 57. Scenario: Publishers cannot add blog posts Given I am logged in as a user with the "Publisher" role When I go to "/node/add" Then I should not see "Blog Entry" Scenario: Anonymous users may not add content Given I am logged out When I go to "/node/add" Then the response status code should be 403 PERMISSIONS.FEATURE Saturday, February 2, 13
  • 58. RIGHT TOOLS FOR THE JOB Saturday, February 2, 13
  • 59. CASPERJS / PHANTOMJS • Test writers need to know JavaScript (or CoffeeScript) • Interact with a fully-featured browser • Use the JavaScript and DOM environment of the browser • Save screenshots Saturday, February 2, 13
  • 60. BEHAT • Tests can be written or read by non-technical stakeholders • New step definitions are written in PHP • Both APIs and browser-based assertions can be tested • You can use a real browser Saturday, February 2, 13
  • 61. BOTH TOOLS • Integrate well with continuous integration tools • Can provide detailed assertion results in JUnit XML format • Provide ways to alter variables per environment Saturday, February 2, 13
  • 62. GO FORTH AND TEST! Saturday, February 2, 13
  • 63. phase2technology.com @phase2tech Saturday, February 2, 13