UA Tes'ng with Selenium and PHPUnit
TrueNorthPHP 2013 Toronto, Canada
���2
• PHP Consultant • President PHPBenelux • Conference speaker
Michelangelo van Dam
���3
Today’s goal
• Set up and use Selenium IDE • Record UA tests • Convert to PHPUnit • Run con'nuously • Mul' browser support
���4
���5
⚠DISCLAIMERS E L E N I U M T E S T S A R E N O T A REPLACEMENT FOR REGULAR UNIT TESTING. THEY ONLY PROVIDE AN ADDITIONAL SET OF TESTS FOCUSED ON U S E R A C C E P T A N C E A N D U S E R EXPERIENCE TESTING.
For more information about unit testing, please see my other material on www.slideshare.net and www.speakerdeck.com. Search for “dragonbe”!
User Acceptance
���6
���7
“Acceptance testing is a test conducted to determine if the requirements of a specification or contract are met.”
!-- source: wikipedia
Checklist for web applica'ons
���8
���9
Func'onal tes'ng
• Test func'onal requirements -‐ e.g. no access to profile without authen'ca'on
• Test UI elements on the web interface -‐ e.g. buTons, form elements, AJAX controls, …
A word of cau'on!
���10
• UA tests only test generated output -‐ not a replacement for unit tes'ng
• UA tests are heavily depending on DOM -‐ changes to the DOM might lead to failing UAT
Browser support
���11
Selenium to the rescue
���12
Plugin for firefox
���13
Get the plugin (demo)
���14
Let’s get started
���16
Pick a test case
���17
Issue #7
���18
Verify this issue on PROD
���19
���20
Fix the issue
���21
Run test to see it’s fixed
���22
���23
���24
Save your test as .html
It’s that easy!
���25
Automated Tes'ng
���26
PHPUnit to the rescue
���27
Export to PHPUnit
���28
The PHPUnit TestCase
���29
<?php class Example extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("http://www.theialive.com/"); } ! public function testMyTestCase() { $this->open("/"); $this->click("link=login"); $this->waitForPageToLoad("30000"); $this->type("id=email", "[email protected]"); $this->type("id=password", "test1234"); $this->click("id=signin"); $this->waitForPageToLoad("30000"); $this->click("link=Test demo"); $this->waitForPageToLoad("30000"); $this->assertEquals("Done", $this->getText("xpath=//th[5]")); $this->click("link=[EDIT]"); $this->waitForPageToLoad("30000"); $this->assertTrue($this->isElementPresent("id=done")); $this->click("link=sign off"); $this->waitForPageToLoad("30000"); } } ?>
Change class name
���30
<?php class Example extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("http://www.theialive.com/"); } ! public function testMyTestCase() { $this->open("/"); $this->click("link=login"); $this->waitForPageToLoad("30000"); $this->type("id=email", "[email protected]"); $this->type("id=password", "test1234"); $this->click("id=signin"); $this->waitForPageToLoad("30000"); $this->click("link=Test demo"); $this->waitForPageToLoad("30000"); $this->assertEquals("Done", $this->getText("xpath=//th[5]")); $this->click("link=[EDIT]"); $this->waitForPageToLoad("30000"); $this->assertTrue($this->isElementPresent("id=done")); $this->click("link=sign off"); $this->waitForPageToLoad("30000"); } } ?>
class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase
The PHPUnit TestCase
���31
<?php class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("http://www.theialive.com/"); } ! public function testMyTestCase() { $this->open("/"); $this->click("link=login"); $this->waitForPageToLoad("30000"); $this->type("id=email", "[email protected]"); $this->type("id=password", "test1234"); $this->click("id=signin"); $this->waitForPageToLoad("30000"); $this->click("link=Test demo"); $this->waitForPageToLoad("30000"); $this->assertEquals("Done", $this->getText("xpath=//th[5]")); $this->click("link=[EDIT]"); $this->waitForPageToLoad("30000"); $this->assertTrue($this->isElementPresent("id=done")); $this->click("link=sign off"); $this->waitForPageToLoad("30000"); } } ?>
protected function setUp() { $this->setBrowser("*iexplore"); $this->setBrowserUrl("http://www.theialive.com/"); $this->setHost('192.168.56.101'); $this->setPort(12666); }
Meaningful method name<?php class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->setBrowser("*iexplore"); $this->setBrowserUrl("http://www.theialive.com/"); $this->setHost('192.168.56.101'); $this->setPort(12666); } ! public function testMyTestCase() { $this->open("/"); $this->click("link=login"); $this->waitForPageToLoad("30000"); $this->type("id=email", "[email protected]"); $this->type("id=password", "test1234"); $this->click("id=signin"); $this->waitForPageToLoad("30000"); $this->click("link=Test demo"); $this->waitForPageToLoad("30000"); $this->assertEquals("Done", $this->getText("xpath=//th[5]")); $this->click("link=[EDIT]"); $this->waitForPageToLoad("30000"); $this->assertTrue($this->isElementPresent("id=done")); $this->click("link=sign off"); $this->waitForPageToLoad("30000"); } } ?>
���32
public function testMarkTestAsDone()
startSeleniumStandAlone.BAT
���33
"C:\Program Files\Java\jre7\bin\java.exe" -jar "C:\Jar\selenium-server-standalone-2.28.0.jar" -port 12666
Now run your tests
���34
How it runs on the node
���36
Advantages
���38
• You can start tes'ng immediately • Even test “hard to test” kind of situa'ons • More nodes for parallel tes'ng • Tes'ng different browsers and plaeorms • Con'nuous Integra'on possible
Next Steps
���39
Mul' Browser support
���40
Base TestCase
���41
<?php !require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; !class TestCase extends PHPUnit_Extensions_SeleniumTestCase { //const TEST_HUB = '217.21.179.192'; const TEST_HUB = '192.168.56.101'; const TEST_PORT = 12666; ! const USERNAME = '[email protected]'; const PASSWORD = 'test1234'; const BASURL = 'http://www.theialive.com'; ! public static $browsers = array ( array ( 'name' => 'Internet Explorer 8 on Windows 7', 'browser' => '*iexplore', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Firefox on Windows 7', 'browser' => '*firefox', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Google Chrome on Windows 7', 'browser' => '*googlechrome', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), ); ! protected function setUp() { $this->setBrowserUrl(self::BASURL); } }
Base TestCase
���42
<?php !require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; !class TestCase extends PHPUnit_Extensions_SeleniumTestCase { //const TEST_HUB = '217.21.179.192'; const TEST_HUB = '192.168.56.101'; const TEST_PORT = 12666; ! const USERNAME = '[email protected]'; const PASSWORD = 'test1234'; const BASURL = 'http://www.theialive.com'; ! public static $browsers = array ( array ( 'name' => 'Internet Explorer 8 on Windows 7', 'browser' => '*iexplore', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Firefox on Windows 7', 'browser' => '*firefox', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Google Chrome on Windows 7', 'browser' => '*googlechrome', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), ); ! protected function setUp() { $this->setBrowserUrl(self::BASURL); } }
array ( 'name' => 'Internet Explorer 8 on Windows 7', 'browser' => '*iexplore', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ),
Base TestCase
���43
<?php !require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; !class TestCase extends PHPUnit_Extensions_SeleniumTestCase { //const TEST_HUB = '217.21.179.192'; const TEST_HUB = '192.168.56.101'; const TEST_PORT = 12666; ! const USERNAME = '[email protected]'; const PASSWORD = 'test1234'; const BASURL = 'http://www.theialive.com'; ! public static $browsers = array ( array ( 'name' => 'Internet Explorer 8 on Windows 7', 'browser' => '*iexplore', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Firefox on Windows 7', 'browser' => '*firefox', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Google Chrome on Windows 7', 'browser' => '*googlechrome', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), ); ! protected function setUp() { $this->setBrowserUrl(self::BASURL); } }
array ( 'name' => 'Firefox on Windows 7', 'browser' => '*firefox', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ),
Base TestCase
���44
<?php !require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; !class TestCase extends PHPUnit_Extensions_SeleniumTestCase { //const TEST_HUB = '217.21.179.192'; const TEST_HUB = '192.168.56.101'; const TEST_PORT = 12666; ! const USERNAME = '[email protected]'; const PASSWORD = 'test1234'; const BASURL = 'http://www.theialive.com'; ! public static $browsers = array ( array ( 'name' => 'Internet Explorer 8 on Windows 7', 'browser' => '*iexplore', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Firefox on Windows 7', 'browser' => '*firefox', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), array ( 'name' => 'Google Chrome on Windows 7', 'browser' => '*googlechrome', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ), ); ! protected function setUp() { $this->setBrowserUrl(self::BASURL); } }
array ( 'name' => 'Google Chrome on Windows 7', 'browser' => '*googlechrome', 'host' => self::TEST_HUB, 'port' => self::TEST_PORT, ),
Modify MarkTaskDoneTest <?php /** * Class MarkTaskDoneTest * * @group Selenium */ require_once 'TestCase.php'; class MarkTaskDoneTest extends TestCase { public function testMarkTestAsDone() { $this->open("/"); $this->click("link=login"); $this->waitForPageToLoad("30000"); $this->type("id=email", TestCase::USERNAME); $this->type("id=password", TestCase::PASSWORD); $this->click("id=signin"); $this->waitForPageToLoad("30000"); $this->click("link=Test demo"); $this->waitForPageToLoad("30000"); $this->assertEquals("Done", $this->getText("xpath=//th[5]")); $this->click("link=[EDIT]"); $this->waitForPageToLoad("30000"); $this->assertTrue($this->isElementPresent("id=done")); $this->click("link=sign off"); $this->waitForPageToLoad("30000"); } }
���45
Require the TestCase and extend it
Running test
���46
���47
Benefits
• run your tests on mul'ple browsers • detect flaws in specific browsers (e.g. IE6) -‐ adapt your apps to solve these flaws
���48
Mul'ple Node Setup
���49
The GRID
���50
• Procedure -‐ centralized server (HUB)
-‐ commands clients (nodes) registered
-‐ and executes the tests
• Goal -‐ allow for automa'on
-‐ adding clients as you go
Selenium Grid Setup
���51
Selenium Testing
CI Server Windows"HUB"
Linux client"NODE"
CI executes tests
Windows HUB launchesSelenium node clients to execute tests
Windows Server collectsfeedback from the Citrixclient nodes and reportsback to CI Server
Windows client"NODE"
Mac OS X client"NODE"
Continuous User Acceptance Testing
Star'ng the server [HUB]
���52
"C:\Program Files\Java\jre7\bin\java.exe" -jar "C:\Jar\selenium-server-standalone-2.28.0.jar" -role hub -port 12666
Star'ng the client [NODE]
���53
"C:\Program Files\Java\jre7\bin\java.exe" -jar "C:\Jar\selenium-server-standalone-2.28.0.jar" -role node -host 192.168.56.103 -port 13666 -hub http://192.168.56.101:12666/grid/register
Mul'ple nodes
���54
Problem
���55
Modify Base TestCase
���56
<?php !require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; !class TestCase extends PHPUnit_Extensions_SeleniumTestCase { const TEST_HUB_WIN = '192.168.56.101'; const TEST_HUB_MAC = '192.168.56.1'; const TEST_HUB_LINUX = '192.168.56.102'; const TEST_PORT = 13666; ! const USERNAME = '[email protected]'; const PASSWORD = 'test1234'; const BASURL = 'http://www.theialive.com'; ! public static $browsers = array ( array ( 'name' => 'Internet Explorer 8 on Windows 7', 'browser' => '*iexplore', 'host' => self::TEST_HUB_WIN, 'port' => self::TEST_PORT, ), array ( 'name' => 'Firefox on Mac OS X', 'browser' => '*firefox', 'host' => self::TEST_HUB_MAC, 'port' => self::TEST_PORT, ), array ( 'name' => 'Google Chrome on Linux', 'browser' => '*googlechrome', 'host' => self::TEST_HUB_LINUX, 'port' => self::TEST_PORT, ), ); ! protected function setUp() { $this->setBrowserUrl(self::BASURL); } }
More informa'on
���57
seleniumhq.org
���58
phpunit.de
���59
http://www.phpunit.de/manual/3.5/en/selenium.html
Credits
���60
• michelangelo: hTp://www.flickr.com/photos/akrabat/8784318813
• apple store: hTp://www.flickr.com/photos/jtjdt/3571748777 • checklist: hTp://www.flickr.com/photos/alancleaver/4439276478 • flat 're: hTp://www.flickr.com/photos/anijdam/2468493546/ • first place: hTp://www.flickr.com/photos/evelynishere/3417340248/
• gears: hTp://www.flickr.com/photos/wwarby/4782904694 • steps: hTp://www.flickr.com/photos/ben_salter/1407168763 • browsers: hTp://www.flickr.com/photos/richoz/3791167457 • informa'on: hTp://www.flickr.com/photos/twicepix/2650241408/
• elephpant: hTp://www.flickr.com/photos/drewm/3191872515
Contact
���61
Michelangelo van Dam Zend Certified Engineer !email: [email protected]
Contact us for Consultancy - Training - QA - Webdesign
Thank you
���63