Adding More Sauce To Behat

24 Apr

 

Note : This post may not work with recent Behat. Please use and my  Github repo for to get it working without any issue https://github.com/Shashikant86/BehatDemo

 

Further to my previous post regarding ‘Behat-Sauce’ integration, ‘Adding Sauce To Behat‘, I am glad to know that there is another Behat and SauceLabs integration from Laura Beth. Thanks a lot Laura for that excellent effort.

On the occasion of Selenium Conference, I met with Noah Sussman talking about “Selenium In the Enterprise: What Went Right, What Went Wrong (So Far)” and one of his slides indicated that, team using Behat and Mink for the functional testing at Etsy. Noah then introduced me to Laura Beth who setup Behat/Mink and SauceLabs integration. Behat-Sauce configuration by Laura Beth is very easy to use.

Now, we will see this in action.

Behat Installation 

Create a ‘Demo’ directory  and Clone the repository from Laura Beth’s GitHub account

moonstar:~ sjagtap$ mkdir Demo
moonstar:~ sjagtap$ cd Demo
moonstar:Demo sjagtap$ git clone https://github.com/elblinkin/Behat-Sauce.git
Cloning into Behat-Sauce...
remote: Counting objects: 178, done.
remote: Compressing objects: 100% (105/105), done.
remote: Total 178 (delta 50), reused 166 (delta 38)
Receiving objects: 100% (178/178), 58.74 MiB | 503 KiB/s, done.
Resolving deltas: 100% (50/50), done.

Ok, you got all the code in ‘Behat-Sauce’ directory. Now you need to download dependencies for Behat. Navigate to Behat-Sauce and download composer.

moonstar:Behat-Sauce sjagtap$ wget  http://getcomposer.org/composer.phar
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  442k  100  442k    0     0   988k      0 --:--:-- --:--:-- --:--:-- 1436k

Now, update ‘composer.phar’ file. It will download all dependencies.

moonstar:Behat-Sauce sjagtap$ php composer.phar update
Updating dependencies
  - Package symfony/yaml (dev-master)
    Cloning 52807f723e8a9743852c2105f11bd01c5af7f977

  - Package symfony/translation (dev-master)
    Cloning cac219a6dee410df41ac5dae15553313f48f1fd1

  - Package symfony/event-dispatcher (dev-master)
    Cloning b98d68d3b8513c62d35504570f09e9d3dc33d083

  - Package symfony/dependency-injection (dev-master)
    Cloning 61e664ab2eead27d83ebb45d2bf83dd55ef509a8

  - Package symfony/config (dev-master)
    Cloning 175adaf7dbed4ad5350e75a4fd3de39480df6cf3

  - Package symfony/console (dev-master)
    Cloning f354e1e5d59261ae03c0fc768bfa4043c0e6ab9c

  - Package symfony/process (dev-master)
    Cloning 3f95a0126588f00d70e745c1ef96631fb10c3a8e

  - Package symfony/css-selector (dev-master)
    Cloning dd695aadd80d8e6e726a7a050535c04325cefa02

  - Package symfony/dom-crawler (dev-master)
    Cloning 69b857977d96e4c726be5524fa00370aef5e9b20

  - Package symfony/browser-kit (dev-master)
    Cloning f03173e232da5d84eb799cad5d57354e6541b0f8

  - Package symfony/finder (dev-master)
    Cloning 5b8658e52eaf424fe943a5857e2404ce95c3b90e

  - Package behat/mink (dev-master)
    Cloning v1.3.3

  - Package behat/behat (dev-master)
    Cloning d8ff3fe0f8c44c664c5eebbb6b972bbdff70c166

  - Package alexandresalome/php-selenium (master-dev)
    Cloning master

  - Package behat/gherkin (v2.1.1)
    Downloading: 100%

symfony/translation suggests installing symfony/config (dev-master)
symfony/translation suggests installing symfony/yaml (dev-master)
symfony/event-dispatcher suggests installing symfony/dependency-injection (dev-master)
symfony/event-dispatcher suggests installing symfony/http-kernel (dev-master)
symfony/dependency-injection suggests installing symfony/yaml (dev-master)
symfony/dependency-injection suggests installing symfony/config (dev-master)
symfony/dom-crawler suggests installing symfony/css-selector (dev-master)
symfony/browser-kit suggests installing symfony/process (dev-master)
Writing lock file
Generating autoload files

You have just installed Behat and all dependencies. Now initialize project by running ‘bin/behat-sauce –init’ command.

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce --init
+d features - place your *.feature files here
+d features/bootstrap - place bootstrap scripts and static files here
+f features/bootstrap/FeatureContext.php - place your feature related code here
+d config - edit you config settings here
+f /Users/sjagtap/Demo/Behat-Sauce/configbehat.yml - place your feature related code here

Once you initialized ‘Behat’. It will ‘features’ and ‘features/bootstrap’ directories and ‘features/bootstrap/FeatureContext.php’ file for you.

Feature file

You can also see ‘config’ directory with ‘behat.yml’ file for you. You need to add SauceLabs ‘Username’ and API key to the ‘behat.yml’.

Now write a simple feature file and save it to ‘features’ directory.

Feature: wikiSearch
  In order to search information on wiki
  As a Wiki user
  I want to get sensible results from site

  @javascript
  Scenario Outline: Search Keywords on wiki
    Given I am on "/"
    And I fill in searchBox with "<input type="text" />"
    When I press search button
Then I should see "<output>"

 Examples:
 | input | output |
 | London | lʌndən/ |

Step Definition

You need implement step definitions using Mink API’s. You feature context file will look like this now.

<!--?php use Behat\Behat\Context\ClosuredContextInterface,     Behat\Behat\Context\TranslatedContextInterface,     Behat\Behat\Exception\PendingException; use Behat\Gherkin\Node\PyStringNode,     Behat\Gherkin\Node\TableNode; use Behat\Sauce\Context\SauceContext; /**  * Features context.  */ class FeatureContext extends SauceContext {     /**      * 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) {         parent::__construct($parameters);     } /**      * @Given /^I fill in searchBox with "([^"]*)"$/      */     public function iFillInSearchboxWith($input)     {         $this--->fillField("searchInput",$input);
    }

    /**
     * @When /^I press search button$/
     */
    public function iPressSearchButton()
    {
        $this->getMink()->getSession()->getDriver()->click("//*[@id='searchButton']");
         $this->getMink()->getSession()->wait("3000");
    }
}

Well, now you are ready to run your tests on SauceLabs just by running

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce

You will see test running on the SauceLabs. Once tests finished running, you will see output like this:

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce
Feature: wikiSearch
  In order to search information on wiki
  As a Wiki user
  I want to get sensible results from site

  @javascript
  Scenario Outline: Search Keywords on wiki # features/wikiSearch.feature:7
    Given I am on "/"                       # FeatureContext::visit()
    And I fill in searchBox with "<input type="text" />"  # FeatureContext::iFillInSearchboxWith()
    When I press search button              # FeatureContext::iPressSearchButton()
Then I should see "<output>" # FeatureContext::assertPageContainsText()

 Examples:
 | input | output |
 | London | lʌndən/ |

1 scenario (1 passed)
4 steps (4 passed)
1m8.949s

You can watch video of the test here

As per Laura Beth, default arguments are:

 --browser              SauceLabs browser name.  Default is:  firefox
 --browser-version      SauceLabs browser version.  Default is:  7
 --os                   SauceLabs operating system.  Default is:  Windows 2003

Now let’s run our tests on different browser and different OS:

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce --browser="firefox" --browser-version="3.6" --os="Linux"

You will see same output:

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce --browser="firefox" --browser-version="3.6" --os="Linux"
Feature: wikiSearch
  In order to search information on wiki
  As a Wiki user
  I want to get sensible results from site

  @javascript
  Scenario Outline: Search Keywords on wiki # features/wikiSearch.feature:7
    Given I am on "/"                       # FeatureContext::visit()
    And I fill in searchBox with "<input type="text" />"  # FeatureContext::iFillInSearchboxWith()
    When I press search button              # FeatureContext::iPressSearchButton()
Then I should see "<output>" # FeatureContext::assertPageContainsText()

 Examples:
 | input | output |
 | London | lʌndən/ |

1 scenario (1 passed)
4 steps (4 passed)
1m38.828s

Video of the tests can be found here

Sauce-Connect:

You can also start Sauce-Connect tunnel with the same credentials that you provided in config/behat.yml file

bin/behat-sauce --tunnel

You will see something like this:

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce --tunnel
[-u, Shashikant86, -k, API Key, -d, sauce-connect.proxy, -s, 127.0.0.1, -p, 80, --ssh-port, 443, -b, --rest-url, https://saucelabs.com/rest/v1, --se-port, 4445, --squid-opts, ]
* Debug messages will be sent to sauce_connect.log
2012-04-24 17:27:32.354:INFO::jetty-7.x.y-SNAPSHOT
2012-04-24 17:27:32.439:INFO::Started SelectChannelConnector@0.0.0.0:50044
.---------------------------------------------------.
| Have questions or need help with Sauce Connect? |
| Contact us: http://support.saucelabs.com/forums |
| Terms of Service: http://saucelabs.com/tos |
-----------------------------------------------------
2012-04-24 17:27:32,509 - / Starting \
2012-04-24 17:27:32,513 - Please wait for "You may start your tests" to start your tests.
2012-04-24 17:27:32,526 - Forwarding: ['sauce-connect.proxy']:['80'] -> 127.0.0.1:['50044']
2012-04-24 17:27:32,538 - Succesfully connected to local server 127.0.0.1:50044 in 6ms
2012-04-24 17:27:33,201 - {"squid_config":[""],"use_caching_proxy":true,"fast_fail_regexps":[""],"ssh_port":443,"metadata":{"PythonVersion":"2.5.1","OwnerHost":"127.0.0.1","Release":"3.0-r18","OwnerPorts":["50044"],"Ports":["80"],"Platform":"Java-1.6.0_26-Java_HotSpot-TM-_64-Bit_Server_VM,_20.1-b02-383,_Apple_Inc.-on-Mac_OS_X-10.7.1-x86_64","Build":"26","ScriptRelease":26,"ScriptName":"sauce_connect"},"use_kgp":true,"domain_names":["sauce-connect.proxy"]}
2012-04-24 17:27:33,486 - Tunnel remote VM is provisioned (a86bd10139b8464081e185b016b6579d)
2012-04-24 17:27:33,756 - Tunnel remote VM is new ..
2012-04-24 17:27:37,068 - Tunnel remote VM is deploying ..
2012-04-24 17:27:40,440 - Tunnel remote VM is booting ..
2012-04-24 17:28:06,611 - Tunnel remote VM is running at maki10148.miso.saucelabs.com
2012-04-24 17:28:06,723 - Succesfully connected to local server 127.0.0.1:50044 in 0ms
2012-04-24 17:28:06,729 - Starting connection to tunnel host...
2012-04-24 17:28:06,732 - Connecting to tunnel host maki10148.miso.saucelabs.com as Shashikant86
2012-04-24 17:28:06,994 - Forwarding Selenium with ephemeral port 50478
2012-04-24 17:28:06.996:INFO::jetty-7.x.y-SNAPSHOT
2012-04-24 17:28:06.998:INFO::Started SelectChannelConnector@0.0.0.0:4445
2012-04-24 17:28:07,000 - Selenium HTTP proxy listening on port 4445
2012-04-24 17:28:07,855 - Successful handshake with Sauce Connect server
2012-04-24 17:28:08,109 - Tunnel host version: 0.1.0, remote endpoint ID: 2851094ae70e4e949a0e96c8ca453748
2012-04-24 17:28:08,112 - Connected! You may start your tests.

Sauce connect is used for testing internal site.

Test Locally:

Well, if you don’t want to waste sauceLabs minutes. You can run your test locally:

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce --local

You will see tests running on local machine with Firefox and output is same:

moonstar:Behat-Sauce sjagtap$ ./bin/behat-sauce --local
Feature: wikiSearch
  In order to search information on wiki
  As a Wiki user
  I want to get sensible results from site

  @javascript
  Scenario Outline: Search Keywords on wiki # features/wikiSearch.feature:7
    Given I am on "/"                       # FeatureContext::visit()
    And I fill in searchBox with "<input type="text" />"  # FeatureContext::iFillInSearchboxWith()
    When I press search button              # FeatureContext::iPressSearchButton()
Then I should see "<output>" # FeatureContext::assertPageContainsText()

 Examples:
 | input | output |
 | London | lʌndən/ |

1 scenario (1 passed)
4 steps (4 passed)
0m16.109s

Contribution:

Well, I have forked repository and started implementing full scale SauceLabs grid which support all browsers &  OS combination. I am also trying to plug the features on continuous integration server like Jenkins. If you also wish to contribute then fork “Behat-Sauce”

Source code:

Code for the above example can be found “Behat-Sauce-Demo” repository.

Conclusion:

Believe me, this is simply awesome. Thanks again Laura Beth.

Happy BDD !!

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: