Archive | Sahi RSS feed for this section

PHPUnit + Behat/Mink + Page Object: The Rockstar Combination of Testing

7 Apr

Last month, we had discussion about implementing page object pattern in Behat/Mink framework at London Behat Users meetup . Page object pattern is a cool way to make tests maintainable, reusable and readable. Everyone was interested to know more about Page Object Pattern.

In this short tutorial, we will implement Mink and PHPUnit  combination for functional testing. Mink and PHPUnit combined with Pageness (Page Object) can be used for maintainable and readable tests. Mink is a web acceptance testing framework for PHP application. Mink has clean API’s which allows browsers emulation and browser controls. Mink has headless browser emulators as well as browser controls which covers all browsers interactions. PHPUnit is testing framework for PHP applications.

Installations

Lets start with some installations assuming PHP, Pear package is already installed.

Install PHPUnit

Now, upgrade pear package & install PHPUnit

$ pear update-channels
$ sudo pear channel-discover pear.phpunit.de
$ sudo pear channel-discover pear.symfony-project.com
$ pear channel-discover components.ez.no
$ sudo pear install –alldeps phpunit/PHPUnit
$ phpunit --version

Install Behat/Mink

$ pear channel-discover pear.symfony.com
$ pear channel-discover pear.behat.org
$ pear install behat/mink

Mink is ready to use just including in PHP classes.

require_once 'mink/autoload.php';

PHPUnit-Mink Framework on GitHub

PHPUnit-Mink framework designed to use combination of PHPUnit, Mink and Page Object Pattern to write functional tests with various browser emulators like Goutte, Selenium, Sahi and WebDriver. PHPUnit-Mink Framework has used Mink and PHPUnit to write tests. Driver support for Selenium, Sahi, WebDriver for browser emulation. Test Report Generation which can plugged in Continuous Integration server. Page Objects which can be used directly in tests. Abstracted common elements up in the framework in order to make it maintainable.

How to use:

  • Clone GitHub Repository
$git clone git@github.com:Shashi-ibuildings/PHPUnit-Mink.git
$cd PHPUnit-Mink
  • Start your Driver

Sahi Driver :

Download sahi zip file from SourceForge

Now launch Sahi Server using command below:

$ cd /path/to/sahi
$ cd userdata/bin
$./start_sahi.sh 

Selenium Driver:

You need to download selenium server jar file and execute following command:

$ cd /path/to/selenium-server
$java -jar selenium-server-standalone-2.20.0.jar 

In this tutorial, we are using sahi driver.

  • Now run tests using ANT
$cd /path/to/PHPUnit-Mink
$ant Mink

Directory structure

  1. conf    : YAML files can be used with Behat
  2. core    : Abstracted common elements/ methods
  3. Page   : Page objects (reusable Methods for page)
  4. report :  Generate Junit, Agile doc reports
  5. tests    :  PHPUnit tests using Mink Api’s

Don’t forget to include Mink and PHPUnit in Test like this:

<?php
require_once 'mink/autoload.php';
use Behat\Mink\Mink,
Behat\Mink\PHPUnit\TestCase;

Page Objects Pattern

There are some areas within application UI where your test interacts with. These areas can be identified by their functionality, they offer e.g login, registration, search etc. Page object pattern models as a object within you test code. While writing tests, we just need to create an object of the page and access methods and variables withing that page objects. This approach is useful when UI changes, we need to make changes in page objects not in the tests. Tests become readable and maintainable using page objects.

Page objects classes generally:

  1. Set of public methods that page offer which can be reused later.
  2. don’t make any assertion. Assertions can be added later into tests not in the page objects
  3. checks if user is on the same page that page object is created.
  4. don’t represent entire page but some important functions of that particular page.

GitHub & Other sources of Page object pattern

Read more about page object on  google wiki. There are couple of GitHub repositories that explains page object pattern, Saunter and pelenium

Writing Page Objects:

Common methods can be abstracted in the ‘page’ directory. You can specify driver of your choice. Now we have test with Sahi session. Example page looks like this

<?php
require_once 'mink/autoload.php';
use Behat\Mink\Mink,
Behat\Mink\PHPUnit\TestCase;
require_once 'core/core_PHPUnitMink_CommonElementFunctions.php';
class page_search extends TestCase
{
function search($input)
{
$this->getSession('sahi')->getPage()->fillField("searchInput",$input);
$this->getMink()->getSession('sahi')->getDriver()->click("//*[@id='searchButton']");
$this->getMink()->getSession('sahi')->wait("3000");
}
}
?

Using Page Objects in Tests

You can use pages just by creating new objects and accessing variables,methods in the test. Example of test looks like this

<?php
class wikiSearchTest extends core_PHPUnitMink_CommonElementFunctions
{
protected static $mink;</pre>
public function testwikiSearchsingle()
 {
 $page = new page_search($this):
 $page->visit();
 $page->search(“mumbai”);
<pre>assertEquals(“Mumbai”, $page->findFirstHeading()));
}

Writing Data-Driven Tests

You can write data driven tests by using PHPUnit and Mink combination. Data can be placed in CSV or in an array. Example data-driven test looks like this

<?php
class wikiSearchTest extends core_PHPUnitMink_CommonElementFunctions
{
protected static $mink;
function searchData() {
return array(
array('london','London'),
array('newyork','New York')
);
}
/**
*
* @param &lt;type&gt; $searchfor
* @param &lt;type&gt; $expectedResult
* @dataProvider searchData
*/

public function testwikiSearchMultiple($input,$output)
{
$this->getSession('sahi')
->visit('http://en.wikipedia.org/wiki/Main_Page');
$this->getSession('sahi')->getPage()->fillField("searchInput",$input);
$this->getMink()->getSession('sahi')->getDriver()->click("//*[@id='searchButton']");
$this->getMink()->getSession('sahi')->wait("3000");
assertEquals($output, $this->getMink()->getSession('sahi')->getDriver()->getText(".//*[@id='firstHeading']/span"));
}

}

Starting Engines

Before running tests, you need to start Mink drivers, here we are using Sahi. You can update tests to run Selenium driver. Launch driver from command line like this:

  • Sahi : Navigate to Sahi directory and run:
moonstar:~ sjagtap$ cd sahi/userdata/bin/
moonstar:bin sjagtap$ ./start_sahi.sh
--------
SAHI_HOME: ../..
SAHI_USERDATA_DIR: ../../userdata
SAHI_EXT_CLASS_PATH:
--------
Sahi properties file = /Users/sjagtap/sahi/config/sahi.properties
Sahi user properties file = /Users/sjagtap/sahi/userdata/config/userdata.properties
Added shutdown hook.
&gt;&gt;&gt;&gt; Sahi started. Listening on port: 9999
&gt;&gt;&gt;&gt; Configure your browser to use this server and port as its proxy
&gt;&gt;&gt;&gt; Browse any page and CTRL-ALT-DblClick on the page to bring up the Sahi Controller
-----
Reading browser types from: /Users/sjagtap/sahi/userdata/config/browser_types.xml
-----
  • Selenium
moonstar:downloads sjagtap$ java -jar selenium-server-standalone-2.20.0.jar
Apr 7, 2012 3:34:19 PM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a standalone server
1 [main] INFO org.openqa.selenium.server.SeleniumServer - Java: Apple Inc. 20.1-b02-383
1 [main] INFO org.openqa.selenium.server.SeleniumServer - OS: Mac OS X 10.7.1 x86_64
8 [main] INFO org.openqa.selenium.server.SeleniumServer - v2.20.0, with Core v2.20.0. Built from revision 16008
131 [main] INFO org.openqa.selenium.server.SeleniumServer - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
132 [main] INFO org.openqa.jetty.http.HttpServer - Version Jetty/5.1.x
132 [main] INFO org.openqa.jetty.util.Container - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
133 [main] INFO org.openqa.jetty.util.Container - Started HttpContext[/selenium-server,/selenium-server]
133 [main] INFO org.openqa.jetty.util.Container - Started HttpContext[/,/]
273 [main] INFO org.openqa.jetty.util.Container - Started org.openqa.jetty.jetty.servlet.ServletHandler@62f47396
273 [main] INFO org.openqa.jetty.util.Container - Started HttpContext[/wd,/wd]
279 [main] INFO org.openqa.jetty.http.SocketListener - Started SocketListener on 0.0.0.0:4444
279 [main] INFO org.openqa.jetty.util.Container - Started org.openqa.jetty.jetty.Server@4a79717e

Running Tests with PHPUnit

Now you can run wikisearch test with PHPUnit like this :

moonstar:PHPUnit-Mink sjagtap$ phpunit tests/wikiSearchTest.php

Temporary SauceLabs fork 3.5.24 of PHPUnit by Sebastian Bergmann. Supports parallel testing. Becomes obsolete when PHPUnit 3.7.0 is released.

...

Time: 33 seconds, Memory: 11.25Mb

OK (3 tests, 3 assertions)

Running Tests with Ant

You can run tests using apache ANT. Navigate to project root directory (PHPUnit-Mink) and run an

moonstar:PHPUnit-Mink sjagtap$ ant Mink
Buildfile: /Users/sjagtap/PHPUnit-Mink/build.xml
[delete] Deleting directory /Users/sjagtap/PHPUnit-Mink/report
[mkdir] Created dir: /Users/sjagtap/PHPUnit-Mink/report

Mink:
[exec]
[exec]
[exec]
[exec]
[exec] Temporary SauceLabs fork 3.5.24 of PHPUnit by Sebastian Bergmann. Supports parallel testing. Becomes obsolete when PHPUnit 3.7.0 is released.
[exec]
[exec] ....
[exec]
[exec] Time: 45 seconds, Memory: 11.75Mb
[exec]
OK (4 tests, 4 assertions)

BUILD SUCCESSFUL
Total time: 46 seconds
moonstar:PHPUnit-Mink sjagtap$ 

Once all tests finished running, you will see build successful message. This build can be easily plugged into Continuous Integration server like Jenkins.

Conclusion:

Functional testing become much easier with use of Mink with PHPUnit. Page Object pattern can be used with PHPUnit-Mink to make tests reusable and readable.

You can find source code on GitHub PHPUnit-Mink repository. Happy PHP Testing !

Advertisements

Web Acceptance Testing Framework for PHP

9 Jan

Web Acceptance Testing Framework for PHP

A Web acceptance testing  framework for PHP is now available on GitHub. It can be used for web acceptance testing of the PHP projects. This framework is build around Behat, Mink, Sauce Labs and ANT. You can configure it with a continuous integration server like Jenkins.

Behat is a BDD framework for PHP.  Behat comes up with Mink  which is used for browser emulation (functional testing) where browser interaction takes place. Behat and Mink combination is used for web acceptance testing.

 Key features of web acceptance testing framework

  • Selenium and Sahi servers are plugged into build file, user doesn’t need to download or launch Selenium or Sahi server while running features with ANT or Jenkins.
  • Test reports are generated in HTML and xml format in “/report” directory.
  • Easy switching over to another driver. You can run tests using any available drivers, just by specifying name of them.
  • Framework is integrated with cloud testing service called “Sauce Labs”. You can run your features in cloud with selenium driver.
  • Testers can get started easily without any hassles.
  • With little changes in config file, it is ready for your project.

Behat for Testers

Testers might have tried Cucumber & Selenium or Cucumber & capybara combination for Ruby projects. BDD for testers could be very interesting topic to discuss. Testers can now use BDD framework for PHP project as well. Thanks to Behat !

Behat has provided lot of driver options for testers. Its not limited to selenium. It has following mink drivers.

Tester can pick one of these and start implementing features. Goutte can be used for tests which doesn’t need browser interaction. Tester can always switch to another driver if feature is failing for one of the driver. There are some pro’s and con’s of each driver


Sahi Selenium Webdriver




Implicit Wait Yes No Yes
Hidden Link Access Yes Yes No
Sauce Lab Support No Yes No
Speed Medium Medium Fast
Https sites testing Hectic, need to add certificate exception Accepts certificated automatically Accepts certificated automatically

It is very important to choose right driver for your testing. It depends on your application and requirement. This framework makes it easy to switch over to another driver.

What you need to use framework?

Install Behat using Behat documentation which explained all these methods in simple way. Similarly install mink using Mink documentation.

  • Create Your Project

Initiate Behat:

$ behat --init
  • Clone Web Acceptance testing  Framework from GitHub

  1. Clone test framework from Github into your local machine.
  2. Make sure you have initialized Behat in your root directory, currently its “Behat”.
  3. Now you are ready to use the framework for adding features and running them with different drivers like Selenium, Sahi or webdriver.
  • How to use framework?
  1. Change “base_url” “browser” parameter in all config files like ‘behat.yml’, ‘sahi.yml’, ‘selenium.yml’, and ‘webdriver.yml’ as per your project requirement. eg change in sahi.yml file as shown below
default:
context:
parameters:
javascript_session: sahi
base_url: http://{your url}
browser: {your browser}
show_cmd: open %s 

Run features locally

To run feature locally, you need to start Selenium or Sahi server before executing them.

Download Selenium or Sahi and launch Selenium or Sahi server as shown below

Selenium Server

You need to download selenium server jar file and execute following command:

$ cd /path/to/selenium-server
$java -jar selenium-server-standalone-2.15.0.jar 

Sahi Server

Download sahi zip file from SourceForge

Now launch Sahi Server using command below:

$ cd /path/to/sahi
$ cd userdata/bin
$bash start_sahi.sh

Now you can run behat command to run feature locally

$ cd /path/to/behat
$behat --name wikiSearch (your feature)

You can see feature running on your local host.

  • How to run features using ANT

Requirement
You need to install Apache Ant on your localhost. You can download and install Ant from Apache Ant website.

No need install or download selenium or Sahi. It is configured inside this framework. Ant will automatically launch selenium or Sahi server still you need to update version of selenium server frequently.

Now you got three drivers options to run your features

  1. Sahi Driver
  2. Selenium Driver
  3. Selenium 2 Driver (webdriver)
  • Run feature with selenium driver
$ cd /path/to/my/project
$ant runSelenium 
  • Run feature with Sahi driver.
$ cd /path/to/my/project
$ant runSahi 
  • Run feature with webdriver
$ cd /path/to/my/project
$ant runWebdriver
$ cd /path/to/my/project
$ant sauceTests 

If you are using selenium driver, then you have to implement wait in your step definitions every time there is new page is loaded like this:

$this->getMink()->getSession()->wait("3000");

Sahi driver waits automatically for element to be appear on page or page to load. You don’t have to implement wait if you would like to use Sahi driver.

Once you run ‘ant’ command from terminal you will see your feature running in browser, you configured.You will see reports generated in “/report” directory. There will be HTML reports as well.

Configure Jenkins to run features

 

  • Download & Launch Jenkins by executing below command:
$  java -jar jenkins.war

Visit url : http://localhost:8080 to access Jenkins in browser. You can specify different port to launch Jenkins.

  • Create new Build a free-style software project and name it “Behat”
  • Configure job by specifying your repository.(Git, SVN, CSV)
  • You need to Invoke Ant as shown below

Jenkins Configuration

If you wish to run tests using Sahi driver then specify target as “runSahi”

You can see reports generated once you run your feature.

Conclusion

Using web acceptance test framework for PHP, you can write features and run them easily on ANT, Jenkins and Sauce labs with choice of available drivers.

Happy BDD for testers !! Any questions or comment mention me @Shashikant86 on Twitter.