SlideShare a Scribd company logo
UA	
  Tes'ng	
  with
Selenium	
  and	
  PHPUnit
TrueNorthPHP	
  2013	
  
Toronto,	
  Canada
Michelangelo	
  van	
  Dam
• PHP	
  Consultant	
  
• President	
  PHPBenelux	
  
• Conference	
  speaker

2
3
Today’s	
  goal
• Set	
  up	
  and	
  use	
  Selenium	
  IDE	
  
• Record	
  UA	
  tests	
  
• Convert	
  to	
  PHPUnit	
  
• Run	
  con'nuously	
  
• Mul'	
  browser	
  support
4
DISCLAIMER
SELENIUM TESTS ARE NOT 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 TA 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”!
5
User	
  Acceptance

6
“Acceptance testing is a test conducted to determine if
the requirements of a specification or contract are met.”	

!

-- source: wikipedia

7
Checklist	
  for	
  web	
  applica'ons

8
Func'onal	
  tes'ng

• Test	
  func'onal	
  requirements	
  
-­‐

e.g.	
  no	
  access	
  to	
  profile	
  without	
  authen'ca'on	
  

-­‐

e.g.	
  buTons,	
  form	
  elements,	
  AJAX	
  controls,	
  …

• Test	
  UI	
  elements	
  on	
  the	
  web	
  interface	
  

9
A	
  word	
  of	
  cau'on!

• UA	
  tests	
  only	
  test	
  generated	
  output	
  
-­‐

not	
  a	
  replacement	
  for	
  unit	
  tes'ng	
  

-­‐

changes	
  to	
  the	
  DOM	
  might	
  lead	
  to	
  failing	
  UAT

• UA	
  tests	
  are	
  heavily	
  depending	
  on	
  DOM	
  

10
Browser	
  support

11
Selenium	
  to	
  the	
  rescue

12
Plugin	
  for	
  firefox

13
Get	
  the	
  plugin	
  (demo)

14
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
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
Save	
  your	
  test	
  as	
  .html

24
It’s	
  that	
  easy!

25
Automated	
  Tes'ng

26
PHPUnit	
  to	
  the	
  rescue

27
Export	
  to	
  PHPUnit

28
The	
  PHPUnit	
  TestCase
?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, dragonbe+tek13@gmail.com);
$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);
}

29
Change	
  class	
  name
?php
class Example extends PHPUnit_Extensions_SeleniumTestCase
{
protected function setUp()
{
$this-setBrowser(*chrome);
class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase
$this-setBrowserUrl(http://www.theialive.com/);
}

!

}
?

public function testMyTestCase()
{
$this-open(/);
$this-click(link=login);
$this-waitForPageToLoad(30000);
$this-type(id=email, dragonbe+tek13@gmail.com);
$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);
}

30
The	
  PHPUnit	
  TestCase
?php
class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase
{
protected function setUp()
{
$this-setBrowser(*chrome);
$this-setBrowserUrl(http://www.theialive.com/);
}

!

}
?

public function testMyTestCase()
{
protected function setUp()
$this-open(/);
{
$this-click(link=login);
$this-waitForPageToLoad(30000);
$this-setBrowser(*iexplore);
$this-type(id=email, dragonbe+tek13@gmail.com);
$this-setBrowserUrl(http://www.theialive.com/);
$this-type(id=password, test1234);
$this-click(id=signin);
$this-setHost('192.168.56.101');
$this-waitForPageToLoad(30000);
$this-setPort(12666);
$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);
}

31
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);
public function testMarkTestAsDone()
$this-type(id=email, dragonbe+tek13@gmail.com);
$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
startSeleniumStandAlone.BAT
C:Program FilesJavajre7binjava.exe
-jar C:Jarselenium-server-standalone-2.28.0.jar
-port 12666

33
Now	
  run	
  your	
  tests

34
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
How	
  it	
  runs	
  on	
  the	
  node

36
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
Advantages
• 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
38
Next	
  Steps

39
Mul'	
  Browser	
  support

40
Base	
  TestCase
?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 = 'dragonbe+tek13@gmail.com';
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);
}

41
Base	
  TestCase
?php

! array (
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
!
'name' = 'Internet Explorer 8 on Windows 7',
class TestCase extends PHPUnit_Extensions_SeleniumTestCase
'browser' = '*iexplore',
{
//const TEST_HUB = '217.21.179.192';
const 'host'= = self::TEST_HUB,
TEST_HUB
'192.168.56.101';
const 'port' == self::TEST_PORT,
TEST_PORT
12666;
!
), USERNAME = 'dragonbe+tek13@gmail.com';
const
!

!
}

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);
}

42
Base	
  TestCase
?php

!
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
!
class TestCase extends PHPUnit_Extensions_SeleniumTestCase
{ array (
//const TEST_HUB = '217.21.179.192';
const 'name'= = 'Firefox on Windows 7',
TEST_HUB
'192.168.56.101';
const TEST_PORT = 12666;
'browser' = '*firefox',
!
const 'host'= = self::TEST_HUB,
USERNAME
'dragonbe+tek13@gmail.com';
const PASSWORD = 'test1234';
const 'port''http://www.theialive.com';
BASURL =
= self::TEST_PORT,
! ),
public static $browsers = array (

!
}

);

array (
'name'
'host'
),
array (
'name'
'host'
),
array (
'name'
'host'
),

= 'Internet Explorer 8 on Windows 7', 'browser' = '*iexplore',
= self::TEST_HUB, 'port' = self::TEST_PORT,
= 'Firefox on Windows 7', 'browser' = '*firefox',
= self::TEST_HUB, 'port' = self::TEST_PORT,
= 'Google Chrome on Windows 7', 'browser' = '*googlechrome',
= self::TEST_HUB, 'port' = self::TEST_PORT,

protected function setUp()
{
$this-setBrowserUrl(self::BASURL);
}

43
Base	
  TestCase
?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;

! array (
const USERNAME = 'dragonbe+tek13@gmail.com';
const 'name'= = 'Google Chrome on Windows 7',
PASSWORD
'test1234';
const BASURL = 'http://www.theialive.com';
'browser' = '*googlechrome',
!
public static $browsers = array (
'host' = self::TEST_HUB,
array (
'port'== self::TEST_PORT, 7', 'browser' = '*iexplore',
'name'
'Internet Explorer 8 on Windows
), ), 'host' = self::TEST_HUB, 'port' = self::TEST_PORT,

!
}

);

array (
'name'
'host'
),
array (
'name'
'host'
),

= 'Firefox on Windows 7', 'browser' = '*firefox',
= self::TEST_HUB, 'port' = self::TEST_PORT,
= 'Google Chrome on Windows 7', 'browser' = '*googlechrome',
= self::TEST_HUB, 'port' = self::TEST_PORT,

protected function setUp()
{
$this-setBrowserUrl(self::BASURL);
}

44
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);
}
}

Require the TestCase
and extend it

45
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
• Procedure	
  
-­‐
-­‐
-­‐

centralized	
  server	
  (HUB)	
  
commands	
  clients	
  (nodes)	
  registered	
  
and	
  executes	
  the	
  tests	
  

-­‐
-­‐

allow	
  for	
  automa'on	
  
adding	
  clients	
  as	
  you	
  go

• Goal	
  

50
Selenium	
  Grid	
  Setup
Selenium Testing
Windows HUB launches
Selenium node clients
to execute tests

CI executes tests

Windows client
NODE

Linux client
NODE
CI Server

Windows
HUB
Windows Server collects
feedback from the Citrix
client nodes and reports
back to CI Server

Mac OS X client
NODE

Continuous User Acceptance Testing

51
Star'ng	
  the	
  server	
  [HUB]
C:Program FilesJavajre7binjava.exe
-jar C:Jarselenium-server-standalone-2.28.0.jar
-role hub
-port 12666

52
Star'ng	
  the	
  client	
  [NODE]
C:Program FilesJavajre7binjava.exe
-jar C:Jarselenium-server-standalone-2.28.0.jar
-role node
-host 192.168.56.103
-port 13666
-hub http://192.168.56.101:12666/grid/register

53
Mul'ple	
  nodes

54
Problem

55
Modify	
  Base	
  TestCase
?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 = 'dragonbe+tek13@gmail.com';
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);
}

56
More	
  informa'on

57
seleniumhq.org

58
phpunit.de
http://www.phpunit.de/manual/3.5/en/selenium.html

59
Credits
• 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
60
Contact
Michelangelo van Dam
Zend Certified Engineer	

!

email: michelangelo@in2it.be	

Contact us for	

Consultancy - Training - QA - Webdesign

61
https://joind.in/10018

62
Thank	
  you

63

More Related Content

What's hot (20)

PDF
Beginning PHPUnit
Jace Ju
 
PDF
13 PHPUnit #burningkeyboards
Denis Ristic
 
PDF
What's new with PHP7
SWIFTotter Solutions
 
KEY
PHP security audits
Damien Seguy
 
PDF
Тестирование и Django
MoscowDjango
 
PDF
Django - Know Your Namespace: Middleware
howiworkdaily
 
PDF
Zf2 how arrays will save your project
Michelangelo van Dam
 
PDF
OWASP Top 10 at International PHP Conference 2014 in Berlin
Tobias Zander
 
PPT
SQL Injection in PHP
Dave Ross
 
PDF
Top5 scalabilityissues
ColdFusionConference
 
ODP
My app is secure... I think
Wim Godden
 
PDF
Your code are my tests
Michelangelo van Dam
 
PDF
WebCamp: Developer Day: Web Security: Cookies, Domains and CORS - Юрий Чайков...
GeeksLab Odessa
 
PPT
Unit testing
davidahaskins
 
KEY
Fatc
Wade Arnold
 
PPT
PHP Security
Mindfire Solutions
 
ODP
Beyond PHP - it's not (just) about the code
Wim Godden
 
KEY
Php Unit With Zend Framework Zendcon09
Michelangelo van Dam
 
PDF
Обзор фреймворка Twisted
Maxim Kulsha
 
PDF
Unit testing after Zend Framework 1.8
Michelangelo van Dam
 
Beginning PHPUnit
Jace Ju
 
13 PHPUnit #burningkeyboards
Denis Ristic
 
What's new with PHP7
SWIFTotter Solutions
 
PHP security audits
Damien Seguy
 
Тестирование и Django
MoscowDjango
 
Django - Know Your Namespace: Middleware
howiworkdaily
 
Zf2 how arrays will save your project
Michelangelo van Dam
 
OWASP Top 10 at International PHP Conference 2014 in Berlin
Tobias Zander
 
SQL Injection in PHP
Dave Ross
 
Top5 scalabilityissues
ColdFusionConference
 
My app is secure... I think
Wim Godden
 
Your code are my tests
Michelangelo van Dam
 
WebCamp: Developer Day: Web Security: Cookies, Domains and CORS - Юрий Чайков...
GeeksLab Odessa
 
Unit testing
davidahaskins
 
PHP Security
Mindfire Solutions
 
Beyond PHP - it's not (just) about the code
Wim Godden
 
Php Unit With Zend Framework Zendcon09
Michelangelo van Dam
 
Обзор фреймворка Twisted
Maxim Kulsha
 
Unit testing after Zend Framework 1.8
Michelangelo van Dam
 

Viewers also liked (8)

PPTX
Policy and procedure
Abdullah831412
 
PPT
Sacudete
cpervar
 
PDF
In search for a good practice of finding information
Kristian Norling
 
PDF
Bouwkennis - crowdfunding in de bouw
Ronald Kleverlaan
 
PDF
Meeting the Retirement Challenge
Steven Reta
 
PDF
Crowdfunding voor religieus erfgoed - kerken
Ronald Kleverlaan
 
PPT
Open data policy in Catalonia. New European judicial framework for opening ac...
gencat .
 
PDF
Guia Hootsuite CAT
gencat .
 
Policy and procedure
Abdullah831412
 
Sacudete
cpervar
 
In search for a good practice of finding information
Kristian Norling
 
Bouwkennis - crowdfunding in de bouw
Ronald Kleverlaan
 
Meeting the Retirement Challenge
Steven Reta
 
Crowdfunding voor religieus erfgoed - kerken
Ronald Kleverlaan
 
Open data policy in Catalonia. New European judicial framework for opening ac...
gencat .
 
Guia Hootsuite CAT
gencat .
 
Ad

Similar to UA testing with Selenium and PHPUnit - TrueNorthPHP 2013 (20)

PDF
Better Testing With PHP Unit
sitecrafting
 
PDF
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
PDF
Leveling Up With Unit Testing - php[tek] 2023
Mark Niebergall
 
PDF
symfony on action - WebTech 207
patter
 
PDF
Selenium rc presentation_20110104
Michael Salvucci
 
PDF
Selenium RC Presentation 20110104
Michael Salvucci
 
PDF
Unit testing with zend framework tek11
Michelangelo van Dam
 
KEY
Unit testing with zend framework PHPBenelux
Michelangelo van Dam
 
PPT
Selenium
husnara mohammad
 
KEY
Unit testing zend framework apps
Michelangelo van Dam
 
PDF
PHPunit and you
markstory
 
PDF
PHPUnit best practices presentation
Thanh Robi
 
PDF
Unit Testing from Setup to Deployment
Mark Niebergall
 
PDF
Browser testing with nightwatch.js - Drupal Europe
Salvador Molina (Slv_)
 
PDF
2010 07-28-testing-zf-apps
Venkata Ramana
 
ZIP
Browser-Based testing using Selenium
ret0
 
PDF
PHPUnit your bug exterminator
rjsmelo
 
PDF
Leveling Up With Unit Testing - LonghornPHP 2022
Mark Niebergall
 
PDF
Getting started with TDD - Confoo 2014
Eric Hogue
 
PDF
Charla EHU Noviembre 2014 - Desarrollo Web
Mikel Torres Ugarte
 
Better Testing With PHP Unit
sitecrafting
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
Leveling Up With Unit Testing - php[tek] 2023
Mark Niebergall
 
symfony on action - WebTech 207
patter
 
Selenium rc presentation_20110104
Michael Salvucci
 
Selenium RC Presentation 20110104
Michael Salvucci
 
Unit testing with zend framework tek11
Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Michelangelo van Dam
 
Unit testing zend framework apps
Michelangelo van Dam
 
PHPunit and you
markstory
 
PHPUnit best practices presentation
Thanh Robi
 
Unit Testing from Setup to Deployment
Mark Niebergall
 
Browser testing with nightwatch.js - Drupal Europe
Salvador Molina (Slv_)
 
2010 07-28-testing-zf-apps
Venkata Ramana
 
Browser-Based testing using Selenium
ret0
 
PHPUnit your bug exterminator
rjsmelo
 
Leveling Up With Unit Testing - LonghornPHP 2022
Mark Niebergall
 
Getting started with TDD - Confoo 2014
Eric Hogue
 
Charla EHU Noviembre 2014 - Desarrollo Web
Mikel Torres Ugarte
 
Ad

More from Michelangelo van Dam (20)

PDF
GDPR Art. 25 - Privacy by design and default
Michelangelo van Dam
 
PDF
Moving from app services to azure functions
Michelangelo van Dam
 
PDF
Privacy by design
Michelangelo van Dam
 
PDF
DevOps or DevSecOps
Michelangelo van Dam
 
PDF
Privacy by design
Michelangelo van Dam
 
PDF
Continuous deployment 2.0
Michelangelo van Dam
 
PDF
Let your tests drive your code
Michelangelo van Dam
 
PDF
General Data Protection Regulation, a developer's story
Michelangelo van Dam
 
PDF
Leveraging a distributed architecture to your advantage
Michelangelo van Dam
 
PDF
The road to php 7.1
Michelangelo van Dam
 
PDF
Open source for a successful business
Michelangelo van Dam
 
PDF
Decouple your framework now, thank me later
Michelangelo van Dam
 
PDF
Deploy to azure in less then 15 minutes
Michelangelo van Dam
 
PDF
Azure and OSS, a match made in heaven
Michelangelo van Dam
 
PDF
Getting hands dirty with php7
Michelangelo van Dam
 
PDF
Create, test, secure, repeat
Michelangelo van Dam
 
PDF
The Continuous PHP Pipeline
Michelangelo van Dam
 
PDF
PHPUnit Episode iv.iii: Return of the tests
Michelangelo van Dam
 
PDF
Easily extend your existing php app with an api
Michelangelo van Dam
 
PDF
200K+ reasons security is a must
Michelangelo van Dam
 
GDPR Art. 25 - Privacy by design and default
Michelangelo van Dam
 
Moving from app services to azure functions
Michelangelo van Dam
 
Privacy by design
Michelangelo van Dam
 
DevOps or DevSecOps
Michelangelo van Dam
 
Privacy by design
Michelangelo van Dam
 
Continuous deployment 2.0
Michelangelo van Dam
 
Let your tests drive your code
Michelangelo van Dam
 
General Data Protection Regulation, a developer's story
Michelangelo van Dam
 
Leveraging a distributed architecture to your advantage
Michelangelo van Dam
 
The road to php 7.1
Michelangelo van Dam
 
Open source for a successful business
Michelangelo van Dam
 
Decouple your framework now, thank me later
Michelangelo van Dam
 
Deploy to azure in less then 15 minutes
Michelangelo van Dam
 
Azure and OSS, a match made in heaven
Michelangelo van Dam
 
Getting hands dirty with php7
Michelangelo van Dam
 
Create, test, secure, repeat
Michelangelo van Dam
 
The Continuous PHP Pipeline
Michelangelo van Dam
 
PHPUnit Episode iv.iii: Return of the tests
Michelangelo van Dam
 
Easily extend your existing php app with an api
Michelangelo van Dam
 
200K+ reasons security is a must
Michelangelo van Dam
 

Recently uploaded (20)

PPTX
𝙳𝚘𝚠𝚗𝚕𝚘𝚊𝚍—Wondershare Filmora Crack 14.0.7 + Key Download 2025
sebastian aliya
 
PPTX
Simplifica la seguridad en la nube y la detección de amenazas con FortiCNAPP
Cristian Garcia G.
 
PPTX
Practical Applications of AI in Local Government
OnBoard
 
PDF
“Scaling i.MX Applications Processors’ Native Edge AI with Discrete AI Accele...
Edge AI and Vision Alliance
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PPTX
Enabling the Digital Artisan – keynote at ICOCI 2025
Alan Dix
 
PDF
Java 25 and Beyond - A Roadmap of Innovations
Ana-Maria Mihalceanu
 
PPTX
01_Approach Cyber- DORA Incident Management.pptx
FinTech Belgium
 
PDF
Cracking the Code - Unveiling Synergies Between Open Source Security and AI.pdf
Priyanka Aash
 
PDF
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
PPTX
reInforce 2025 Lightning Talk - Scott Francis.pptx
ScottFrancis51
 
PDF
UiPath Agentic AI ile Akıllı Otomasyonun Yeni Çağı
UiPathCommunity
 
PDF
Database Benchmarking for Performance Masterclass: Session 2 - Data Modeling ...
ScyllaDB
 
PDF
Darley - FIRST Copenhagen Lightning Talk (2025-06-26) Epochalypse 2038 - Time...
treyka
 
PDF
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
Edge AI and Vision Alliance
 
PDF
The Growing Value and Application of FME & GenAI
Safe Software
 
PDF
Kubernetes - Architecture & Components.pdf
geethak285
 
PDF
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
PDF
Why aren't you using FME Flow's CPU Time?
Safe Software
 
PDF
My Journey from CAD to BIM: A True Underdog Story
Safe Software
 
𝙳𝚘𝚠𝚗𝚕𝚘𝚊𝚍—Wondershare Filmora Crack 14.0.7 + Key Download 2025
sebastian aliya
 
Simplifica la seguridad en la nube y la detección de amenazas con FortiCNAPP
Cristian Garcia G.
 
Practical Applications of AI in Local Government
OnBoard
 
“Scaling i.MX Applications Processors’ Native Edge AI with Discrete AI Accele...
Edge AI and Vision Alliance
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Enabling the Digital Artisan – keynote at ICOCI 2025
Alan Dix
 
Java 25 and Beyond - A Roadmap of Innovations
Ana-Maria Mihalceanu
 
01_Approach Cyber- DORA Incident Management.pptx
FinTech Belgium
 
Cracking the Code - Unveiling Synergies Between Open Source Security and AI.pdf
Priyanka Aash
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
reInforce 2025 Lightning Talk - Scott Francis.pptx
ScottFrancis51
 
UiPath Agentic AI ile Akıllı Otomasyonun Yeni Çağı
UiPathCommunity
 
Database Benchmarking for Performance Masterclass: Session 2 - Data Modeling ...
ScyllaDB
 
Darley - FIRST Copenhagen Lightning Talk (2025-06-26) Epochalypse 2038 - Time...
treyka
 
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
Edge AI and Vision Alliance
 
The Growing Value and Application of FME & GenAI
Safe Software
 
Kubernetes - Architecture & Components.pdf
geethak285
 
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
Why aren't you using FME Flow's CPU Time?
Safe Software
 
My Journey from CAD to BIM: A True Underdog Story
Safe Software
 

UA testing with Selenium and PHPUnit - TrueNorthPHP 2013

  • 1. UA  Tes'ng  with Selenium  and  PHPUnit TrueNorthPHP  2013   Toronto,  Canada
  • 2. Michelangelo  van  Dam • PHP  Consultant   • President  PHPBenelux   • Conference  speaker 2
  • 3. 3
  • 4. Today’s  goal • Set  up  and  use  Selenium  IDE   • Record  UA  tests   • Convert  to  PHPUnit   • Run  con'nuously   • Mul'  browser  support 4
  • 5. DISCLAIMER SELENIUM TESTS ARE NOT 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 TA 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”! 5
  • 7. “Acceptance testing is a test conducted to determine if the requirements of a specification or contract are met.” ! -- source: wikipedia 7
  • 8. 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   -­‐ e.g.  buTons,  form  elements,  AJAX  controls,  … • Test  UI  elements  on  the  web  interface   9
  • 10. A  word  of  cau'on! • UA  tests  only  test  generated  output   -­‐ not  a  replacement  for  unit  tes'ng   -­‐ changes  to  the  DOM  might  lead  to  failing  UAT • UA  tests  are  heavily  depending  on  DOM   10
  • 12. Selenium  to  the  rescue 12
  • 14. Get  the  plugin  (demo) 14
  • 17. Pick  a  test  case 17
  • 19. Verify  this  issue  on  PROD 19
  • 20. 20
  • 22. Run  test  to  see  it’s  fixed 22
  • 23. 23
  • 24. Save  your  test  as  .html 24
  • 27. PHPUnit  to  the  rescue 27
  • 29. The  PHPUnit  TestCase ?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); } 29
  • 30. Change  class  name ?php class Example extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this-setBrowser(*chrome); class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase $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); } 30
  • 31. The  PHPUnit  TestCase ?php class MarkTaskDoneTest extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this-setBrowser(*chrome); $this-setBrowserUrl(http://www.theialive.com/); } ! } ? public function testMyTestCase() { protected function setUp() $this-open(/); { $this-click(link=login); $this-waitForPageToLoad(30000); $this-setBrowser(*iexplore); $this-type(id=email, [email protected]); $this-setBrowserUrl(http://www.theialive.com/); $this-type(id=password, test1234); $this-click(id=signin); $this-setHost('192.168.56.101'); $this-waitForPageToLoad(30000); $this-setPort(12666); $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); } 31
  • 32. 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); public function testMarkTestAsDone() $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
  • 34. Now  run  your  tests 34
  • 36. How  it  runs  on  the  node 36
  • 38. Advantages • 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 38
  • 41. Base  TestCase ?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); } 41
  • 42. Base  TestCase ?php ! array ( require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; ! 'name' = 'Internet Explorer 8 on Windows 7', class TestCase extends PHPUnit_Extensions_SeleniumTestCase 'browser' = '*iexplore', { //const TEST_HUB = '217.21.179.192'; const 'host'= = self::TEST_HUB, TEST_HUB '192.168.56.101'; const 'port' == self::TEST_PORT, TEST_PORT 12666; ! ), USERNAME = '[email protected]'; const ! ! } 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); } 42
  • 43. Base  TestCase ?php ! require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; ! class TestCase extends PHPUnit_Extensions_SeleniumTestCase { array ( //const TEST_HUB = '217.21.179.192'; const 'name'= = 'Firefox on Windows 7', TEST_HUB '192.168.56.101'; const TEST_PORT = 12666; 'browser' = '*firefox', ! const 'host'= = self::TEST_HUB, USERNAME '[email protected]'; const PASSWORD = 'test1234'; const 'port''http://www.theialive.com'; BASURL = = self::TEST_PORT, ! ), public static $browsers = array ( ! } ); array ( 'name' 'host' ), array ( 'name' 'host' ), array ( 'name' 'host' ), = 'Internet Explorer 8 on Windows 7', 'browser' = '*iexplore', = self::TEST_HUB, 'port' = self::TEST_PORT, = 'Firefox on Windows 7', 'browser' = '*firefox', = self::TEST_HUB, 'port' = self::TEST_PORT, = 'Google Chrome on Windows 7', 'browser' = '*googlechrome', = self::TEST_HUB, 'port' = self::TEST_PORT, protected function setUp() { $this-setBrowserUrl(self::BASURL); } 43
  • 44. Base  TestCase ?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; ! array ( const USERNAME = '[email protected]'; const 'name'= = 'Google Chrome on Windows 7', PASSWORD 'test1234'; const BASURL = 'http://www.theialive.com'; 'browser' = '*googlechrome', ! public static $browsers = array ( 'host' = self::TEST_HUB, array ( 'port'== self::TEST_PORT, 7', 'browser' = '*iexplore', 'name' 'Internet Explorer 8 on Windows ), ), 'host' = self::TEST_HUB, 'port' = self::TEST_PORT, ! } ); array ( 'name' 'host' ), array ( 'name' 'host' ), = 'Firefox on Windows 7', 'browser' = '*firefox', = self::TEST_HUB, 'port' = self::TEST_PORT, = 'Google Chrome on Windows 7', 'browser' = '*googlechrome', = self::TEST_HUB, 'port' = self::TEST_PORT, protected function setUp() { $this-setBrowserUrl(self::BASURL); } 44
  • 45. 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); } } Require the TestCase and extend it 45
  • 47. 47
  • 48. Benefits • run  your  tests  on  mul'ple  browsers   • detect  flaws  in  specific  browsers  (e.g.  IE6)   -­‐ adapt  your  apps  to  solve  these  flaws 48
  • 50. The  GRID • Procedure   -­‐ -­‐ -­‐ centralized  server  (HUB)   commands  clients  (nodes)  registered   and  executes  the  tests   -­‐ -­‐ allow  for  automa'on   adding  clients  as  you  go • Goal   50
  • 51. Selenium  Grid  Setup Selenium Testing Windows HUB launches Selenium node clients to execute tests CI executes tests Windows client NODE Linux client NODE CI Server Windows HUB Windows Server collects feedback from the Citrix client nodes and reports back to CI Server Mac OS X client NODE Continuous User Acceptance Testing 51
  • 52. Star'ng  the  server  [HUB] C:Program FilesJavajre7binjava.exe -jar C:Jarselenium-server-standalone-2.28.0.jar -role hub -port 12666 52
  • 53. Star'ng  the  client  [NODE] C:Program FilesJavajre7binjava.exe -jar C:Jarselenium-server-standalone-2.28.0.jar -role node -host 192.168.56.103 -port 13666 -hub http://192.168.56.101:12666/grid/register 53
  • 56. Modify  Base  TestCase ?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); } 56
  • 60. Credits • 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 60
  • 61. Contact Michelangelo van Dam Zend Certified Engineer ! email: [email protected] Contact us for Consultancy - Training - QA - Webdesign 61