SlideShare une entreprise Scribd logo
1  sur  66
Télécharger pour lire hors ligne
Nightwatch at Tilt
San Francisco Selenium Meetup
March 4th, 2015
About Me
• NJ -> UIUC -> Penn State -> Blacksburg VA -> SF Bay Area
• Grad School -> WebDev -> DevOps Lead -> Frontend Lead
• Java -> Python -> JavaScript
• @tildedave
• Blog, etc: tildedave.com
San Francisco Selenium Meetup March 4th 2014
Tilt
Make Amazing Things Happen
San Francisco Selenium Meetup March 4th 2014
Tilt is a social crowd-funding
company
San Francisco Selenium Meetup March 4th 2014
San Francisco Selenium Meetup March 4th 2014
“Move Fast and Break
Things”
It turns out that this statement is a lie
San Francisco Selenium Meetup March 4th 2014
Golden Features
• Login
• Signup
• Contribution Flow
• Commenting
• Admin Payouts
• … really no user flow can ever break acceptably
San Francisco Selenium Meetup March 4th 2014
Selenium at Tilt
San Francisco Selenium Meetup March 4th 2014
History of Selenium at Tilt
• CI/CD environment - push code to production daily
• No dedicated QA resources as part of the
development team
• Must not break core flows
San Francisco Selenium Meetup March 4th 2014
History of Selenium at Tilt
• Pre-History: PhantomJS/PhantomProxy - no visibility
on failures
• February 2013 - Introduce Selenium for functional
testing (2.31.0)
• June 2014 - Selenium tests vs staging/production as a
‘health check’ of deployed code (2.42.2)
San Francisco Selenium Meetup March 4th 2014
Ancient Code: Phantom JS
!
promiseIt('can contribute to regular campaign', function(p) {!
return p!
.withPrimedCampaign()!
.thenOpenCampaignPage()!
.thenLightboxClick('.campaign-tilt-info .btn')!
.thenType('#amount_lightbox', '2.00')!
.thenClickAndWaitForDocumentReady('#contribute-continue')!
.thenVerifyElementContents('#display-total', '2.05')!
.thenFillCCForm()!
.thenClickAndWaitAndFailIfLightboxCloses('#confirm-btn')!
.thenWait(1000)!
.thenVerifyElementVisible('#just_contributed')!
.thenCancelCampaign();!
});!
!
San Francisco Selenium Meetup March 4th 2014
Today: Nightwatch Tests
'Can contribute as admin': function(client) {!
var selectors = client.page.campaign().selectors;!
client.page.homepage().load()!
.createFBUserAndLogIn()!
.createCampaignAPI({}, function(campaign) {!
return client.page.campaign().load(campaign.title);!
})!
.page.campaign().clickContribute()!
.page.contributionFlow().enterContributionAmount('2')!
.page.contributionFlow().checkOut()!
.page.contributionFlow().skipInviteAndShare()!
// admins don't get asked to comment!
.verify.elementNotPresent(selectors.lightboxTitle)!
.end();!
}!
San Francisco Selenium Meetup March 4th 2014
Nightwatch at Tilt
• September 2014
• Selenium suite run on every branch before merge
• Lots of flapping tests - developers often rerun tests
until green
• Test suite expansion seems like a nightmare - lots of
selectors in tests, copy/pasted setup, etc
• October 2014 - We start investigating better solutions
San Francisco Selenium Meetup March 4th 2014
Nightwatch.js
San Francisco Selenium Meetup March 4th 2014
Nightwatch
• http://nightwatchjs.org/
• Better interface to selenium-webdriver
• Library provides Custom Commands, Page Objects,
and Assertions
• It’s in JavaScript!
San Francisco Selenium Meetup March 4th 2014
Why Nightwatch for Tilt?
• It’s in JavaScript
• Using Ruby just for tests is a hard sell
• Easily use npm modules as part of your tests
• Builds in important concepts that Tilt had rolled itself
(custom commands) or should have (page objects)
• Old suite had too much technical debt to be saved
San Francisco Selenium Meetup March 4th 2014
Tiltcabulary
• Users - users of the site
• Campaigns - crowdfunding campaigns
San Francisco Selenium Meetup March 4th 2014
Basic Nightwatch Test for
tilt.com
San Francisco Selenium Meetup March 4th 2014
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com': function(client) {!
var title = 'Collect money from your group';!
client!
.url('https://www.tilt.com')!
.waitForElementVisible('.hero-title', 1000)!
.verify.containsText('.hero-title',!
title)!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com': function(client) {!
var title = 'Collect money from your group';!
client!
.url('https://www.tilt.com')!
.waitForElementVisible('.hero-title', 1000)!
.verify.containsText('.hero-title',!
title)!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Arrange
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com': function(client) {!
var title = 'Collect money from your group';!
client!
.url('https://www.tilt.com')!
.waitForElementVisible('.hero-title', 1000)!
.verify.containsText('.hero-title',!
title)!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Assert
Basic Nightwatch Test for
tilt.com
• We have a video on our homepage. Probably it
shouldn’t break.















San Francisco Selenium Meetup March 4th 2014
Basic Nightwatch Test for
tilt.com
San Francisco Selenium Meetup March 4th 2014
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com Video': function(client) {!
client!
.url('https://www.tilt.com')!
.waitForElementVisible(‘.video-link', 1000)!
.pause(3000) // vidyard JS must have loaded!
.click('.video-link')!
.waitForElementVisible('.vidyard_tclose', 3000)!
.click('.vidyard_tclose')!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com Video': function(client) {!
client!
.url('https://www.tilt.com')!
.waitForElementVisible(‘.video-link', 1000)!
.pause(3000) // vidyard JS must have loaded!
.click('.video-link')!
.waitForElementVisible('.vidyard_tclose', 3000)!
.click('.vidyard_tclose')!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Arrange
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com Video': function(client) {!
client!
.url('https://www.tilt.com')!
.waitForElementVisible(‘.video-link', 1000)!
.pause(3000) // vidyard JS must have loaded!
.click('.video-link')!
.waitForElementVisible('.vidyard_tclose', 3000)!
.click('.vidyard_tclose')!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Act
Basic Nightwatch Test for
tilt.com
module.exports = {!
'Tilt.com Video': function(client) {!
client!
.url('https://www.tilt.com')!
.waitForElementVisible(‘.video-link', 1000)!
.pause(3000) // vidyard JS must have loaded!
.click('.video-link')!
.waitForElementVisible('.vidyard_tclose', 3000)!
.click('.vidyard_tclose')!
.end();!
}!
};!
San Francisco Selenium Meetup March 4th 2014
Assert
Basic Homepage Page
Object
module.exports = function (client) {!
var selectors = {!
title: '.hero-title',!
video: '.vidyard_tbox',!
videoLink: '.video-link',!
videoClose: '.vidyard_tclose'!
};!
this.selectors = selectors;!
!
this.openVideo = function() {!
return client!
.waitForElementVisible(selectors.videoLink, 1000)!
.click(selectors.videoLink)!
.waitForElementVisible(selectors.videoClose, 5000);!
};!
!
this.closeVideo = function() {!
return client!
.waitForElementVisible(selectors.videoClose, 1000)!
.click(selectors.videoClose)!
.waitForElementNotVisible(selectors.videoClose, 5000);!
};!
};!
San Francisco Selenium Meetup March 4th 2014
Basic Homepage Page
Object
module.exports = function (client) {!
var selectors = {!
title: '.hero-title',!
video: '.vidyard_tbox',!
videoLink: '.video-link',!
videoClose: '.vidyard_tclose'!
};!
this.selectors = selectors;!
!
this.openVideo = function() {!
return client!
.waitForElementVisible(selectors.videoLink, 1000)!
.click(selectors.videoLink)!
.waitForElementVisible(selectors.videoClose, 5000);!
};!
!
this.closeVideo = function() {!
return client!
.waitForElementVisible(selectors.videoClose, 1000)!
.click(selectors.videoClose)!
.waitForElementNotVisible(selectors.videoClose, 5000);!
};!
};!
San Francisco Selenium Meetup March 4th 2014
Unify DOM selectors

as variables
Basic Homepage Page
Object
module.exports = function (client) {!
var selectors = {!
title: '.hero-title',!
video: '.vidyard_tbox',!
videoLink: '.video-link',!
videoClose: '.vidyard_tclose'!
};!
this.selectors = selectors;!
!
this.openVideo = function() {!
return client!
.waitForElementVisible(selectors.videoLink, 1000)!
.click(selectors.videoLink)!
.waitForElementVisible(selectors.videoClose, 5000);!
};!
!
this.closeVideo = function() {!
return client!
.waitForElementVisible(selectors.videoClose, 1000)!
.click(selectors.videoClose)!
.waitForElementNotVisible(selectors.videoClose, 5000);!
};!
};!
San Francisco Selenium Meetup March 4th 2014
Utility Methods for
Tests
Basic Page Objects
module.exports = {!
!
'Tilt.com Video': function(client) {!
var title = 'Collect money from your group';!
client!
.url(‘https://www.tilt.com')!
.page.homepage().openVideo()!
.verify.elementPresent(!
client.page.homepage().selectors.video!
)!
.page.homepage().closeVideo()!
.end();!
}!
!
};!
San Francisco Selenium Meetup March 4th 2014
Basic Page Objects
module.exports = {!
!
'Tilt.com Video': function(client) {!
var title = 'Collect money from your group';!
client!
.url(‘https://www.tilt.com')!
.page.homepage().openVideo()!
.verify.elementPresent(!
client.page.homepage().selectors.video!
)!
.page.homepage().closeVideo()!
.end();!
}!
!
};!
San Francisco Selenium Meetup March 4th 2014
No selectors in tests
Basic Page Objects
module.exports = {!
!
'Tilt.com Video': function(client) {!
var title = 'Collect money from your group';!
client!
.url(‘https://www.tilt.com')!
.page.homepage().openVideo()!
.verify.elementPresent(!
client.page.homepage().selectors.video!
)!
.page.homepage().closeVideo()!
.end();!
}!
!
};!
San Francisco Selenium Meetup March 4th 2014
Waits common
to the page now inside
the page object
Why Nightwatch?
• Three features you would otherwise build yourself
• Page Objects
• Custom Commands
• Custom Assertions
San Francisco Selenium Meetup March 4th 2014
Page Objects
• Basic design pattern - abstract page behavior out of
selectors
• Add in common functions for interacting with page
• In our repo: abstract different desktop/mobile behavior
into the page object
San Francisco Selenium Meetup March 4th 2014
Page Object Example:
“Contribution Flow”
this.enterContributionAmount = function(amount) {!
var sels = (client.globals.isDesktop) ?!
selectors.desktop : selectors.mobile;!
return client!
.waitForElementVisible(sels.contributeAmountField,!
client.globals.timeout)!
.setValue(sels.contributeAmountField, amount)!
.pause(500)!
.click(seles.contributeStep1Submit)!
.waitForElementNotVisible(!
sels.contributeStep1Submit,!
client.globals.timeout!
);!
};!
San Francisco Selenium Meetup March 4th 2014
Page Objects: Desktop vs
Mobile
San Francisco Selenium Meetup March 4th 2014
Page Objects: Desktop vs
Mobile
San Francisco Selenium Meetup March 4th 2014
Expiration is

two fields
Expiration is 

one field
Page Objects: Desktop vs
Mobile
this.enterCreditCard = function(cardNumber, expirationMonth,!
expirationYear, cvc, zip) {!
var platformSelectors = (client.globals.isDesktop) ?!
selectors.desktop :!
selectors.mobile;!
var d = client!
.waitForElementVisible(platformSelectors.cardNumber,!
client.globals.timeout)!
.setValue(platformSelectors.cardNumber,!
[cardNumber, client.Keys.TAB]);!
if (client.globals.isDesktop) {!
d = d.setValue(platformSelectors.expiration,!
[expirationMonth + '/' + expirationYear,!
client.Keys.TAB]);!
} else {!
d = d!
.setValue(platformSelectors.expirationMonth, [expirationMonth,!
client.Keys.TAB])!
.setValue(platformSelectors.expirationYear, [expirationYear,!
client.Keys.TAB]);!
}!
return d!
.setValue(platformSelectors.cvc, [cvc, client.Keys.TAB])!
.setValue(platformSelectors.zip, [zip, client.Keys.TAB]);!
}!
San Francisco Selenium Meetup March 4th 2014
Custom Commands
• Build business-specific language for your tests
• Example commands from our repository:
• createEmailUser
• createEmailUserAndLogIn
• createFacebookTestUser
• setCountry
San Francisco Selenium Meetup March 4th 2014
Custom Assertions
• Add specific assertions to your tests
• We don’t use these as much - examples from our repo:
• isLoggedIn
• linkMatches(text, href)
• lightboxHasHeader
San Francisco Selenium Meetup March 4th 2014
Test Suite Benefits
San Francisco Selenium Meetup March 4th 2014
Bootstrapping JavaScript
• Tilt runs on a hybrid stack
• Old code uses jQuery/jQuery UI for frontend widgets
• New code uses React
• Server-side rendering with a node.js service
San Francisco Selenium Meetup March 4th 2014
Server-side Rendering
Challenges
• Elements in the DOM but not functional
• Elements visible but not functional
San Francisco Selenium Meetup March 4th 2014
Opening the User Menu
San Francisco Selenium Meetup March 4th 2014
Opening the User Menu
this.openUserMenu = function(callback) {!
return client!
.waitForElementVisible(!
this.selectors.menuToggle,!
client.globals.timeout!
)!
// completely arbitrary wait time so that menu JS !
// initializes!
.pause(5000)!
.click(this.selectors.menuToggle)!
.waitForElementVisible('.user-menu', 1000, callback);!
};!
San Francisco Selenium Meetup March 4th 2014
Opening the User Menu
this.openUserMenu = function(callback) {!
return client!
.waitForElementVisible(!
this.selectors.menuToggle,!
client.globals.timeout!
)!
// completely arbitrary wait time so that menu JS !
// initializes!
.pause(5000)!
.click(this.selectors.menuToggle)!
.waitForElementVisible('.user-menu', 1000, callback);!
};!
San Francisco Selenium Meetup March 4th 2014
JavaScript must have
initialized before menu is
functional!
Old Code
window.rewireReact = function() {!
$('[data-mount-as]').each(function() {!
var $this = $(this),!
name = $this.attr('data-mount-as'),!
props = JSON.parse($this.attr('data-props'));!
!
$this.removeAttr('data-mount-as');!
!
// This causes event handlers on the component !
// to become functional!
var component = ReactComponents[name];!
React.render(React.createElement(component, props),!
$this.get(0));!
});!
};!
!
$(document).ready(window.rewireReact);
San Francisco Selenium Meetup March 4th 2014
Old Code
window.rewireReact = function() {!
$('[data-mount-as]').each(function() {!
var $this = $(this),!
name = $this.attr('data-mount-as'),!
props = JSON.parse($this.attr('data-props'));!
!
$this.removeAttr('data-mount-as');!
!
// This causes event handlers on the component !
// to become functional!
var component = ReactComponents[name];!
React.render(React.createElement(component, props),!
$this.get(0));!
});!
};!
!
$(document).ready(window.rewireReact);
Menus only functional
after document ready!
San Francisco Selenium Meetup March 4th 2014
New Code
<!-- Tilt JavaScript bundle -->!
<script src="https://d25y59nqso5bzg.cloudfront.net/built/home-
ce348751.js"></script>!
<!-- all JS is loaded, make the page functional -->!
<script type=“text/javascript”>window.rewireReact();</script>!
San Francisco Selenium Meetup March 4th 2014
New Code
<!-- Tilt JavaScript bundle -->!
<script src="https://d25y59nqso5bzg.cloudfront.net/built/home-
ce348751.js"></script>!
<!-- all JS is loaded, make the page functional -->!
<script type=“text/javascript”>window.rewireReact();</script>!
No more sticky menus!
San Francisco Selenium Meetup March 4th 2014
Test Suite Suggestions
in case you are green-fielding a new test suite
San Francisco Selenium Meetup March 4th 2014
Develop and run tests against
an integration environment
Staging, production, etc - not someone’s local box
San Francisco Selenium Meetup March 4th 2014
Run Tests Constantly
San Francisco Selenium Meetup March 4th 2014
Run Tests Constantly
• We run our tests every 10 minutes against staging
• When you add a wait time to a test you have asserted
that your system always responds in that amount of
time
• See how tests behave in an integration environment
and adjust
San Francisco Selenium Meetup March 4th 2014
Happy Path Tests First
Sad path tests … eventually
San Francisco Selenium Meetup March 4th 2014
Single Responsibility Page
Objects
San Francisco Selenium Meetup March 4th 2014
Page Objects…
• Don’t do test setup
• they don’t make users
• they don’t make campaigns
• Don’t orchestrate complex flows between pages
• Do one thing and one thing only
• (yes this puts more verbosity into your tests)
San Francisco Selenium Meetup March 4th 2014
Problems We’ve Had With
Nightwatch
your mileage may vary!
San Francisco Selenium Meetup March 4th 2014
Hard to run an individual test
Something like mocha —grep would be really great

(currently I just comment out tests)
San Francisco Selenium Meetup March 4th 2014
No Page Object
Documentation Yet
We had to dig through the repo to really understand how to use these
San Francisco Selenium Meetup March 4th 2014
Nondeterminstic Behavior
Page objects sometimes inherit a stale selenium session, repeating “stale element exception”
Use —verbose to see what’s happening if you are really stumped
San Francisco Selenium Meetup March 4th 2014
waitForElementVisible
failures
When running an individual test file, a waitForElementVisible failure causes all
the rest of the tests to be skipped
San Francisco Selenium Meetup March 4th 2014
Nightwatch Pull Requests I
Really Want Merged
• Distinguish between test failures and selenium errors
when taking screenshots: https://github.com/
beatfactor/nightwatch/pull/316
• Run individual test files in parallel with test workers
https://github.com/beatfactor/nightwatch/pull/317
San Francisco Selenium Meetup March 4th 2014
Next Steps for Nightwatch at
Tilt
• Replicate full functionality of old suite
• Cross-browser testing with Saucelabs
• Shard test suite (currently 2 jobs) into specific suites:
• Selenium-Nightwatch-Contribution, Selenium-
Nightwatch-Login, etc.
San Francisco Selenium Meetup March 4th 2014
Thank You!
• Questions?
San Francisco Selenium Meetup March 4th 2014

Contenu connexe

Tendances

JavaScript Testing VIA Selenium
JavaScript Testing VIA SeleniumJavaScript Testing VIA Selenium
JavaScript Testing VIA Selenium
Adam Christian
 

Tendances (20)

ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 -  Fullstack end-to-end Test Automation with node.jsForwardJS 2017 -  Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
 
Testing nightwatch, by David Torroija
Testing nightwatch, by David TorroijaTesting nightwatch, by David Torroija
Testing nightwatch, by David Torroija
 
Night Watch with QA
Night Watch with QANight Watch with QA
Night Watch with QA
 
Protractor Tutorial Quality in Agile 2015
Protractor Tutorial Quality in Agile 2015Protractor Tutorial Quality in Agile 2015
Protractor Tutorial Quality in Agile 2015
 
Automated Web Testing using JavaScript
Automated Web Testing using JavaScriptAutomated Web Testing using JavaScript
Automated Web Testing using JavaScript
 
Front-end Automated Testing
Front-end Automated TestingFront-end Automated Testing
Front-end Automated Testing
 
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
 
Testing frontends with nightwatch & saucelabs
Testing frontends with nightwatch & saucelabsTesting frontends with nightwatch & saucelabs
Testing frontends with nightwatch & saucelabs
 
Unit-testing and E2E testing in JS
Unit-testing and E2E testing in JSUnit-testing and E2E testing in JS
Unit-testing and E2E testing in JS
 
Real World Selenium Testing
Real World Selenium TestingReal World Selenium Testing
Real World Selenium Testing
 
AngularJS and Protractor
AngularJS and ProtractorAngularJS and Protractor
AngularJS and Protractor
 
Webdriver cheatsheets summary
Webdriver cheatsheets summaryWebdriver cheatsheets summary
Webdriver cheatsheets summary
 
Automated Smoke Tests with Protractor
Automated Smoke Tests with ProtractorAutomated Smoke Tests with Protractor
Automated Smoke Tests with Protractor
 
JavaScript Testing VIA Selenium
JavaScript Testing VIA SeleniumJavaScript Testing VIA Selenium
JavaScript Testing VIA Selenium
 
Automate testing with behat, selenium, phantom js and nightwatch.js (5)
Automate testing with behat, selenium, phantom js and nightwatch.js (5)Automate testing with behat, selenium, phantom js and nightwatch.js (5)
Automate testing with behat, selenium, phantom js and nightwatch.js (5)
 
Building testable chrome extensions
Building testable chrome extensionsBuilding testable chrome extensions
Building testable chrome extensions
 
APIs: A Better Alternative to Page Objects
APIs: A Better Alternative to Page ObjectsAPIs: A Better Alternative to Page Objects
APIs: A Better Alternative to Page Objects
 
Automated Testing in Angular Slides
Automated Testing in Angular SlidesAutomated Testing in Angular Slides
Automated Testing in Angular Slides
 
Automation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and BeyondAutomation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and Beyond
 
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
 

En vedette

En vedette (11)

Getting By Without "QA"
Getting By Without "QA"Getting By Without "QA"
Getting By Without "QA"
 
Anointing to excel
Anointing to excelAnointing to excel
Anointing to excel
 
DrupalCon Dublin 2016 - Automated browser testing with Nightwatch.js
DrupalCon Dublin 2016 - Automated browser testing with Nightwatch.jsDrupalCon Dublin 2016 - Automated browser testing with Nightwatch.js
DrupalCon Dublin 2016 - Automated browser testing with Nightwatch.js
 
The Javascript Toolkit 2.0
The Javascript Toolkit 2.0The Javascript Toolkit 2.0
The Javascript Toolkit 2.0
 
Evolving legacy to microservices and ddd
Evolving legacy to microservices and dddEvolving legacy to microservices and ddd
Evolving legacy to microservices and ddd
 
Fashion Forward_ VIVACITY 7
Fashion Forward_ VIVACITY 7Fashion Forward_ VIVACITY 7
Fashion Forward_ VIVACITY 7
 
Анастасия Войтова: Здоровая психологическая атмосфера в жизни разработчика, ...
Анастасия Войтова:  Здоровая психологическая атмосфера в жизни разработчика, ...Анастасия Войтова:  Здоровая психологическая атмосфера в жизни разработчика, ...
Анастасия Войтова: Здоровая психологическая атмосфера в жизни разработчика, ...
 
Benchmark Morgages, Inc. Now Hiring
Benchmark Morgages, Inc. Now HiringBenchmark Morgages, Inc. Now Hiring
Benchmark Morgages, Inc. Now Hiring
 
Indie Music for the Indie Writer: A Productivity Playlist by Scribendi.com
Indie Music for the Indie Writer: A Productivity Playlist by Scribendi.com Indie Music for the Indie Writer: A Productivity Playlist by Scribendi.com
Indie Music for the Indie Writer: A Productivity Playlist by Scribendi.com
 
Romanticism
RomanticismRomanticism
Romanticism
 
Photography
Photography Photography
Photography
 

Similaire à Nightwatch at Tilt

Building Things Fast - and getting approval
Building Things Fast - and getting approvalBuilding Things Fast - and getting approval
Building Things Fast - and getting approval
Simon Willison
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
Frank Rousseau
 
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
崇之 清水
 

Similaire à Nightwatch at Tilt (20)

Turn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesTurn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modules
 
ApacheCon 2005
ApacheCon 2005ApacheCon 2005
ApacheCon 2005
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unit
 
BPM-3 Advanced Workflow Deep Dive
BPM-3 Advanced Workflow Deep DiveBPM-3 Advanced Workflow Deep Dive
BPM-3 Advanced Workflow Deep Dive
 
How I Became a WordPress Hacker
How I Became a WordPress HackerHow I Became a WordPress Hacker
How I Became a WordPress Hacker
 
Building Things Fast - and getting approval
Building Things Fast - and getting approvalBuilding Things Fast - and getting approval
Building Things Fast - and getting approval
 
Service Worker - Reliability bits
Service Worker - Reliability bitsService Worker - Reliability bits
Service Worker - Reliability bits
 
FamilySearch Reference Client
FamilySearch Reference ClientFamilySearch Reference Client
FamilySearch Reference Client
 
Effectively Testing Services - Burlington Ruby Conf
Effectively Testing Services - Burlington Ruby ConfEffectively Testing Services - Burlington Ruby Conf
Effectively Testing Services - Burlington Ruby Conf
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
 
Introduction to Selenium and Ruby
Introduction to Selenium and RubyIntroduction to Selenium and Ruby
Introduction to Selenium and Ruby
 
Selenium bootcamp slides
Selenium bootcamp slides   Selenium bootcamp slides
Selenium bootcamp slides
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
 
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
 
The Art of AngularJS in 2015 - Angular Summit 2015
The Art of AngularJS in 2015 - Angular Summit 2015The Art of AngularJS in 2015 - Angular Summit 2015
The Art of AngularJS in 2015 - Angular Summit 2015
 
Deploying Next Gen Systems with Zero Downtime
Deploying Next Gen Systems with Zero DowntimeDeploying Next Gen Systems with Zero Downtime
Deploying Next Gen Systems with Zero Downtime
 
How to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMHow to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAM
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
How to build Client Side Applications with WordPress and WP-API | #wcmia
How to build Client Side Applications with WordPress and WP-API | #wcmiaHow to build Client Side Applications with WordPress and WP-API | #wcmia
How to build Client Side Applications with WordPress and WP-API | #wcmia
 
PWA Roadshow Korea - Service Worker
PWA Roadshow Korea - Service WorkerPWA Roadshow Korea - Service Worker
PWA Roadshow Korea - Service Worker
 

Dernier

CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Dernier (20)

Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 

Nightwatch at Tilt

  • 1. Nightwatch at Tilt San Francisco Selenium Meetup March 4th, 2015
  • 2. About Me • NJ -> UIUC -> Penn State -> Blacksburg VA -> SF Bay Area • Grad School -> WebDev -> DevOps Lead -> Frontend Lead • Java -> Python -> JavaScript • @tildedave • Blog, etc: tildedave.com San Francisco Selenium Meetup March 4th 2014
  • 3. Tilt Make Amazing Things Happen San Francisco Selenium Meetup March 4th 2014
  • 4. Tilt is a social crowd-funding company San Francisco Selenium Meetup March 4th 2014
  • 5. San Francisco Selenium Meetup March 4th 2014
  • 6. “Move Fast and Break Things” It turns out that this statement is a lie San Francisco Selenium Meetup March 4th 2014
  • 7. Golden Features • Login • Signup • Contribution Flow • Commenting • Admin Payouts • … really no user flow can ever break acceptably San Francisco Selenium Meetup March 4th 2014
  • 8. Selenium at Tilt San Francisco Selenium Meetup March 4th 2014
  • 9. History of Selenium at Tilt • CI/CD environment - push code to production daily • No dedicated QA resources as part of the development team • Must not break core flows San Francisco Selenium Meetup March 4th 2014
  • 10. History of Selenium at Tilt • Pre-History: PhantomJS/PhantomProxy - no visibility on failures • February 2013 - Introduce Selenium for functional testing (2.31.0) • June 2014 - Selenium tests vs staging/production as a ‘health check’ of deployed code (2.42.2) San Francisco Selenium Meetup March 4th 2014
  • 11. Ancient Code: Phantom JS ! promiseIt('can contribute to regular campaign', function(p) {! return p! .withPrimedCampaign()! .thenOpenCampaignPage()! .thenLightboxClick('.campaign-tilt-info .btn')! .thenType('#amount_lightbox', '2.00')! .thenClickAndWaitForDocumentReady('#contribute-continue')! .thenVerifyElementContents('#display-total', '2.05')! .thenFillCCForm()! .thenClickAndWaitAndFailIfLightboxCloses('#confirm-btn')! .thenWait(1000)! .thenVerifyElementVisible('#just_contributed')! .thenCancelCampaign();! });! ! San Francisco Selenium Meetup March 4th 2014
  • 12. Today: Nightwatch Tests 'Can contribute as admin': function(client) {! var selectors = client.page.campaign().selectors;! client.page.homepage().load()! .createFBUserAndLogIn()! .createCampaignAPI({}, function(campaign) {! return client.page.campaign().load(campaign.title);! })! .page.campaign().clickContribute()! .page.contributionFlow().enterContributionAmount('2')! .page.contributionFlow().checkOut()! .page.contributionFlow().skipInviteAndShare()! // admins don't get asked to comment! .verify.elementNotPresent(selectors.lightboxTitle)! .end();! }! San Francisco Selenium Meetup March 4th 2014
  • 13. Nightwatch at Tilt • September 2014 • Selenium suite run on every branch before merge • Lots of flapping tests - developers often rerun tests until green • Test suite expansion seems like a nightmare - lots of selectors in tests, copy/pasted setup, etc • October 2014 - We start investigating better solutions San Francisco Selenium Meetup March 4th 2014
  • 14. Nightwatch.js San Francisco Selenium Meetup March 4th 2014
  • 15. Nightwatch • http://nightwatchjs.org/ • Better interface to selenium-webdriver • Library provides Custom Commands, Page Objects, and Assertions • It’s in JavaScript! San Francisco Selenium Meetup March 4th 2014
  • 16. Why Nightwatch for Tilt? • It’s in JavaScript • Using Ruby just for tests is a hard sell • Easily use npm modules as part of your tests • Builds in important concepts that Tilt had rolled itself (custom commands) or should have (page objects) • Old suite had too much technical debt to be saved San Francisco Selenium Meetup March 4th 2014
  • 17. Tiltcabulary • Users - users of the site • Campaigns - crowdfunding campaigns San Francisco Selenium Meetup March 4th 2014
  • 18. Basic Nightwatch Test for tilt.com San Francisco Selenium Meetup March 4th 2014
  • 19. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com': function(client) {! var title = 'Collect money from your group';! client! .url('https://www.tilt.com')! .waitForElementVisible('.hero-title', 1000)! .verify.containsText('.hero-title',! title)! .end();! }! };! San Francisco Selenium Meetup March 4th 2014
  • 20. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com': function(client) {! var title = 'Collect money from your group';! client! .url('https://www.tilt.com')! .waitForElementVisible('.hero-title', 1000)! .verify.containsText('.hero-title',! title)! .end();! }! };! San Francisco Selenium Meetup March 4th 2014 Arrange
  • 21. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com': function(client) {! var title = 'Collect money from your group';! client! .url('https://www.tilt.com')! .waitForElementVisible('.hero-title', 1000)! .verify.containsText('.hero-title',! title)! .end();! }! };! San Francisco Selenium Meetup March 4th 2014 Assert
  • 22. Basic Nightwatch Test for tilt.com • We have a video on our homepage. Probably it shouldn’t break.
 
 
 
 
 
 
 
 San Francisco Selenium Meetup March 4th 2014
  • 23. Basic Nightwatch Test for tilt.com San Francisco Selenium Meetup March 4th 2014
  • 24. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com Video': function(client) {! client! .url('https://www.tilt.com')! .waitForElementVisible(‘.video-link', 1000)! .pause(3000) // vidyard JS must have loaded! .click('.video-link')! .waitForElementVisible('.vidyard_tclose', 3000)! .click('.vidyard_tclose')! .end();! }! };! San Francisco Selenium Meetup March 4th 2014
  • 25. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com Video': function(client) {! client! .url('https://www.tilt.com')! .waitForElementVisible(‘.video-link', 1000)! .pause(3000) // vidyard JS must have loaded! .click('.video-link')! .waitForElementVisible('.vidyard_tclose', 3000)! .click('.vidyard_tclose')! .end();! }! };! San Francisco Selenium Meetup March 4th 2014 Arrange
  • 26. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com Video': function(client) {! client! .url('https://www.tilt.com')! .waitForElementVisible(‘.video-link', 1000)! .pause(3000) // vidyard JS must have loaded! .click('.video-link')! .waitForElementVisible('.vidyard_tclose', 3000)! .click('.vidyard_tclose')! .end();! }! };! San Francisco Selenium Meetup March 4th 2014 Act
  • 27. Basic Nightwatch Test for tilt.com module.exports = {! 'Tilt.com Video': function(client) {! client! .url('https://www.tilt.com')! .waitForElementVisible(‘.video-link', 1000)! .pause(3000) // vidyard JS must have loaded! .click('.video-link')! .waitForElementVisible('.vidyard_tclose', 3000)! .click('.vidyard_tclose')! .end();! }! };! San Francisco Selenium Meetup March 4th 2014 Assert
  • 28. Basic Homepage Page Object module.exports = function (client) {! var selectors = {! title: '.hero-title',! video: '.vidyard_tbox',! videoLink: '.video-link',! videoClose: '.vidyard_tclose'! };! this.selectors = selectors;! ! this.openVideo = function() {! return client! .waitForElementVisible(selectors.videoLink, 1000)! .click(selectors.videoLink)! .waitForElementVisible(selectors.videoClose, 5000);! };! ! this.closeVideo = function() {! return client! .waitForElementVisible(selectors.videoClose, 1000)! .click(selectors.videoClose)! .waitForElementNotVisible(selectors.videoClose, 5000);! };! };! San Francisco Selenium Meetup March 4th 2014
  • 29. Basic Homepage Page Object module.exports = function (client) {! var selectors = {! title: '.hero-title',! video: '.vidyard_tbox',! videoLink: '.video-link',! videoClose: '.vidyard_tclose'! };! this.selectors = selectors;! ! this.openVideo = function() {! return client! .waitForElementVisible(selectors.videoLink, 1000)! .click(selectors.videoLink)! .waitForElementVisible(selectors.videoClose, 5000);! };! ! this.closeVideo = function() {! return client! .waitForElementVisible(selectors.videoClose, 1000)! .click(selectors.videoClose)! .waitForElementNotVisible(selectors.videoClose, 5000);! };! };! San Francisco Selenium Meetup March 4th 2014 Unify DOM selectors
 as variables
  • 30. Basic Homepage Page Object module.exports = function (client) {! var selectors = {! title: '.hero-title',! video: '.vidyard_tbox',! videoLink: '.video-link',! videoClose: '.vidyard_tclose'! };! this.selectors = selectors;! ! this.openVideo = function() {! return client! .waitForElementVisible(selectors.videoLink, 1000)! .click(selectors.videoLink)! .waitForElementVisible(selectors.videoClose, 5000);! };! ! this.closeVideo = function() {! return client! .waitForElementVisible(selectors.videoClose, 1000)! .click(selectors.videoClose)! .waitForElementNotVisible(selectors.videoClose, 5000);! };! };! San Francisco Selenium Meetup March 4th 2014 Utility Methods for Tests
  • 31. Basic Page Objects module.exports = {! ! 'Tilt.com Video': function(client) {! var title = 'Collect money from your group';! client! .url(‘https://www.tilt.com')! .page.homepage().openVideo()! .verify.elementPresent(! client.page.homepage().selectors.video! )! .page.homepage().closeVideo()! .end();! }! ! };! San Francisco Selenium Meetup March 4th 2014
  • 32. Basic Page Objects module.exports = {! ! 'Tilt.com Video': function(client) {! var title = 'Collect money from your group';! client! .url(‘https://www.tilt.com')! .page.homepage().openVideo()! .verify.elementPresent(! client.page.homepage().selectors.video! )! .page.homepage().closeVideo()! .end();! }! ! };! San Francisco Selenium Meetup March 4th 2014 No selectors in tests
  • 33. Basic Page Objects module.exports = {! ! 'Tilt.com Video': function(client) {! var title = 'Collect money from your group';! client! .url(‘https://www.tilt.com')! .page.homepage().openVideo()! .verify.elementPresent(! client.page.homepage().selectors.video! )! .page.homepage().closeVideo()! .end();! }! ! };! San Francisco Selenium Meetup March 4th 2014 Waits common to the page now inside the page object
  • 34. Why Nightwatch? • Three features you would otherwise build yourself • Page Objects • Custom Commands • Custom Assertions San Francisco Selenium Meetup March 4th 2014
  • 35. Page Objects • Basic design pattern - abstract page behavior out of selectors • Add in common functions for interacting with page • In our repo: abstract different desktop/mobile behavior into the page object San Francisco Selenium Meetup March 4th 2014
  • 36. Page Object Example: “Contribution Flow” this.enterContributionAmount = function(amount) {! var sels = (client.globals.isDesktop) ?! selectors.desktop : selectors.mobile;! return client! .waitForElementVisible(sels.contributeAmountField,! client.globals.timeout)! .setValue(sels.contributeAmountField, amount)! .pause(500)! .click(seles.contributeStep1Submit)! .waitForElementNotVisible(! sels.contributeStep1Submit,! client.globals.timeout! );! };! San Francisco Selenium Meetup March 4th 2014
  • 37. Page Objects: Desktop vs Mobile San Francisco Selenium Meetup March 4th 2014
  • 38. Page Objects: Desktop vs Mobile San Francisco Selenium Meetup March 4th 2014 Expiration is
 two fields Expiration is 
 one field
  • 39. Page Objects: Desktop vs Mobile this.enterCreditCard = function(cardNumber, expirationMonth,! expirationYear, cvc, zip) {! var platformSelectors = (client.globals.isDesktop) ?! selectors.desktop :! selectors.mobile;! var d = client! .waitForElementVisible(platformSelectors.cardNumber,! client.globals.timeout)! .setValue(platformSelectors.cardNumber,! [cardNumber, client.Keys.TAB]);! if (client.globals.isDesktop) {! d = d.setValue(platformSelectors.expiration,! [expirationMonth + '/' + expirationYear,! client.Keys.TAB]);! } else {! d = d! .setValue(platformSelectors.expirationMonth, [expirationMonth,! client.Keys.TAB])! .setValue(platformSelectors.expirationYear, [expirationYear,! client.Keys.TAB]);! }! return d! .setValue(platformSelectors.cvc, [cvc, client.Keys.TAB])! .setValue(platformSelectors.zip, [zip, client.Keys.TAB]);! }! San Francisco Selenium Meetup March 4th 2014
  • 40. Custom Commands • Build business-specific language for your tests • Example commands from our repository: • createEmailUser • createEmailUserAndLogIn • createFacebookTestUser • setCountry San Francisco Selenium Meetup March 4th 2014
  • 41. Custom Assertions • Add specific assertions to your tests • We don’t use these as much - examples from our repo: • isLoggedIn • linkMatches(text, href) • lightboxHasHeader San Francisco Selenium Meetup March 4th 2014
  • 42. Test Suite Benefits San Francisco Selenium Meetup March 4th 2014
  • 43. Bootstrapping JavaScript • Tilt runs on a hybrid stack • Old code uses jQuery/jQuery UI for frontend widgets • New code uses React • Server-side rendering with a node.js service San Francisco Selenium Meetup March 4th 2014
  • 44. Server-side Rendering Challenges • Elements in the DOM but not functional • Elements visible but not functional San Francisco Selenium Meetup March 4th 2014
  • 45. Opening the User Menu San Francisco Selenium Meetup March 4th 2014
  • 46. Opening the User Menu this.openUserMenu = function(callback) {! return client! .waitForElementVisible(! this.selectors.menuToggle,! client.globals.timeout! )! // completely arbitrary wait time so that menu JS ! // initializes! .pause(5000)! .click(this.selectors.menuToggle)! .waitForElementVisible('.user-menu', 1000, callback);! };! San Francisco Selenium Meetup March 4th 2014
  • 47. Opening the User Menu this.openUserMenu = function(callback) {! return client! .waitForElementVisible(! this.selectors.menuToggle,! client.globals.timeout! )! // completely arbitrary wait time so that menu JS ! // initializes! .pause(5000)! .click(this.selectors.menuToggle)! .waitForElementVisible('.user-menu', 1000, callback);! };! San Francisco Selenium Meetup March 4th 2014 JavaScript must have initialized before menu is functional!
  • 48. Old Code window.rewireReact = function() {! $('[data-mount-as]').each(function() {! var $this = $(this),! name = $this.attr('data-mount-as'),! props = JSON.parse($this.attr('data-props'));! ! $this.removeAttr('data-mount-as');! ! // This causes event handlers on the component ! // to become functional! var component = ReactComponents[name];! React.render(React.createElement(component, props),! $this.get(0));! });! };! ! $(document).ready(window.rewireReact); San Francisco Selenium Meetup March 4th 2014
  • 49. Old Code window.rewireReact = function() {! $('[data-mount-as]').each(function() {! var $this = $(this),! name = $this.attr('data-mount-as'),! props = JSON.parse($this.attr('data-props'));! ! $this.removeAttr('data-mount-as');! ! // This causes event handlers on the component ! // to become functional! var component = ReactComponents[name];! React.render(React.createElement(component, props),! $this.get(0));! });! };! ! $(document).ready(window.rewireReact); Menus only functional after document ready! San Francisco Selenium Meetup March 4th 2014
  • 50. New Code <!-- Tilt JavaScript bundle -->! <script src="https://d25y59nqso5bzg.cloudfront.net/built/home- ce348751.js"></script>! <!-- all JS is loaded, make the page functional -->! <script type=“text/javascript”>window.rewireReact();</script>! San Francisco Selenium Meetup March 4th 2014
  • 51. New Code <!-- Tilt JavaScript bundle -->! <script src="https://d25y59nqso5bzg.cloudfront.net/built/home- ce348751.js"></script>! <!-- all JS is loaded, make the page functional -->! <script type=“text/javascript”>window.rewireReact();</script>! No more sticky menus! San Francisco Selenium Meetup March 4th 2014
  • 52. Test Suite Suggestions in case you are green-fielding a new test suite San Francisco Selenium Meetup March 4th 2014
  • 53. Develop and run tests against an integration environment Staging, production, etc - not someone’s local box San Francisco Selenium Meetup March 4th 2014
  • 54. Run Tests Constantly San Francisco Selenium Meetup March 4th 2014
  • 55. Run Tests Constantly • We run our tests every 10 minutes against staging • When you add a wait time to a test you have asserted that your system always responds in that amount of time • See how tests behave in an integration environment and adjust San Francisco Selenium Meetup March 4th 2014
  • 56. Happy Path Tests First Sad path tests … eventually San Francisco Selenium Meetup March 4th 2014
  • 57. Single Responsibility Page Objects San Francisco Selenium Meetup March 4th 2014
  • 58. Page Objects… • Don’t do test setup • they don’t make users • they don’t make campaigns • Don’t orchestrate complex flows between pages • Do one thing and one thing only • (yes this puts more verbosity into your tests) San Francisco Selenium Meetup March 4th 2014
  • 59. Problems We’ve Had With Nightwatch your mileage may vary! San Francisco Selenium Meetup March 4th 2014
  • 60. Hard to run an individual test Something like mocha —grep would be really great
 (currently I just comment out tests) San Francisco Selenium Meetup March 4th 2014
  • 61. No Page Object Documentation Yet We had to dig through the repo to really understand how to use these San Francisco Selenium Meetup March 4th 2014
  • 62. Nondeterminstic Behavior Page objects sometimes inherit a stale selenium session, repeating “stale element exception” Use —verbose to see what’s happening if you are really stumped San Francisco Selenium Meetup March 4th 2014
  • 63. waitForElementVisible failures When running an individual test file, a waitForElementVisible failure causes all the rest of the tests to be skipped San Francisco Selenium Meetup March 4th 2014
  • 64. Nightwatch Pull Requests I Really Want Merged • Distinguish between test failures and selenium errors when taking screenshots: https://github.com/ beatfactor/nightwatch/pull/316 • Run individual test files in parallel with test workers https://github.com/beatfactor/nightwatch/pull/317 San Francisco Selenium Meetup March 4th 2014
  • 65. Next Steps for Nightwatch at Tilt • Replicate full functionality of old suite • Cross-browser testing with Saucelabs • Shard test suite (currently 2 jobs) into specific suites: • Selenium-Nightwatch-Contribution, Selenium- Nightwatch-Login, etc. San Francisco Selenium Meetup March 4th 2014
  • 66. Thank You! • Questions? San Francisco Selenium Meetup March 4th 2014