SlideShare una empresa de Scribd logo
1 de 48
Descargar para leer sin conexión
Writing an Extensible Web Testing
Framework ready for the Cloud
Presented by Mike Ensor May 22, 2013 – Presented at GR8Conf in Copenhagen Denmark
©2013 Acquity Group, LLC. All rights reserved.
Introductions
2
• What is this talk about?
• Curious about automated browser testing
• Testing a Reference application and/or SaaS
• Expanding Geb’s inheritance model
• Who is Mike!?
• Developing software for 16+ years
• Started working with Groovy and Grails in 2007
• Attended GR8Conf last year
• Acquity Group
• Blending strategy, creative and technology
• Currently a principal architect; Intershop and Demandware platform
• Introduced Geb and Spock to Demandware practice
©2013 Acquity Group, LLC. All rights reserved.
Useful Links
3
Demandware testing framework
• http://mikeensor.bitbucket.org/demandware-testing-framework
Spock feature override extension
• https://github.com/mike-ensor/spock-feature-override-extension
Presentation
• http://www.slideshare.net/MikeEnsor/
Twitter @mikeensor
• http://www.twitter.com/mikeensor
Blog
• http://www.ensor.cc
Web Testing
©2013 Acquity Group, LLC. All rights reserved.
Why Test?
5
Raise
Confidence
Safety Net
Prove
Functionality
Ensure
Quality
Lower Costs
©2013 Acquity Group, LLC. All rights reserved.
Cost Savings
6
$0
$1,000
$2,000
$3,000
$4,000
$5,000
$6,000
Developer Unit Tests Integration
Tests
Environment
Cost per Defect
Avg Cost
Google Study presented at XP Days London 2009 – Mark Streibeck, Google Inc
©2013 Acquity Group, LLC. All rights reserved.
SaaS Access
Acceptance
Functional
Integration
Unit tests
Levels of Testing
7
Complexity
Quantity
©2013 Acquity Group, LLC. All rights reserved.
History of Web Testing
Manual
Click
Testing
•Time
consuming
•Error prone
Screen
Scrape
•Custom
scripts
•Maintenance
nightmare
HTTPUnit
•Does not
work with
JavaScript
•Tests HTML
structure
only
Canoo
WebTest
•Developing
in XML*
•Duplicate
code
Selenium
RC
•Cut-Copy-
Paste scripts
•Duplication
of code
•Mouse
driven
WebDriver
•Very low
level
framework
•Easy to
create brittle
tests
Geb
•Abstraction
on top of
WebDriver
•Designed for
code reuse
8
©2013 Acquity Group, LLC. All rights reserved.
What is Geb?
9
• Groovy based abstraction of Selenium Web Driver with
jQuery-like syntax for content selection
• Designed for robust yet simplistic syntax
• Simplified DSL describing Pages and Modules
• Words like
• url
• content
• base
• at
• Created with DRY principal in mind
• Use of highly configurable reusable modules
• Abstraction of WebDriver’s Page Model
©2013 Acquity Group, LLC. All rights reserved.
Geb Core
10
Page
Objects
ModulesGeb
©2013 Acquity Group, LLC. All rights reserved.
Page Objects
11
• What is a “Page”?
• Object representing a generic type of
webpage on a site
• Domain Specific Language
• url - Appended to configurable ‘baseUrl’
• Assists in navigating to page
• at
• closure used to determine if browser
is ‘at’ the page
• content
• Variables representing page content
with CSS selectors
class HomePage extends Page {
static url = "default/Home-Show"
static at = {
title.trim() == "Welcome"
}
static content = {
pageTitle {
$("header h1.title")
}
}
}
...
<header>
<h1 class=“title”>Main Page Title</h1>
</header>
...
©2013 Acquity Group, LLC. All rights reserved.
Building multiple Pages
12
class HomePage extends Page {
static url = "default/Home-Show"
static at = {
title.trim() == "Welcome"
}
static content = {
companyTitle {
$("header h1.title")
}
footerCopywrite {
$("footer span.copy")
}
}
}
class ProductPage extends Page {
static url = "default/Product-Show"
static at = {
title.trim() == "Products"
}
static content = {
companyTitle {
$("header h1.title")
}
footerCopywrite {
$("footer span.copy")
}
productTitle {
$("#product h2.title")
}
}
}
©2013 Acquity Group, LLC. All rights reserved.
Code Duplication
13
©2013 Acquity Group, LLC. All rights reserved.
Dangers of Code Duplication
14
• Small change in underlying structure = many changes
• Long sections of nearly identical code
• Conceal purpose of code
• File size
• Code Maintenance
©2013 Acquity Group, LLC. All rights reserved.
Modules
15
• What is a ‘Module’?
• Re-usable encapsulation
consisting of content references
• Domain Specific Language
• base
• Optional content closure acting as a
base to start content selection
• content
• Variables representing page content
with CSS selectors, optionally
originating from base closure
class HeaderModule extends Module {
static base = { $("header") }
static content = {
companyTitle {
$("h1.title")
}
login { $("a.login") }
}
}
...
<header>
<h1 class=“title”>Page Title</h1>
<a href=“/login”>Login</a>
</header>
...
©2013 Acquity Group, LLC. All rights reserved.
Geb: Pages + Modules
16
class HomePage extends Page {
static url = "default/Home-Show"
static at = { title.trim() == "Welcome" }
static content = {
footer { module FooterModule }
header { module HeaderModule }
}
}
class ProductPage extends Page {
static url = "default/Product-Show"
static at = { title.trim() == "Products" }
static content = {
productTitle { $("#product h2.title") }
footer { module FooterModule }
header { module HeaderModule }
}
}
class HeaderModule extends Module {
static base = { $("header") }
static content = {
companyTitle { $("h1.title") }
login { $("a.login") }
}
}
©2013 Acquity Group, LLC. All rights reserved.
Now what?
17
Not Logged In Logged In
Extending Geb Objects
©2013 Acquity Group, LLC. All rights reserved.
Scenario
Your Mission:
You have been asked to create a special Product page for when a customer has logged in
The page looks and functions exactly like the Product page, but has an extra header
19
©2013 Acquity Group, LLC. All rights reserved.
Extending Page Objects
20
• Extend our page object
• Re-define url, and at
• Inherits content
• Overwrite/add content
elements
class PersonalProductPage extends ProductPage {
static url = "default/MyProduct-Show"
static at = { title.trim() == "Personalized" }
static content = {
// header inherited from HomePage
// footer inherited from HomePage
productTitle {
$("section#personal h2.title")
}
}
}
©2013 Acquity Group, LLC. All rights reserved.
• Extend module object
• Re-define base
• Inherits content
• Overwrite/add content
elements
Extending Modules Objects
21
class AuthHeaderModule extends HeaderModule {
static base = { $("header section#personal") }
static content = {
// companyTitle inherited from HeaderModule
// login inherited from HeaderModule
logout { $("a.logout") }
}
}
©2013 Acquity Group, LLC. All rights reserved.
Drawbacks & Best Practices
• Watch out for
• Overriding content segments happen at runtime
• No name spacing
• Possible to unintentionally overwrite content
• Possible solutions
• Document well (use JavaDoc style comments)
• API Groovy Doc
• Write a test to explicitly prove the inheritance
• Tests should fail if the inheritance fails
• Subscribe to user@geb.codehaus.org
22
©2013 Acquity Group, LLC. All rights reserved.
With great power
comes great responsibility -- Uncle Ben
23
Using Geb with Spock
©2013 Acquity Group, LLC. All rights reserved.
Spock
• Specification based testing framework designed to describe
the intention of the test in business friendly terms
• Provides keywords for structure
• when
• Action
• then
• Expectation
• Geb provides GebReportingSpec
• Can be extended to change functionality
• Provides extension model
• Control specification lifecycle
25
©2013 Acquity Group, LLC. All rights reserved.
Creating a Specification
• Extend GebReportingSpec
• Describe a feature
• aka - “Test method”
• Browse to
• Verify at
• Verify content
• Defined in ProductPage
• Verify module content
• Defined in
HeaderModule
26
class ProductPageSpec extends GebReportingSpec {
def "user can view the product page"() {
given:
to ProductPage
expect:
at ProductPage
and:
productTitle.text() == "My Cool Product"
and:
header.companyTitle.text() == "Company X"
}
}
Extensible Web Testing
©2013 Acquity Group, LLC. All rights reserved.
Scenario
Your Mission:
You work on a SaaS platform where each implementation is very similar in features and structure.
Design a testing framework where you can leverage common functionality inherent in all
implementations of the SaaS platform.
28
Reference
Application Implementation
• Size & Color Filters
• Breadcrumbs
• Category Navigation
• Mini-Cart
• Wish List
• 3-in-row Product Grid
• Size & Color Filters
• Breadcrumbs
• Category Navigation
• Mini-Cart
• Wish List
• 4-in-row Product Grid
©2013 Acquity Group, LLC. All rights reserved.
Common Functionality: Reference Application
29
Category Filter
Color Refinement
Size Refinement
Mini-Cart
Wish List
Breadcrumbs
Pagination
Price Refinement
©2013 Acquity Group, LLC. All rights reserved.
Common Functionality: Implementation Application
30
Category Filter
Price
Refinement
Color
Refinement
Mini-Cart
Wish List
Breadcrumbs
Pagination
©2013 Acquity Group, LLC. All rights reserved.
Inheriting Test Functionality
• Add dependency on
Reference App’s Test JAR
• Extend target specification
• Inherits all features from
parent specification
• Foresee problems?
• Overwrite inherited
features?
• Use derived Page objects?
• Investigate these one-by-one
31
class HomePgSpec extends GebReportingSpec {
def "user can view the home page"() {
// trimmed for clarity
given:
to HomePage
}
def "user can login"() {
// omitted for simplicity
}
}
class ClientPageSpec extends HomePgSpec {
// Inherit "user can view the home page“ & "user can login"
def "user can open wishlist"() {
// trimmed for clarity
given:
to ClientHomePage
}
}
©2013 Acquity Group, LLC. All rights reserved.
Inheriting Test Functionality: First Run
32
class HomePgSpec extends GebReportingSpec {
def "user can view the home page"() {
given:
to HomePage
when:
header.login.click()
then:
at MyAccountPage
}
def "user can login"() { /*obmitted for clarity*/ }
}
class ClientPageSpec extends HomePgSpec {
def "user can open wishlist"() {
given:
to ClientHomePage
}
}
• Run ClientPageSpec
• Spock determines list of features
• “user can view the home page”
• “user can login”
• “user can open wishlist”
• Run “user can view the home page”
• Navigate “to” HomePage ????
©2013 Acquity Group, LLC. All rights reserved.
Plan: overwrite inherited features
• Look for a feature in the parent
class with the same name
• Replace the inherited feature
with the provided feature
• Utilize Spock Extension features
to modify test execution
33
class ClientPageSpec extends HomePgSpec {
def "user can login"() {
given:
to ClientHomePage
when:
header.login.click()
then:
at ClientMyAccountPage
}
def "user can open wishlist"() {
// omitted for clarity
}
}
©2013 Acquity Group, LLC. All rights reserved.
Spock Extensions
Add runtime
functionality
Implements Visitor
Pattern
• Allow for modifications to the
Specification feature sequence
Ignore inherited
features if implemented
in Child
Triggered by Annotation
• @OverrideFeatures
34
©2013 Acquity Group, LLC. All rights reserved.
Overwrite Inherited Features
• Look for a feature in the Parent
class with the same name
• Create a marker @Annotation
• Tell Spock to use this feature, not
the Parent by using a Spock
Extension
• spock-feature-override-extension
• Open Sourced on github
35
@OverrideFeatures
class ClientPageSpec extends HomePgSpec {
def "user can login"() {
given:
to ClientHomePage
when:
header.login.click()
then:
at ClientMyAccountPage
}
def "user can open wishlist"() {
// omitted for clarity
}
}
©2013 Acquity Group, LLC. All rights reserved.
Now what?
• Able to override inherited features
• Override every feature?
• Why inherit?
36
class HomePage extends Page {
static url = "default/Home-Show"
static at = {
title.trim() == "Welcome"
}
static content = {
header { module HeaderModule }
footer { module FooterModule }
}
}
class ClientHomePage extends HomePage {
static url = "default/Home-Show"
static at = {
title.trim() == "Company Home"
}
static content = {
nav { module NavigationModule }
}
}
• What do we want?
• Dynamically swap sub-classed Page
objects
©2013 Acquity Group, LLC. All rights reserved.
Dynamically Swap Page Objects
• Page objects are managed by Browsers in Geb
• Extend existing Browser
• Create a “Browser” that knows about Page object relationships
37
geb.Browser
---------------------------------------------
Browser()
Page at(Class<? extends Page>)
Page to(Class<? extends Page>)
PageSelectingBrowser extends Browser
----------------------------------------------------------
PageSelectingBrowser(Map pageMap)
Page at(Class<? extends Page>)
Page to(Class<? extends Page>)
Page createPage(Class<? extends Page>)
©2013 Acquity Group, LLC. All rights reserved.
PageSelectingBrowser
38
class PageSelectingBrowser extends Browser {
private final Map<Class<? extends Page>, Class<? extends Page>> overridePages
/** Other methods omitted **/
@Override
Page createPage(Class<? extends Page> possibleParent) {
Class<? extends Page> type = possibleParent
if (overridePages.containsKey(possibleParent)) {
type = overridePages.get(possibleParent)
if (!possibleParent.isAssignableFrom(type)) {
throw new IllegalArgumentException("${type} not a ${possibleParent}")
}
}
type
}
}
©2013 Acquity Group, LLC. All rights reserved.
Using PageSelectingBrowser
39
• Browsers are created/used in GebSpec or GebReportingSpec
• Extend GebReportingSpec
• Override createBrowser() and return new PageSelectingBrowser
• Create a default empty Page object Map
• Each specification can overwrite Page object Map
class OverridableGebReportingSpec extends GebReportingSpec {
@Override
Browser createBrowser() {
new PageSelectingBrowser(createConf(), getChildPageMap())
}
Map<Class<? extends Page>, Class<? extends Page>> getChildPageMap() {
[:]
}
}
©2013 Acquity Group, LLC. All rights reserved.
OverridableGebReportingSpec
40
class HomePageSpecification extends OverridableGebReportingSpec {
def "user can view the home page"() {
given:
to HomePage
expect:
at HomePage
}
}
class ClientHomePageSpecification extends HomePageSpecification {
// inherit all features from HomePageSpecification
@Override
Map<Class<? extends Page>, Class<? extends Page>> getChildPageMap() {
[(HomePage.class): ClientHomePage.class]
}
}
Dynamically replace
ClientHomePage for HomePage
©2013 Acquity Group, LLC. All rights reserved.
Final Example
41
class HomePageSpec extends OverridableGebReportingSpec {
def "user can view the home page"() { // omitted for clarity }
def "user can login"() { // omitted for clarity }
}
@OverrideFeatures
class ClientHomePageSpecification extends HomePageSpecification {
def "user can login"() {
when:
to ClientHomePage
header.login.click()
then:
at ClientMyAccountPage
}
def "user can open wishlist"() { /* omitted for clarity */ }
@Override
Map<Class<? extends Page>, Class<? extends Page>> getChildPageMap() {
[(HomePage.class): ClientHomePage.class]
}
}
Inherit Features
Override Feature by Name
Create new features
Dynamically replace Page objects
©2013 Acquity Group, LLC. All rights reserved.42
Testing in the Cloud
©2013 Acquity Group, LLC. All rights reserved.
Testing on Continuous Integration
44
©2013 Acquity Group, LLC. All rights reserved.
Running without a Browser?
45
• What is RemoteWebDriver?
• Remotely sends driver commands to Selenium Grid
• Allows for same code to run on multiple browsers
©2013 Acquity Group, LLC. All rights reserved.
Sauce Labs
46
• SauceLabs – In-cloud based Remote WebDriver
• Removes infrastructure requirements
• Records video of remote run
• Can operate behind firewalls via SSH tunnel
©2013 Acquity Group, LLC. All rights reserved.
Parallelization
47
• Initial approach
• Modify GebSpec to create multiple browsers
• Cons
• Spock Extensions are not thread safe
• Browsers run at different speeds
• Remote WebDriver runners difficult to determine completion
• Reports not easy to collate
• Solution*
• Poor man’s Parallel
• Kick off multiple builds on CI with different configuration
• Possible parallelization with Gradle
• Fork per JVM
Questions?

Más contenido relacionado

La actualidad más candente

Building search app with ElasticSearch
Building search app with ElasticSearchBuilding search app with ElasticSearch
Building search app with ElasticSearchLukas Vlcek
 
AEM Sightly Deep Dive
AEM Sightly Deep DiveAEM Sightly Deep Dive
AEM Sightly Deep DiveGabriel Walt
 
Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)
Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)
Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)Michael Greene
 
HTML5: the new frontier of the web
HTML5: the new frontier of the webHTML5: the new frontier of the web
HTML5: the new frontier of the webIvano Malavolta
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling RewriterJustin Edelson
 
Modern development paradigms
Modern development paradigmsModern development paradigms
Modern development paradigmsIvano Malavolta
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresherIvano Malavolta
 
Intro to polymer-Devfest Yaoundé 2013
Intro to polymer-Devfest Yaoundé 2013Intro to polymer-Devfest Yaoundé 2013
Intro to polymer-Devfest Yaoundé 2013gdgyaounde
 
What is SharePoint Development??
What is SharePoint Development??What is SharePoint Development??
What is SharePoint Development??Mark Rackley
 
Dynamic components using SPA concepts in AEM
Dynamic components using SPA concepts in AEMDynamic components using SPA concepts in AEM
Dynamic components using SPA concepts in AEMBojana Popovska
 
Adobe Ask the AEM Community Expert Session Oct 2016
Adobe Ask the AEM Community Expert Session Oct 2016Adobe Ask the AEM Community Expert Session Oct 2016
Adobe Ask the AEM Community Expert Session Oct 2016AdobeMarketingCloud
 
Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...
Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...
Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...Brian Huff
 
User interface customization for aem6 circuit
User interface customization for aem6 circuitUser interface customization for aem6 circuit
User interface customization for aem6 circuitDamien Antipa
 
Acquia Drupal Certification
Acquia Drupal CertificationAcquia Drupal Certification
Acquia Drupal CertificationPhilip Norton
 
Adobe Experience Manager Core Components
Adobe Experience Manager Core ComponentsAdobe Experience Manager Core Components
Adobe Experience Manager Core ComponentsGabriel Walt
 

La actualidad más candente (20)

Building search app with ElasticSearch
Building search app with ElasticSearchBuilding search app with ElasticSearch
Building search app with ElasticSearch
 
Crx 2.2 Deep-Dive
Crx 2.2 Deep-DiveCrx 2.2 Deep-Dive
Crx 2.2 Deep-Dive
 
Sling Dynamic Include
Sling Dynamic IncludeSling Dynamic Include
Sling Dynamic Include
 
AEM Sightly Deep Dive
AEM Sightly Deep DiveAEM Sightly Deep Dive
AEM Sightly Deep Dive
 
Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)
Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)
Enhancing SharePoint 2010 for the iPad (SPSAusTX 2012)
 
HTML5: the new frontier of the web
HTML5: the new frontier of the webHTML5: the new frontier of the web
HTML5: the new frontier of the web
 
Sling Models Overview
Sling Models OverviewSling Models Overview
Sling Models Overview
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling Rewriter
 
Modern development paradigms
Modern development paradigmsModern development paradigms
Modern development paradigms
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresher
 
Intro to polymer-Devfest Yaoundé 2013
Intro to polymer-Devfest Yaoundé 2013Intro to polymer-Devfest Yaoundé 2013
Intro to polymer-Devfest Yaoundé 2013
 
AEM - Client Libraries
AEM - Client LibrariesAEM - Client Libraries
AEM - Client Libraries
 
What is SharePoint Development??
What is SharePoint Development??What is SharePoint Development??
What is SharePoint Development??
 
Dynamic components using SPA concepts in AEM
Dynamic components using SPA concepts in AEMDynamic components using SPA concepts in AEM
Dynamic components using SPA concepts in AEM
 
Adobe Ask the AEM Community Expert Session Oct 2016
Adobe Ask the AEM Community Expert Session Oct 2016Adobe Ask the AEM Community Expert Session Oct 2016
Adobe Ask the AEM Community Expert Session Oct 2016
 
Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...
Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...
Seamless Integrations between WebCenter Content, Site Studio, and WebCenter S...
 
User interface customization for aem6 circuit
User interface customization for aem6 circuitUser interface customization for aem6 circuit
User interface customization for aem6 circuit
 
Acquia Drupal Certification
Acquia Drupal CertificationAcquia Drupal Certification
Acquia Drupal Certification
 
Adobe Experience Manager Core Components
Adobe Experience Manager Core ComponentsAdobe Experience Manager Core Components
Adobe Experience Manager Core Components
 
Sightly_techInsight
Sightly_techInsightSightly_techInsight
Sightly_techInsight
 

Similar a Writing an extensible web testing framework ready for the cloud slide share

Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect ModelComprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect ModelvodQA
 
Stencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedStencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedGil Fink
 
Creating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJSCreating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJSGunnar Hillert
 
Web Development with HTML5, CSS3 & JavaScript
Web Development with HTML5, CSS3 & JavaScriptWeb Development with HTML5, CSS3 & JavaScript
Web Development with HTML5, CSS3 & JavaScriptEdureka!
 
GraalVM and Oracle's Documentation Trends.pdf
GraalVM and Oracle's Documentation Trends.pdfGraalVM and Oracle's Documentation Trends.pdf
GraalVM and Oracle's Documentation Trends.pdfohupalo
 
An Unexpected Solution to Microservices UI Composition
An Unexpected Solution to Microservices UI CompositionAn Unexpected Solution to Microservices UI Composition
An Unexpected Solution to Microservices UI CompositionDr. Arif Wider
 
Apache CloudStack Google Summer of Code
Apache CloudStack Google Summer of CodeApache CloudStack Google Summer of Code
Apache CloudStack Google Summer of CodeSebastien Goasguen
 
webdevelopment_6132030-lva1-app6891.pptx
webdevelopment_6132030-lva1-app6891.pptxwebdevelopment_6132030-lva1-app6891.pptx
webdevelopment_6132030-lva1-app6891.pptxlekhacce
 
Sitecore development approach evolution – destination helix
Sitecore development approach evolution – destination helixSitecore development approach evolution – destination helix
Sitecore development approach evolution – destination helixPeter Nazarov
 
Link your Way to Successful Content Management with MadCap Flare
Link your Way to Successful Content Management with MadCap FlareLink your Way to Successful Content Management with MadCap Flare
Link your Way to Successful Content Management with MadCap FlareDenise Kadilak
 
Stencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedStencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedGil Fink
 
Best Practices in Widget Development - Examples and Counterexamples
Best Practices in Widget Development  - Examples and CounterexamplesBest Practices in Widget Development  - Examples and Counterexamples
Best Practices in Widget Development - Examples and CounterexamplesROLE Project
 
Web component driven development
Web component driven developmentWeb component driven development
Web component driven developmentGil Fink
 
Custom Runtimes for the Cloud
Custom Runtimes for the CloudCustom Runtimes for the Cloud
Custom Runtimes for the CloudCloudBees
 
Brand Your Community Using Less and Gulp
Brand Your Community Using Less and GulpBrand Your Community Using Less and Gulp
Brand Your Community Using Less and Gulpshujiui
 
OSH01 - Developing SharePoint Framework Solutions for the Enterprise
OSH01 - Developing SharePoint Framework Solutions for the EnterpriseOSH01 - Developing SharePoint Framework Solutions for the Enterprise
OSH01 - Developing SharePoint Framework Solutions for the EnterpriseEric Shupps
 
Utilizing jQuery in SharePoint: Get More Done Faster
Utilizing jQuery in SharePoint: Get More Done FasterUtilizing jQuery in SharePoint: Get More Done Faster
Utilizing jQuery in SharePoint: Get More Done FasterMark Rackley
 
HTML Semantic Tags
HTML Semantic TagsHTML Semantic Tags
HTML Semantic TagsBruce Kyle
 
Pluggable patterns
Pluggable patternsPluggable patterns
Pluggable patternsCorey Oordt
 

Similar a Writing an extensible web testing framework ready for the cloud slide share (20)

Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect ModelComprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
 
Stencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedStencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrived
 
Creating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJSCreating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJS
 
Web Development with HTML5, CSS3 & JavaScript
Web Development with HTML5, CSS3 & JavaScriptWeb Development with HTML5, CSS3 & JavaScript
Web Development with HTML5, CSS3 & JavaScript
 
GraalVM and Oracle's Documentation Trends.pdf
GraalVM and Oracle's Documentation Trends.pdfGraalVM and Oracle's Documentation Trends.pdf
GraalVM and Oracle's Documentation Trends.pdf
 
An Unexpected Solution to Microservices UI Composition
An Unexpected Solution to Microservices UI CompositionAn Unexpected Solution to Microservices UI Composition
An Unexpected Solution to Microservices UI Composition
 
Apache CloudStack Google Summer of Code
Apache CloudStack Google Summer of CodeApache CloudStack Google Summer of Code
Apache CloudStack Google Summer of Code
 
webdevelopment_6132030-lva1-app6891.pptx
webdevelopment_6132030-lva1-app6891.pptxwebdevelopment_6132030-lva1-app6891.pptx
webdevelopment_6132030-lva1-app6891.pptx
 
Sitecore development approach evolution – destination helix
Sitecore development approach evolution – destination helixSitecore development approach evolution – destination helix
Sitecore development approach evolution – destination helix
 
Link your Way to Successful Content Management with MadCap Flare
Link your Way to Successful Content Management with MadCap FlareLink your Way to Successful Content Management with MadCap Flare
Link your Way to Successful Content Management with MadCap Flare
 
Stencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedStencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrived
 
Best Practices in Widget Development - Examples and Counterexamples
Best Practices in Widget Development  - Examples and CounterexamplesBest Practices in Widget Development  - Examples and Counterexamples
Best Practices in Widget Development - Examples and Counterexamples
 
Web component driven development
Web component driven developmentWeb component driven development
Web component driven development
 
Custom Runtimes for the Cloud
Custom Runtimes for the CloudCustom Runtimes for the Cloud
Custom Runtimes for the Cloud
 
Alfresco content model
Alfresco content modelAlfresco content model
Alfresco content model
 
Brand Your Community Using Less and Gulp
Brand Your Community Using Less and GulpBrand Your Community Using Less and Gulp
Brand Your Community Using Less and Gulp
 
OSH01 - Developing SharePoint Framework Solutions for the Enterprise
OSH01 - Developing SharePoint Framework Solutions for the EnterpriseOSH01 - Developing SharePoint Framework Solutions for the Enterprise
OSH01 - Developing SharePoint Framework Solutions for the Enterprise
 
Utilizing jQuery in SharePoint: Get More Done Faster
Utilizing jQuery in SharePoint: Get More Done FasterUtilizing jQuery in SharePoint: Get More Done Faster
Utilizing jQuery in SharePoint: Get More Done Faster
 
HTML Semantic Tags
HTML Semantic TagsHTML Semantic Tags
HTML Semantic Tags
 
Pluggable patterns
Pluggable patternsPluggable patterns
Pluggable patterns
 

Último

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 

Último (20)

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 

Writing an extensible web testing framework ready for the cloud slide share

  • 1. Writing an Extensible Web Testing Framework ready for the Cloud Presented by Mike Ensor May 22, 2013 – Presented at GR8Conf in Copenhagen Denmark
  • 2. ©2013 Acquity Group, LLC. All rights reserved. Introductions 2 • What is this talk about? • Curious about automated browser testing • Testing a Reference application and/or SaaS • Expanding Geb’s inheritance model • Who is Mike!? • Developing software for 16+ years • Started working with Groovy and Grails in 2007 • Attended GR8Conf last year • Acquity Group • Blending strategy, creative and technology • Currently a principal architect; Intershop and Demandware platform • Introduced Geb and Spock to Demandware practice
  • 3. ©2013 Acquity Group, LLC. All rights reserved. Useful Links 3 Demandware testing framework • http://mikeensor.bitbucket.org/demandware-testing-framework Spock feature override extension • https://github.com/mike-ensor/spock-feature-override-extension Presentation • http://www.slideshare.net/MikeEnsor/ Twitter @mikeensor • http://www.twitter.com/mikeensor Blog • http://www.ensor.cc
  • 5. ©2013 Acquity Group, LLC. All rights reserved. Why Test? 5 Raise Confidence Safety Net Prove Functionality Ensure Quality Lower Costs
  • 6. ©2013 Acquity Group, LLC. All rights reserved. Cost Savings 6 $0 $1,000 $2,000 $3,000 $4,000 $5,000 $6,000 Developer Unit Tests Integration Tests Environment Cost per Defect Avg Cost Google Study presented at XP Days London 2009 – Mark Streibeck, Google Inc
  • 7. ©2013 Acquity Group, LLC. All rights reserved. SaaS Access Acceptance Functional Integration Unit tests Levels of Testing 7 Complexity Quantity
  • 8. ©2013 Acquity Group, LLC. All rights reserved. History of Web Testing Manual Click Testing •Time consuming •Error prone Screen Scrape •Custom scripts •Maintenance nightmare HTTPUnit •Does not work with JavaScript •Tests HTML structure only Canoo WebTest •Developing in XML* •Duplicate code Selenium RC •Cut-Copy- Paste scripts •Duplication of code •Mouse driven WebDriver •Very low level framework •Easy to create brittle tests Geb •Abstraction on top of WebDriver •Designed for code reuse 8
  • 9. ©2013 Acquity Group, LLC. All rights reserved. What is Geb? 9 • Groovy based abstraction of Selenium Web Driver with jQuery-like syntax for content selection • Designed for robust yet simplistic syntax • Simplified DSL describing Pages and Modules • Words like • url • content • base • at • Created with DRY principal in mind • Use of highly configurable reusable modules • Abstraction of WebDriver’s Page Model
  • 10. ©2013 Acquity Group, LLC. All rights reserved. Geb Core 10 Page Objects ModulesGeb
  • 11. ©2013 Acquity Group, LLC. All rights reserved. Page Objects 11 • What is a “Page”? • Object representing a generic type of webpage on a site • Domain Specific Language • url - Appended to configurable ‘baseUrl’ • Assists in navigating to page • at • closure used to determine if browser is ‘at’ the page • content • Variables representing page content with CSS selectors class HomePage extends Page { static url = "default/Home-Show" static at = { title.trim() == "Welcome" } static content = { pageTitle { $("header h1.title") } } } ... <header> <h1 class=“title”>Main Page Title</h1> </header> ...
  • 12. ©2013 Acquity Group, LLC. All rights reserved. Building multiple Pages 12 class HomePage extends Page { static url = "default/Home-Show" static at = { title.trim() == "Welcome" } static content = { companyTitle { $("header h1.title") } footerCopywrite { $("footer span.copy") } } } class ProductPage extends Page { static url = "default/Product-Show" static at = { title.trim() == "Products" } static content = { companyTitle { $("header h1.title") } footerCopywrite { $("footer span.copy") } productTitle { $("#product h2.title") } } }
  • 13. ©2013 Acquity Group, LLC. All rights reserved. Code Duplication 13
  • 14. ©2013 Acquity Group, LLC. All rights reserved. Dangers of Code Duplication 14 • Small change in underlying structure = many changes • Long sections of nearly identical code • Conceal purpose of code • File size • Code Maintenance
  • 15. ©2013 Acquity Group, LLC. All rights reserved. Modules 15 • What is a ‘Module’? • Re-usable encapsulation consisting of content references • Domain Specific Language • base • Optional content closure acting as a base to start content selection • content • Variables representing page content with CSS selectors, optionally originating from base closure class HeaderModule extends Module { static base = { $("header") } static content = { companyTitle { $("h1.title") } login { $("a.login") } } } ... <header> <h1 class=“title”>Page Title</h1> <a href=“/login”>Login</a> </header> ...
  • 16. ©2013 Acquity Group, LLC. All rights reserved. Geb: Pages + Modules 16 class HomePage extends Page { static url = "default/Home-Show" static at = { title.trim() == "Welcome" } static content = { footer { module FooterModule } header { module HeaderModule } } } class ProductPage extends Page { static url = "default/Product-Show" static at = { title.trim() == "Products" } static content = { productTitle { $("#product h2.title") } footer { module FooterModule } header { module HeaderModule } } } class HeaderModule extends Module { static base = { $("header") } static content = { companyTitle { $("h1.title") } login { $("a.login") } } }
  • 17. ©2013 Acquity Group, LLC. All rights reserved. Now what? 17 Not Logged In Logged In
  • 19. ©2013 Acquity Group, LLC. All rights reserved. Scenario Your Mission: You have been asked to create a special Product page for when a customer has logged in The page looks and functions exactly like the Product page, but has an extra header 19
  • 20. ©2013 Acquity Group, LLC. All rights reserved. Extending Page Objects 20 • Extend our page object • Re-define url, and at • Inherits content • Overwrite/add content elements class PersonalProductPage extends ProductPage { static url = "default/MyProduct-Show" static at = { title.trim() == "Personalized" } static content = { // header inherited from HomePage // footer inherited from HomePage productTitle { $("section#personal h2.title") } } }
  • 21. ©2013 Acquity Group, LLC. All rights reserved. • Extend module object • Re-define base • Inherits content • Overwrite/add content elements Extending Modules Objects 21 class AuthHeaderModule extends HeaderModule { static base = { $("header section#personal") } static content = { // companyTitle inherited from HeaderModule // login inherited from HeaderModule logout { $("a.logout") } } }
  • 22. ©2013 Acquity Group, LLC. All rights reserved. Drawbacks & Best Practices • Watch out for • Overriding content segments happen at runtime • No name spacing • Possible to unintentionally overwrite content • Possible solutions • Document well (use JavaDoc style comments) • API Groovy Doc • Write a test to explicitly prove the inheritance • Tests should fail if the inheritance fails • Subscribe to user@geb.codehaus.org 22
  • 23. ©2013 Acquity Group, LLC. All rights reserved. With great power comes great responsibility -- Uncle Ben 23
  • 24. Using Geb with Spock
  • 25. ©2013 Acquity Group, LLC. All rights reserved. Spock • Specification based testing framework designed to describe the intention of the test in business friendly terms • Provides keywords for structure • when • Action • then • Expectation • Geb provides GebReportingSpec • Can be extended to change functionality • Provides extension model • Control specification lifecycle 25
  • 26. ©2013 Acquity Group, LLC. All rights reserved. Creating a Specification • Extend GebReportingSpec • Describe a feature • aka - “Test method” • Browse to • Verify at • Verify content • Defined in ProductPage • Verify module content • Defined in HeaderModule 26 class ProductPageSpec extends GebReportingSpec { def "user can view the product page"() { given: to ProductPage expect: at ProductPage and: productTitle.text() == "My Cool Product" and: header.companyTitle.text() == "Company X" } }
  • 28. ©2013 Acquity Group, LLC. All rights reserved. Scenario Your Mission: You work on a SaaS platform where each implementation is very similar in features and structure. Design a testing framework where you can leverage common functionality inherent in all implementations of the SaaS platform. 28 Reference Application Implementation • Size & Color Filters • Breadcrumbs • Category Navigation • Mini-Cart • Wish List • 3-in-row Product Grid • Size & Color Filters • Breadcrumbs • Category Navigation • Mini-Cart • Wish List • 4-in-row Product Grid
  • 29. ©2013 Acquity Group, LLC. All rights reserved. Common Functionality: Reference Application 29 Category Filter Color Refinement Size Refinement Mini-Cart Wish List Breadcrumbs Pagination Price Refinement
  • 30. ©2013 Acquity Group, LLC. All rights reserved. Common Functionality: Implementation Application 30 Category Filter Price Refinement Color Refinement Mini-Cart Wish List Breadcrumbs Pagination
  • 31. ©2013 Acquity Group, LLC. All rights reserved. Inheriting Test Functionality • Add dependency on Reference App’s Test JAR • Extend target specification • Inherits all features from parent specification • Foresee problems? • Overwrite inherited features? • Use derived Page objects? • Investigate these one-by-one 31 class HomePgSpec extends GebReportingSpec { def "user can view the home page"() { // trimmed for clarity given: to HomePage } def "user can login"() { // omitted for simplicity } } class ClientPageSpec extends HomePgSpec { // Inherit "user can view the home page“ & "user can login" def "user can open wishlist"() { // trimmed for clarity given: to ClientHomePage } }
  • 32. ©2013 Acquity Group, LLC. All rights reserved. Inheriting Test Functionality: First Run 32 class HomePgSpec extends GebReportingSpec { def "user can view the home page"() { given: to HomePage when: header.login.click() then: at MyAccountPage } def "user can login"() { /*obmitted for clarity*/ } } class ClientPageSpec extends HomePgSpec { def "user can open wishlist"() { given: to ClientHomePage } } • Run ClientPageSpec • Spock determines list of features • “user can view the home page” • “user can login” • “user can open wishlist” • Run “user can view the home page” • Navigate “to” HomePage ????
  • 33. ©2013 Acquity Group, LLC. All rights reserved. Plan: overwrite inherited features • Look for a feature in the parent class with the same name • Replace the inherited feature with the provided feature • Utilize Spock Extension features to modify test execution 33 class ClientPageSpec extends HomePgSpec { def "user can login"() { given: to ClientHomePage when: header.login.click() then: at ClientMyAccountPage } def "user can open wishlist"() { // omitted for clarity } }
  • 34. ©2013 Acquity Group, LLC. All rights reserved. Spock Extensions Add runtime functionality Implements Visitor Pattern • Allow for modifications to the Specification feature sequence Ignore inherited features if implemented in Child Triggered by Annotation • @OverrideFeatures 34
  • 35. ©2013 Acquity Group, LLC. All rights reserved. Overwrite Inherited Features • Look for a feature in the Parent class with the same name • Create a marker @Annotation • Tell Spock to use this feature, not the Parent by using a Spock Extension • spock-feature-override-extension • Open Sourced on github 35 @OverrideFeatures class ClientPageSpec extends HomePgSpec { def "user can login"() { given: to ClientHomePage when: header.login.click() then: at ClientMyAccountPage } def "user can open wishlist"() { // omitted for clarity } }
  • 36. ©2013 Acquity Group, LLC. All rights reserved. Now what? • Able to override inherited features • Override every feature? • Why inherit? 36 class HomePage extends Page { static url = "default/Home-Show" static at = { title.trim() == "Welcome" } static content = { header { module HeaderModule } footer { module FooterModule } } } class ClientHomePage extends HomePage { static url = "default/Home-Show" static at = { title.trim() == "Company Home" } static content = { nav { module NavigationModule } } } • What do we want? • Dynamically swap sub-classed Page objects
  • 37. ©2013 Acquity Group, LLC. All rights reserved. Dynamically Swap Page Objects • Page objects are managed by Browsers in Geb • Extend existing Browser • Create a “Browser” that knows about Page object relationships 37 geb.Browser --------------------------------------------- Browser() Page at(Class<? extends Page>) Page to(Class<? extends Page>) PageSelectingBrowser extends Browser ---------------------------------------------------------- PageSelectingBrowser(Map pageMap) Page at(Class<? extends Page>) Page to(Class<? extends Page>) Page createPage(Class<? extends Page>)
  • 38. ©2013 Acquity Group, LLC. All rights reserved. PageSelectingBrowser 38 class PageSelectingBrowser extends Browser { private final Map<Class<? extends Page>, Class<? extends Page>> overridePages /** Other methods omitted **/ @Override Page createPage(Class<? extends Page> possibleParent) { Class<? extends Page> type = possibleParent if (overridePages.containsKey(possibleParent)) { type = overridePages.get(possibleParent) if (!possibleParent.isAssignableFrom(type)) { throw new IllegalArgumentException("${type} not a ${possibleParent}") } } type } }
  • 39. ©2013 Acquity Group, LLC. All rights reserved. Using PageSelectingBrowser 39 • Browsers are created/used in GebSpec or GebReportingSpec • Extend GebReportingSpec • Override createBrowser() and return new PageSelectingBrowser • Create a default empty Page object Map • Each specification can overwrite Page object Map class OverridableGebReportingSpec extends GebReportingSpec { @Override Browser createBrowser() { new PageSelectingBrowser(createConf(), getChildPageMap()) } Map<Class<? extends Page>, Class<? extends Page>> getChildPageMap() { [:] } }
  • 40. ©2013 Acquity Group, LLC. All rights reserved. OverridableGebReportingSpec 40 class HomePageSpecification extends OverridableGebReportingSpec { def "user can view the home page"() { given: to HomePage expect: at HomePage } } class ClientHomePageSpecification extends HomePageSpecification { // inherit all features from HomePageSpecification @Override Map<Class<? extends Page>, Class<? extends Page>> getChildPageMap() { [(HomePage.class): ClientHomePage.class] } } Dynamically replace ClientHomePage for HomePage
  • 41. ©2013 Acquity Group, LLC. All rights reserved. Final Example 41 class HomePageSpec extends OverridableGebReportingSpec { def "user can view the home page"() { // omitted for clarity } def "user can login"() { // omitted for clarity } } @OverrideFeatures class ClientHomePageSpecification extends HomePageSpecification { def "user can login"() { when: to ClientHomePage header.login.click() then: at ClientMyAccountPage } def "user can open wishlist"() { /* omitted for clarity */ } @Override Map<Class<? extends Page>, Class<? extends Page>> getChildPageMap() { [(HomePage.class): ClientHomePage.class] } } Inherit Features Override Feature by Name Create new features Dynamically replace Page objects
  • 42. ©2013 Acquity Group, LLC. All rights reserved.42
  • 43. Testing in the Cloud
  • 44. ©2013 Acquity Group, LLC. All rights reserved. Testing on Continuous Integration 44
  • 45. ©2013 Acquity Group, LLC. All rights reserved. Running without a Browser? 45 • What is RemoteWebDriver? • Remotely sends driver commands to Selenium Grid • Allows for same code to run on multiple browsers
  • 46. ©2013 Acquity Group, LLC. All rights reserved. Sauce Labs 46 • SauceLabs – In-cloud based Remote WebDriver • Removes infrastructure requirements • Records video of remote run • Can operate behind firewalls via SSH tunnel
  • 47. ©2013 Acquity Group, LLC. All rights reserved. Parallelization 47 • Initial approach • Modify GebSpec to create multiple browsers • Cons • Spock Extensions are not thread safe • Browsers run at different speeds • Remote WebDriver runners difficult to determine completion • Reports not easy to collate • Solution* • Poor man’s Parallel • Kick off multiple builds on CI with different configuration • Possible parallelization with Gradle • Fork per JVM