testing single page webapp
DESCRIPTION
TRANSCRIPT
Testing Single-page Web App
Akshay MathurSiddharth Saha
Nikita Mundhada
2
Ground Rules• Post on FB and Tweet now• Disturb Everyone during the
session– Not by phone rings– Not by local talks– By more information and questions
@akshaymathu @sid_chilling @nikitascorner
@akshaymathu @sid_chilling @nikitascorner 3
Let’s Know Each Other
• Do you code?• Do you test?• OS?• Programing Language?• HTML DOM, CSS Selectors, JQuery ?• Why are you attending?
@akshaymathu @sid_chilling @nikitascorner 4
Akshay Mathur
• Managed development, testing and release teams in last 14+ years– Currently Principal Architect at ShopSocially
• Founding Team Member of– ShopSocially (Enabling “social” for retailers)– AirTight Neworks (Global leader of WIPS)
@akshaymathu @sid_chilling @nikitascorner 5
Siddharth Saha
• CS graduate from NIT Rourkela• 3+ years in Software Product industry• Worked in Telecom (Drishti Soft) and Social
Shopping (ShopSocially) Domains• Currently Junior Application Architect at
ShopSocially
@akshaymathu @sid_chilling @nikitascorner 6
Nikita Mundhada
• CS graduate from PICT Pune• 2 years in Software Product industry• Worked– at Amdocs as a Java Developer – at ShopSocially as a Full Stack Developer
• Going back to college– For MS at Georgia Institute of Technology
@akshaymathu @sid_chilling @nikitascorner 7
Agenda
• Problem Statement – What are single page apps and how are they different– Why other tools fail testing dynamic DoM in browser
• Introduction to Server Side Javascript and Related Technologies– Headless Browser, NodeJS, PhantomJS, CasperJS, Splinter
• Demonstrations and Code Walkthroughs– Invoking UI test suite, in the browser from Python console,
using Splinter– Testing UI from command line, without opening the browser,
using CasperJS
Traditional Web Apps
Dynamic on Server
The Evolution of Web
Static PagesInput FormsDynamic Pages
Interactive Apps
Rich Internet Apps
9@akshaymathu @sid_chilling @nikitascorner
@akshaymathu @sid_chilling @nikitascorner 10
Traditional Apps
• Action items are implemented as hyperlinks to URLs
• Different web page is requested from server for next step of workflow
• Browser’s address bar is the only progress indicator
• Tooltips are available for in-context help
@akshaymathu @sid_chilling @nikitascorner 11
Page Construction
• On Server:– Dynamic portion of the page executes and brings
the data– HTML gets constructed using PHP, ASP, JSP etc.
• On Client:– Browser renders the HTML DOM– No major change happens in HTML DOM after
rendering• Light use of Javascript
@akshaymathu @sid_chilling @nikitascorner 12
Traditional Testing Tools Work Fine
• Get a copy of HTML DOM just before it is being rendered by web browser
• Do not execute Javascript• For recognizing DOM elements:– Old: Use window coordinates– New: Use Object’s xPath
• Use UI elements/Events for interactions
Modern Apps
Dynamic on Client
@akshaymathu @sid_chilling @nikitascorner 14
Modern Apps
• Javascript event handlers are attached to on-screen actions
• Only required portion of page gets updated as needed
• Loading indicator appears whenever user need to wait
• Rich in-context interaction, in form of light-box popups
@akshaymathu @sid_chilling @nikitascorner 15
Page Construction
• On Server:– Minimal HTML rendering– Typically no (or minimum) data-driven components– Separate calls for data
• On Client:– Data requested from Server using AJAX calls– HTML DOM changes dynamically– Workflow implemented in browser
• Heavy use of Javascript– Jquery, BackboneJS etc.
@akshaymathu @sid_chilling @nikitascorner 16
Traditional Testing Tools Fail
• Changed HTML DOM is not available to the tool
• xPaths of existing elements change
@akshaymathu @sid_chilling @nikitascorner 17
Requirements for New Age Tools
• Should have complete control over HTML DOM and the Javascript on the page– Should be able to fire DOM events as user does– Should be able run Javascript on the page as it
happens in the browser on user’s action– Should be able to get changed DOM as needed
• Should use selectors rather than xPaths• Should not depend too much on screen
painting
@akshaymathu @sid_chilling @nikitascorner 18
Javascript Runtime Environment
Outside the Brower
@akshaymathu @sid_chilling @nikitascorner 20
NodeJS
• Technology that allows to use Javascript on server side or in command line environment– A complete app-server and web-framework can be
written using NodeJS• Even-driven and Asynchronous programming– High performance– Low response time
@akshaymathu @sid_chilling @nikitascorner 21
Headless Browser
• Browser without Graphical User Interface– Implements everything same as web browsers• HTTP Request and Response handling• Rendering Engine• HTTP DOM and Events• Javascript Runtime Environment
• Used for website testing, screen capture and page automation from command line
@akshaymathu @sid_chilling @nikitascorner 22
Headless Browsers
• Phantom JS– Headless browser implementing Webkit• Similar to Chrome, Safari
• Slimer JS– Upcoming headless browser implementing Gecko• Similar to Firefox
Testing Tools
@akshaymathu @sid_chilling @nikitascorner 24
Casper JS
• Tool built on top of Headless Browsers– Same code works for PhantomJS and SlimerJS
• Eases the process of defining a full navigation scenario
• Provides syntactic sugar for common tasks:– Filling Forms– Clicking and following links– Logging events– Finding DOM elements– …
@akshaymathu @sid_chilling @nikitascorner 25
Splinter
• Open source tool for testing web applications using Python
• An abstraction layer on top of existing browser automation tools:– Selenium– PhantomJS – Zope
@akshaymathu @sid_chilling @nikitascorner 26
@akshaymathu @sid_chilling @nikitascorner 27
Demonstrations
• Important points to note– The UI under test is sensitive to screen size– The test includes interacting with the elements in
an iFrame– The DOM in the iFrame changes dynamically
without loading the complete page
@akshaymathu @sid_chilling @nikitascorner 28
ShopSocially
• Provides social apps to online retailers– Most of apps are embed-able on web pages• Execute in iFrame• Do not reload page for better user experience
Testing with Browser UI
Splinter Demonstration and Code
Siddharth Saha
@akshaymathu @sid_chilling @nikitascorner 30
Splinter
• Open source tool for testing web applications using Python
• An abstraction layer on top of existing browser automation tools:– Selenium– PhantomJS – Zope
@akshaymathu @sid_chilling @nikitascorner 31
Splinter
• Simple Python APIs• Multiple webdrivers– Chrome, Firefox, PhatomJS, Zope– One code to rule them all
• CSS and Xpath Selectors• Support for iframe and alerts• Executes JavaScript
@akshaymathu @sid_chilling @nikitascorner 32
Do with Splinter
• Browser Navigation• Finding elements• Mouse interactions• Interacting with elements and forms• Cookies manipulation• Execute JavaScript• Deal with HTTP status codes• Interact with iframes, alerts and prompts
@akshaymathu @sid_chilling @nikitascorner 33
@akshaymathu @sid_chilling @nikitascorner 34
Choosing Browser
from splinter import Browser
browser = Browser(‘chrome’)
B = Browser(user_agent = ‘Mozilla/5.0 (iPhone; U;)’)
@akshaymathu @sid_chilling @nikitascorner 35
Navigation
browser.visit(‘http://shopsocially.com’)
browser.back()
browser.forward()
@akshaymathu @sid_chilling @nikitascorner 36
Finding DOM Element
browser.find_by_id(‘my_id’)
browser.find_by_name(‘my_name’)
browser.find_by_tag(‘h1’)
@akshaymathu @sid_chilling @nikitascorner 37
Mouse Interactions
browser.find_by_tag(‘div’).first.click()
browser.find_by_id(‘my_id’). right_click()
browser.find_by_name(‘my_name’). double_click()
browser.find_by_tag(‘h1’).mouse_over()
@akshaymathu @sid_chilling @nikitascorner 38
Interacting with Form Elements
browser.fill(‘query’, ‘Siddharth’)
browser.choose(‘some-radio’, ‘radio-value’)
browser.select(‘my-dropdown’, ‘my-fav-value’)
@akshaymathu @sid_chilling @nikitascorner 39
Executing Javascript
browser.execute_script(
“$(‘body’).css(‘bgcolor’, ‘#ccc’);\
$(‘#some_el’).hide();”
)
@akshaymathu @sid_chilling @nikitascorner 40
Dealing with iFrames
with browser.get_iframe(‘iframe_id’) as iframe:
iframe.fill(‘query’, ‘sid’)
• iFrame is another browser object– Supports all the functionality of a browser
@akshaymathu @sid_chilling @nikitascorner 41
Testing without Browser UI
CasperJS Demonstration and Code
Nikita Mudada
@akshaymathu @sid_chilling @nikitascorner 43
Casper JS
• Tool built on top of Headless Browsers– Same code works for PhantomJS and SlimerJS
• Eases the process of defining a full navigation scenario
• Provides syntactic sugar for common tasks:– Filling Forms– Clicking and following links– Logging events– Finding DOM elements– …
@akshaymathu @sid_chilling @nikitascorner 44
Casper JS
• Code written in only JavaScript/CoffeeScript• Casper JS and the javascript in the page
execute in their own sandboxes– Specific call is available to communicate
• Tester module provides functions and assertions for testing
• Utils module provide general utilities for I/O
@akshaymathu @sid_chilling @nikitascorner 45
Skeleton of a CasperJS program
start()
then()
run()
create()
evaluate()
Passes Function
Returns Value
Page DOM SandboxCasperJS Sandbox
ExecutesFunction
@akshaymathu @sid_chilling @nikitascorner 46
Example var casper = require('casper').create();
casper.start('http://facebook.com/’); casper.then(function() {
this.echo(this.getTitle());
this.evaluate(function(){alert("Cookies are:" + document.cookie);});
});
casper.run();
@akshaymathu @sid_chilling @nikitascorner 47
Demonstration
@akshaymathu @sid_chilling @nikitascorner 48
Specifying Window Size
var casper = require('casper').create({
verbose:true,logLevel:'info',waitTimeout:10000,viewportSize:
{width: 900, height:700}
});
@akshaymathu @sid_chilling @nikitascorner 49
Checking for DOM Element
casper.then(function(){this.test.assertExists('#ssmi_getafan_sidebar_image','Sidebar image loaded.'); this.click('#ssmi_getafan_sidebar_image a'); this.page.switchToChildFrame("ssmi_getafan_iframe");
@akshaymathu @sid_chilling @nikitascorner 50
Clicking a Hyperlink
casper.then(function(){ this.test.assertExists('#ssmi_getafan_sidebar_image', 'Sidebar image loaded.');
this.click('#ssmi_getafan_sidebar_image a'); this.page.switchToChildFrame("ssmi_getafan_iframe");
@akshaymathu @sid_chilling @nikitascorner 51
Getting into iFrame
casper.then(function(){ this.test.assertExists('#ssmi_getafan_sidebar_image', 'Sidebar image loaded.'); this.click('#ssmi_getafan_sidebar_image a');
this.page.switchToChildFrame("ssmi_getafan_iframe");
@akshaymathu @sid_chilling @nikitascorner 52
Getting info from Web Page
this.evaluate(function(){alert("Cookies are:" +
document.cookie);});
});
@akshaymathu @sid_chilling @nikitascorner 53
Waiting for Changing DOM
casper.waitForSelector('#coupon_area > span', function() { this.test.assertTextExists('Thank you!', 'Thank you message displayed correctly.');
});
@akshaymathu @sid_chilling @nikitascorner 54
Reporting Results
casper.run(function(){require('utils').dump(
casper.test.getFailures());
require('utils').dump(casper.test.getPasses());
casper.test.renderResults(true, 0, 'test-results.xml');
});
@akshaymathu @sid_chilling @nikitascorner 55
Result Format <testsuite> <testcase classname="samples" name="Get-a-Fan App Sidebar loaded." time="39.647"> </testcase>
<testcase classname="samples" name="Found “Special-20” within the selector coupon_area1 > span" time="0.013">
<failure type="assertSelectorHasText">Found "Special-20" within the selector "#coupon_area1 > span“>
</failure></testcase>
</testsuite>
@akshaymathu @sid_chilling @nikitascorner 56
Do with CasperJS
• Test webpages– Report results in X-unit XML format– Integrate with Continuous Integration tool like
Jenkins• Take screenshots• Fill forms• Insert scripts into webpages• Download links
@akshaymathu @sid_chilling @nikitascorner 57
@akshaymathu @sid_chilling @nikitascorner 58
Summary
• Nature of web apps is changing– Javascript is becoming more and more powerful– Dynamism has come to browser
• Testing tools are also catching up– Dependency on UI layout is decreasing
• Using newer tools and technologies, We can save a lot– Tests are faster as they need not wait for UI– Multiple CasperJS tests can run on same machine
@akshaymathu @sid_chilling @nikitascorner 59
Thanks
@akshaymathu @sid_chilling @nikitascorner