SlideShare a Scribd company logo
1 of 76
Download to read offline
Join The Darkside 
Selenium testing with Nightwatch.js 
presented by seth mclaughlin on 10.21.14
Nightwatch.js 
learn more: www.nightwatchjs.org
1. Project Overview 
2. Features 
3. Getting Started
"End to End" testing 
1. Navigate to Login page 
2. Locate username form field, type in seth 
3. Locate password form field, type in html5dev 
4. Locate submit form button and click it 
5. Wait for form submission to complete 
6. Verify that title of page is now equal to Welcome!
Selenium 
HTTP 
Test Runner WebDriver Web Browser 
JAVA JAR 
Test Script
Selenium 
HTTP 
Test Runner WebDriver Web Browser 
JAVA JAR 
Test Script
Selenium 
HTTP 
Node.js module 
Test Script 
Test Runner WebDriver Web Browser 
Node.js application JAVA JAR
Selenium 
WebDriver 
Selenium 
WebDriver 
Web 
HTTP 
Test Runner Browser 
JAVA JAR 
Test Script 
Selenium 
Grid 
Selenium 
WebDriver 
Web 
Browser 
JAVA JAR 
Selenium 
WebDriver 
Web 
Browser 
JAVA JAR 
Web 
Browser 
JAVA JAR
Features 
★ Good documentation 
★ Use CSS or XPATH selectors 
★ Test runner can execute sequentially or in parallel 
★ Test filtering by file name pattern, folders and tags 
★ SauceLabs + BrowserStack support 
★ Built in JUnit XML reporting 
★ Extension model for custom commands
created by 
Andrei Rusu 
@beatfactor 
learn more: www.linkedin.com/in/beatfactor
~9,000 
downloads per month 
~2,200 
stars on github 
~150 
forks on github 
~83% 
code coverage 
learn more: www.npmjs.org/package/nightwatch
contributors 
27 
1 
1 
46 
164 
primary contributor (Andrei) 
pending pull requests (from 8/14/14) 
open issues 
closed issues 
learn more: github.com/beatfactor/nightwatch
Sample test: Login flow 
1. Navigate to Login page 
2. Locate username form field, type in seth 
3. Locate password form field, type in html5dev 
4. Locate submit form button and click it 
5. Wait for form submission to complete 
6. Verify that title of page is now equal to Welcome!
├── Nightwatch.js 
└── tests 
└── login.js
├── Nightwatch.js 
└── tests 
└── login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client.url('http://localhost:8000'); 
client.assert.title('Awesome App'); 
client.setValue('input[name=username]', 'seth'); 
client.setValue('input[name=password]', 'html5dev'); 
client.click('input[type=submit]'); 
client.assert.title('Welcome!'); 
client.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client.url('http://localhost:8000'); 
client.assert.title('Awesome App'); 
client.setValue('input[name=username]', 'seth'); 
client.setValue('input[name=password]', 'html5dev'); 
client.click('input[type=submit]'); 
client.assert.title('Welcome!'); 
console.log('all done!'); // wrong! 
client.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client.url('http://localhost:8000'); 
client.assert.title('Awesome App'); 
client.setValue('input[name=username]', 'seth'); 
client.setValue('input[name=password]', 'html5dev'); 
client.click('input[type=submit]'); 
client.assert.title('Welcome!'); 
client.perform(function (client, done) { 
console.log('all done!'); // right! 
}); 
client.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client.url('http://localhost:8000'); 
client.assert.title('Awesome App'); 
client.setValue('input[name=username]', 'seth'); 
client.setValue('input[name=password]', 'html5dev'); 
client.click('input[type=submit]'); 
client.assert.title('Welcome!'); 
client.perform(function (client, done) { 
foo.doSomethingAsync().then(done); 
}); 
client.end(); 
} 
}; 
login.js
├── Nightwatch.js 
└── tests 
└── login.js
module.exports = { 
src_folders: ['./tests'], 
output_folder: './results', 
selenium: { 
start_process: true, 
server_path: './selenium-server-standalone-2.38.0.jar', 
log_path: './results', 
host: '127.0.0.1', 
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
Nightwatch.js
module.exports = { 
src_folders: ['./tests'], 
output_folder: './results', 
selenium: { 
start_process: true, 
server_path: './selenium-server-standalone-2.38.0.jar', 
log_path: './results', 
host: '127.0.0.1', 
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
Nightwatch.js
module.exports = { 
src_folders: ['./tests'], 
output_folder: './results', 
selenium: { 
start_process: true, 
server_path: './selenium-server-standalone-2.38.0.jar', 
log_path: './results', 
host: '127.0.0.1', 
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
Nightwatch.js
module.exports = { 
src_folders: ['./tests'], 
output_folder: './results', 
selenium: { 
start_process: true, 
server_path: './selenium-server-standalone-2.38.0.jar', 
log_path: './results', 
host: '127.0.0.1', 
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
Nightwatch.js
module.exports = { 
src_folders: ['./tests'], 
output_folder: './results', 
selenium: { 
start_process: true, 
server_path: './selenium-server-standalone-2.38.0.jar', 
log_path: './results', 
host: '127.0.0.1', 
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
Nightwatch.js
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
path: './results/screenshots' 
}, 
desiredCapabilities: { 
browserName: 'firefox', 
javascriptEnabled: true, 
acceptSslCerts: true 
} 
} 
} 
}; 
Nightwatch.js
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
path: './results/screenshots' 
}, 
desiredCapabilities: { 
browserName: 'firefox', 
javascriptEnabled: true, 
acceptSslCerts: true 
} 
} 
} 
}; 
Nightwatch.js
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
path: './results/screenshots' 
}, 
desiredCapabilities: { 
browserName: 'firefox', 
javascriptEnabled: true, 
acceptSslCerts: true 
} 
} 
} 
}; 
Nightwatch.js
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
path: './results/screenshots' 
}, 
desiredCapabilities: { 
browserName: 'firefox', 
javascriptEnabled: true, 
acceptSslCerts: true 
} 
} 
} 
}; 
Nightwatch.js
> nightwatch -c ./Nightwatch.js --env default
[Login] Test Suite 
================== 
Running: Fill out form and login 
✔ Testing if the page title equals "Awesome App". 
✔ Testing if the page title equals "Welcome!". 
OK. 2 total assertions passed. (2.233s)
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
Y U HARDCODE 
VALUES ???
Data Driven Tests
├── Nightwatch.js 
├── data 
│ ├── dev.js 
│ └── staging.js 
└── tests 
└── login.js
module.exports = { 
username: 'seth', 
password: 'html5dev', 
urls: { 
login: 'http://localhost:8000' 
} 
}; 
data/dev.js
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
screenshots: { 
enabled: true, 
path: './results/screenshots' 
}, 
desiredCapabilities: { 
browserName: 'firefox', 
javascriptEnabled: true, 
acceptSslCerts: true 
}, 
globals: require('./data/dev') 
} 
} 
Nightwatch.js
module.exports = { 
'Fill out form and login': function (client) { 
var data = client.globals; 
client 
.url(data.urls.login) 
.assert.title('Awesome App') 
.setValue('input[name=username]', data.username) 
.setValue('input[name=password]', data.password) 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
var data = client.globals; 
client 
.url(data.urls.login) 
.assert.title('Awesome App') 
.setValue('input[name=username]', data.username) 
.setValue('input[name=password]', data.password) 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
var data = client.globals; 
client 
.url(data.urls.login) 
.assert.title('Awesome App') 
.setValue('input[name=username]', data.username) 
.setValue('input[name=password]', data.password) 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form and login': function (client) { 
var data = client.globals; 
client 
.url(data.urls.login) 
.assert.title('Awesome App') 
.setValue('input[name=username]', data.username) 
.setValue('input[name=password]', data.password) 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
} 
}; 
login.js
module.exports = { 
'Fill out form': function (client) { 
var data = client.globals; 
client 
.url(data.urls.login) 
.assert.title('Awesome App') 
.setValue('input[name=username]', data.username) 
.setValue('input[name=password]', data.password); 
}, 
'Submit form': function (client) { 
var data = client.globals; 
client 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
}, 
}; 
login.js
module.exports = { 
'Fill out form': function (client) { 
var data = client.globals; 
client 
.url(data.urls.login) 
.assert.title('Awesome App') 
.setValue('input[name=username]', data.username) 
.setValue('input[name=password]', data.password); 
}, 
'Submit form': function (client) { 
console.log('previous step is done executing'); 
var data = client.globals; 
client 
.click('input[type=submit]') 
.assert.title('Welcome!') 
.end(); 
}, 
}; 
login.js
[Login] Test Suite 
=================== 
Running: Fill out form 
✔ Testing if the page title equals "Awesome App". 
OK. 1 assertions passed. (1.567s) 
Running: Submit form 
✔ Testing if the page title equals "Welcome!". 
OK. 1 assertions passed. (204ms)
Terminology 
Login Test suite 
Fill out form Test 
Submit form Test
Assert vs. Verify 
assert.title('Awesome App') If false, log failure 
and stop running current 
test suite 
verify.title('Awesome App') If false, log failure 
and continue running 
current test suite
Debugging tips 
pause() Pause test execution, leaving 
browser window open. 
client 
.url('http://localhost:8000') 
.assert.title('Awesome App') 
.setValue('input[name=username]', 'seth') 
.setValue('input[name=password]', 'html5dev') 
.pause() 
.click('input[type=submit]')
Debugging tips 
debugger; Insert breakpoint (in node.js code) 
> node debug `which nightwatch` 
-c ./Nightwatch.js --env default 
Commands: run (r), cont (c), next (n), step (s), out (o), backtrace (bt), 
setBreakpoint (sb), clearBreakpoint (cb), watch, unwatch, watchers, 
repl, restart, kill, list, scripts, breakOnException, breakpoints, version 
learn more: nodejs.org/api/debugger.html
Commands 
clearValue 
click 
deleteCookie 
deleteCookies 
end 
getAttribute 
getCookie 
getCookies 
getCssProperty 
getElementSize 
getLocation 
learn more: nightwatchjs.org/api 
getLocationInView 
getTagName 
getText 
getTitle 
getValue 
init 
injectScript 
isVisible 
maximizeWindow 
moveToElement 
pause 
resizeWindow 
saveScreenshot 
setCookie 
setValue 
submitForm 
switchWindow 
urlHash 
waitForElementNotPresent 
waitForElementNotVisible 
waitForElementPresent 
waitForElementVisible
Assertions 
attributeEquals 
containsText 
cssClassPresent 
cssClassNotPresent 
cssProperty 
elementPresent 
elementNotPresent 
learn more: nightwatchjs.org/api 
hidden 
title 
urlContains 
value 
valueContains 
visible
Using custom commands and assertions 
module.exports = { 
'Load Netflix.com': function (client) { 
client 
.url('http://www.netflix.com') 
.tagCount('a', function (result) { 
console.log( 
'NOTE: there are %s anchor elements on the pagen', 
result.value 
); 
}) 
.assert.tagCountGreaterThan('a', 100) 
.end(); 
} 
}; 
learn more: nightwatchjs.org/guide#custom-commands
Using custom commands and assertions 
module.exports = { 
'Load Netflix.com': function (client) { 
client 
.url('http://www.netflix.com') 
.tagCount('a', function (result) { 
console.log( 
'NOTE: there are %s anchor elements on the pagen', 
result.value 
); 
}) 
.assert.tagCountGreaterThan('a', 100) 
.end(); 
} 
}; 
learn more: nightwatchjs.org/guide#custom-commands
Using custom commands and assertions 
module.exports = { 
'Load Netflix.com': function (client) { 
client 
.url('http://www.netflix.com') 
.tagCount('a', function (result) { 
console.log( 
'NOTE: there are %s anchor elements on the pagen', 
result.value 
); 
}) 
.assert.tagCountGreaterThan('a', 100) 
.end(); 
} 
}; 
learn more: nightwatchjs.org/guide#custom-commands
Extending Nightwatch: custom commands 
// command to return the number of elements in a page 
// which are of a certain tag name 
exports.command = function (tagName, callback) { 
callback = callback || function () {}; 
this.execute(function (tagName) { 
return document.getElementsByTagName(tagName).length; 
}, [tagName], function (result) { 
callback.call(this, result); 
}); 
return this; // allows the command to be chained. 
}; 
learn more: nightwatchjs.org/guide#custom-commands
Extending Nightwatch: custom assertions 
var util = require('util'); 
exports.assertion = function(tagName, minCount, msg) { 
var defaultMessage = 'Testing if there are more than %s <%s> elements on the page'; 
var errorMessage = 'Error executing command'; 
// Set default message 
this.message = msg || util.format(defaultMessage, minCount, tagName); 
// The expected text 
this.expected = function () { 
return 'to find at least ' + (minCount+1) + ' ' + tagName + ' elements on page'; 
}; 
// returning true means assertion passed 
// returning false means assertion failed 
this.pass = function(value) { 
return (value > minCount); 
}; 
// returning true means element could not be found 
this.failure = function (result) { 
var failed = (result === false || (result && result.status === -1)); 
if (failed) { 
this.message = msg || errorMessage; 
} 
return failed; 
}; 
learn more: nightwatchjs.org/guide#custom-assertions 
// passed result of calling this.command() 
this.value = function (result) { 
return result.value;
module.exports = { 
src_folders: ['./tests'], 
output_folder: './results', 
custom_commands_path: './commands', 
custom_assertions_path: './assertions', 
selenium: { 
start_process: true, 
server_path: './selenium-server-standalone-2.38.0.jar', 
log_path: './results', 
host: '127.0.0.1', 
port: 4444 
}, 
test_settings: { 
default: { 
selenium_host: '127.0.0.1', 
selenium_port: 4444, 
Nightwatch.js
more to explore 
before and after test hooks! 
take screenshots! 
use sauce labs to run tests! 
use tags to organize test suites! 
learn more: www.nightwatchjs.org 
create custom commands! 
create custom assertions! 
contribute to nightwatch! 
...and more
Get started 
prerequisite: node.js 
1. Use npm to install nightwatch 
2. Download selenium-server-standalone.jar 
3. Create Nightwatch config file 
4. Create some tests
Closing thoughts 
Nightwatch.js is best selenium testing framework 
available to JavaScript developers 
Good community, actively supported 
Easy to get started, check it out
Resources 
documentation 
http://nightwatchjs.org/guide & http://nightwatchjs.org/api 
sample code 
https://github.com/sethmcl/join-the-dark-side 
nightwatch generator (quick start) 
https://github.com/sethmcl/generator-selenium-nightwatch 
nightwatch page object model 
https://github.com/beatfactor/nightwatch/issues/242

More Related Content

What's hot

Automated Web Testing using JavaScript
Automated Web Testing using JavaScriptAutomated Web Testing using JavaScript
Automated Web Testing using JavaScriptSimon Guest
 
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 2015Codemotion
 
Fullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year laterFullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year laterMek Srunyu Stittri
 
Front-end Automated Testing
Front-end Automated TestingFront-end Automated Testing
Front-end Automated TestingRuben Teijeiro
 
Real World Selenium Testing
Real World Selenium TestingReal World Selenium Testing
Real World Selenium TestingMary Jo Sminkey
 
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 JSMichael Haberman
 
Node.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java sideNode.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java sideMek Srunyu Stittri
 
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)Faichi Solutions
 
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.jsMek Srunyu Stittri
 
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)Cogapp
 
Building testable chrome extensions
Building testable chrome extensionsBuilding testable chrome extensions
Building testable chrome extensionsSeth McLaughlin
 
Automated Smoke Tests with Protractor
Automated Smoke Tests with ProtractorAutomated Smoke Tests with Protractor
Automated Smoke Tests with Protractor🌱 Dale Spoonemore
 
AngularJS and Protractor
AngularJS and ProtractorAngularJS and Protractor
AngularJS and ProtractorFilipe Falcão
 
Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015 Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015 Joe Ferguson
 
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 BeyondAlan Richardson
 
An Introduction to AngularJS End to End Testing using Protractor
An Introduction to AngularJS End to End Testing using ProtractorAn Introduction to AngularJS End to End Testing using Protractor
An Introduction to AngularJS End to End Testing using ProtractorCubet Techno Labs
 
UI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected JourneyUI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected JourneyOren Farhi
 
Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012Hazem Saleh
 
Angular UI Testing with Protractor
Angular UI Testing with ProtractorAngular UI Testing with Protractor
Angular UI Testing with ProtractorAndrew Eisenberg
 

What's hot (20)

Automated Web Testing using JavaScript
Automated Web Testing using JavaScriptAutomated Web Testing using JavaScript
Automated Web Testing using JavaScript
 
Night Watch with QA
Night Watch with QANight Watch with QA
Night Watch with QA
 
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
 
Fullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year laterFullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year later
 
Front-end Automated Testing
Front-end Automated TestingFront-end Automated Testing
Front-end Automated Testing
 
Real World Selenium Testing
Real World Selenium TestingReal World Selenium Testing
Real World Selenium Testing
 
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
 
Node.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java sideNode.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java side
 
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)
 
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
 
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)
 
Building testable chrome extensions
Building testable chrome extensionsBuilding testable chrome extensions
Building testable chrome extensions
 
Automated Smoke Tests with Protractor
Automated Smoke Tests with ProtractorAutomated Smoke Tests with Protractor
Automated Smoke Tests with Protractor
 
AngularJS and Protractor
AngularJS and ProtractorAngularJS and Protractor
AngularJS and Protractor
 
Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015 Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015
 
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
 
An Introduction to AngularJS End to End Testing using Protractor
An Introduction to AngularJS End to End Testing using ProtractorAn Introduction to AngularJS End to End Testing using Protractor
An Introduction to AngularJS End to End Testing using Protractor
 
UI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected JourneyUI Testing Best Practices - An Expected Journey
UI Testing Best Practices - An Expected Journey
 
Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012Efficient JavaScript Unit Testing, May 2012
Efficient JavaScript Unit Testing, May 2012
 
Angular UI Testing with Protractor
Angular UI Testing with ProtractorAngular UI Testing with Protractor
Angular UI Testing with Protractor
 

Viewers also liked

Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)Deutsche Post
 
Automation Testing using Selenium
Automation Testing using SeleniumAutomation Testing using Selenium
Automation Testing using SeleniumNaresh Chintalcheru
 
Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907NodejsFoundation
 
The Number One Mistake Everybody Makes on Twitter
The Number One Mistake Everybody Makes on TwitterThe Number One Mistake Everybody Makes on Twitter
The Number One Mistake Everybody Makes on TwitterGary Vaynerchuk
 
113. ¿Cualquiera puede ser un tester?
113. ¿Cualquiera puede ser un tester?113. ¿Cualquiera puede ser un tester?
113. ¿Cualquiera puede ser un tester?GeneXus
 
Severity и Priority для неначинающих: очевидное и невероятное
Severity и Priority для неначинающих: очевидное и невероятноеSeverity и Priority для неначинающих: очевидное и невероятное
Severity и Priority для неначинающих: очевидное и невероятноеDeutsche Post
 
La Importancia de las Certificaciones en TI
La Importancia de las Certificaciones en TILa Importancia de las Certificaciones en TI
La Importancia de las Certificaciones en TISoftware Guru
 
Usando Netbeans para desarrollos en PHP
Usando Netbeans para desarrollos en PHPUsando Netbeans para desarrollos en PHP
Usando Netbeans para desarrollos en PHPDKR Visión SRL
 
Using chrome developer tools for QA'ing Optimizely
Using chrome developer tools for QA'ing Optimizely Using chrome developer tools for QA'ing Optimizely
Using chrome developer tools for QA'ing Optimizely Optimizely
 
Desarrollo para Android con Groovy
Desarrollo para Android con GroovyDesarrollo para Android con Groovy
Desarrollo para Android con GroovySoftware Guru
 

Viewers also liked (16)

Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)Javascript Test Automation Workshop (21.08.2014)
Javascript Test Automation Workshop (21.08.2014)
 
Automation Testing using Selenium
Automation Testing using SeleniumAutomation Testing using Selenium
Automation Testing using Selenium
 
Selenium ppt
Selenium pptSelenium ppt
Selenium ppt
 
Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907
 
Technical report writing
Technical report writingTechnical report writing
Technical report writing
 
The Number One Mistake Everybody Makes on Twitter
The Number One Mistake Everybody Makes on TwitterThe Number One Mistake Everybody Makes on Twitter
The Number One Mistake Everybody Makes on Twitter
 
113. ¿Cualquiera puede ser un tester?
113. ¿Cualquiera puede ser un tester?113. ¿Cualquiera puede ser un tester?
113. ¿Cualquiera puede ser un tester?
 
Severity и Priority для неначинающих: очевидное и невероятное
Severity и Priority для неначинающих: очевидное и невероятноеSeverity и Priority для неначинающих: очевидное и невероятное
Severity и Priority для неначинающих: очевидное и невероятное
 
Selenium Primer
Selenium PrimerSelenium Primer
Selenium Primer
 
La Importancia de las Certificaciones en TI
La Importancia de las Certificaciones en TILa Importancia de las Certificaciones en TI
La Importancia de las Certificaciones en TI
 
Capacitacitación Tester - QA 4
Capacitacitación Tester - QA 4Capacitacitación Tester - QA 4
Capacitacitación Tester - QA 4
 
Agile webinar pack (2)
Agile webinar pack (2)Agile webinar pack (2)
Agile webinar pack (2)
 
Usando Netbeans para desarrollos en PHP
Usando Netbeans para desarrollos en PHPUsando Netbeans para desarrollos en PHP
Usando Netbeans para desarrollos en PHP
 
Using chrome developer tools for QA'ing Optimizely
Using chrome developer tools for QA'ing Optimizely Using chrome developer tools for QA'ing Optimizely
Using chrome developer tools for QA'ing Optimizely
 
Desarrollo para Android con Groovy
Desarrollo para Android con GroovyDesarrollo para Android con Groovy
Desarrollo para Android con Groovy
 
Webdriver.io
Webdriver.io Webdriver.io
Webdriver.io
 

Similar to Join the darkside: Selenium testing with Nightwatch.js

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.jsVladimir Roudakov
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQMichelangelo van Dam
 
UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013Michelangelo van Dam
 
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST ServicesEWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST ServicesRob Tweed
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Yevgeniy Brikman
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unitsitecrafting
 
Automated javascript unit testing
Automated javascript unit testingAutomated javascript unit testing
Automated javascript unit testingryan_chambers
 
UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013Michelangelo van Dam
 
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...Rob Tweed
 
Workshop: Building Vaadin add-ons
Workshop: Building Vaadin add-onsWorkshop: Building Vaadin add-ons
Workshop: Building Vaadin add-onsSami Ekblad
 
Rapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirageRapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirageKrzysztof Bialek
 
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013Michelangelo van Dam
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress DevelopmentAdam Tomat
 
Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]JavaScript Meetup HCMC
 
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationEWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationRob Tweed
 
Micro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMicro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMichael Dawson
 

Similar to Join the darkside: Selenium testing with Nightwatch.js (20)

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
 
Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
 
UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013
 
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST ServicesEWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unit
 
Automated javascript unit testing
Automated javascript unit testingAutomated javascript unit testing
Automated javascript unit testing
 
UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013
 
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
 
Workshop: Building Vaadin add-ons
Workshop: Building Vaadin add-onsWorkshop: Building Vaadin add-ons
Workshop: Building Vaadin add-ons
 
Testing in JavaScript
Testing in JavaScriptTesting in JavaScript
Testing in JavaScript
 
Rapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirageRapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirage
 
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
UA testing with Selenium and PHPUnit - TrueNorthPHP 2013
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
 
Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]
 
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationEWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
 
Micro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMicro app-framework - NodeLive Boston
Micro app-framework - NodeLive Boston
 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-framework
 

More from Seth McLaughlin

Chapter 2: What's your type?
Chapter 2: What's your type?Chapter 2: What's your type?
Chapter 2: What's your type?Seth McLaughlin
 
Chapter 1: Communicating with Your Computer
Chapter 1: Communicating with Your ComputerChapter 1: Communicating with Your Computer
Chapter 1: Communicating with Your ComputerSeth McLaughlin
 
JavaScript State of Mind
JavaScript State of MindJavaScript State of Mind
JavaScript State of MindSeth McLaughlin
 
Get Moving! (with HTML5 canvas)
Get Moving! (with HTML5 canvas)Get Moving! (with HTML5 canvas)
Get Moving! (with HTML5 canvas)Seth McLaughlin
 
Introduction to Venus.js
Introduction to Venus.jsIntroduction to Venus.js
Introduction to Venus.jsSeth McLaughlin
 

More from Seth McLaughlin (7)

Chapter 2: What's your type?
Chapter 2: What's your type?Chapter 2: What's your type?
Chapter 2: What's your type?
 
Chapter 1: Communicating with Your Computer
Chapter 1: Communicating with Your ComputerChapter 1: Communicating with Your Computer
Chapter 1: Communicating with Your Computer
 
Are we there yet?
Are we there yet?Are we there yet?
Are we there yet?
 
JavaScript State of Mind
JavaScript State of MindJavaScript State of Mind
JavaScript State of Mind
 
Get Moving! (with HTML5 canvas)
Get Moving! (with HTML5 canvas)Get Moving! (with HTML5 canvas)
Get Moving! (with HTML5 canvas)
 
Hello, Canvas.
Hello, Canvas.Hello, Canvas.
Hello, Canvas.
 
Introduction to Venus.js
Introduction to Venus.jsIntroduction to Venus.js
Introduction to Venus.js
 

Recently uploaded

%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
+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
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
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-...Steffen Staab
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 

Recently uploaded (20)

%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
+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...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
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-...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 

Join the darkside: Selenium testing with Nightwatch.js

  • 1. Join The Darkside Selenium testing with Nightwatch.js presented by seth mclaughlin on 10.21.14
  • 2.
  • 3.
  • 4.
  • 5. Nightwatch.js learn more: www.nightwatchjs.org
  • 6. 1. Project Overview 2. Features 3. Getting Started
  • 7. "End to End" testing 1. Navigate to Login page 2. Locate username form field, type in seth 3. Locate password form field, type in html5dev 4. Locate submit form button and click it 5. Wait for form submission to complete 6. Verify that title of page is now equal to Welcome!
  • 8. Selenium HTTP Test Runner WebDriver Web Browser JAVA JAR Test Script
  • 9. Selenium HTTP Test Runner WebDriver Web Browser JAVA JAR Test Script
  • 10. Selenium HTTP Node.js module Test Script Test Runner WebDriver Web Browser Node.js application JAVA JAR
  • 11. Selenium WebDriver Selenium WebDriver Web HTTP Test Runner Browser JAVA JAR Test Script Selenium Grid Selenium WebDriver Web Browser JAVA JAR Selenium WebDriver Web Browser JAVA JAR Web Browser JAVA JAR
  • 12. Features ★ Good documentation ★ Use CSS or XPATH selectors ★ Test runner can execute sequentially or in parallel ★ Test filtering by file name pattern, folders and tags ★ SauceLabs + BrowserStack support ★ Built in JUnit XML reporting ★ Extension model for custom commands
  • 13. created by Andrei Rusu @beatfactor learn more: www.linkedin.com/in/beatfactor
  • 14. ~9,000 downloads per month ~2,200 stars on github ~150 forks on github ~83% code coverage learn more: www.npmjs.org/package/nightwatch
  • 15. contributors 27 1 1 46 164 primary contributor (Andrei) pending pull requests (from 8/14/14) open issues closed issues learn more: github.com/beatfactor/nightwatch
  • 16.
  • 17. Sample test: Login flow 1. Navigate to Login page 2. Locate username form field, type in seth 3. Locate password form field, type in html5dev 4. Locate submit form button and click it 5. Wait for form submission to complete 6. Verify that title of page is now equal to Welcome!
  • 18. ├── Nightwatch.js └── tests └── login.js
  • 19. ├── Nightwatch.js └── tests └── login.js
  • 20. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 21. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 22. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 23. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 24. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 25. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 26. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 27. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 28. module.exports = { 'Fill out form and login': function (client) { client.url('http://localhost:8000'); client.assert.title('Awesome App'); client.setValue('input[name=username]', 'seth'); client.setValue('input[name=password]', 'html5dev'); client.click('input[type=submit]'); client.assert.title('Welcome!'); client.end(); } }; login.js
  • 29. module.exports = { 'Fill out form and login': function (client) { client.url('http://localhost:8000'); client.assert.title('Awesome App'); client.setValue('input[name=username]', 'seth'); client.setValue('input[name=password]', 'html5dev'); client.click('input[type=submit]'); client.assert.title('Welcome!'); console.log('all done!'); // wrong! client.end(); } }; login.js
  • 30. module.exports = { 'Fill out form and login': function (client) { client.url('http://localhost:8000'); client.assert.title('Awesome App'); client.setValue('input[name=username]', 'seth'); client.setValue('input[name=password]', 'html5dev'); client.click('input[type=submit]'); client.assert.title('Welcome!'); client.perform(function (client, done) { console.log('all done!'); // right! }); client.end(); } }; login.js
  • 31. module.exports = { 'Fill out form and login': function (client) { client.url('http://localhost:8000'); client.assert.title('Awesome App'); client.setValue('input[name=username]', 'seth'); client.setValue('input[name=password]', 'html5dev'); client.click('input[type=submit]'); client.assert.title('Welcome!'); client.perform(function (client, done) { foo.doSomethingAsync().then(done); }); client.end(); } }; login.js
  • 32. ├── Nightwatch.js └── tests └── login.js
  • 33. module.exports = { src_folders: ['./tests'], output_folder: './results', selenium: { start_process: true, server_path: './selenium-server-standalone-2.38.0.jar', log_path: './results', host: '127.0.0.1', port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, Nightwatch.js
  • 34. module.exports = { src_folders: ['./tests'], output_folder: './results', selenium: { start_process: true, server_path: './selenium-server-standalone-2.38.0.jar', log_path: './results', host: '127.0.0.1', port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, Nightwatch.js
  • 35. module.exports = { src_folders: ['./tests'], output_folder: './results', selenium: { start_process: true, server_path: './selenium-server-standalone-2.38.0.jar', log_path: './results', host: '127.0.0.1', port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, Nightwatch.js
  • 36. module.exports = { src_folders: ['./tests'], output_folder: './results', selenium: { start_process: true, server_path: './selenium-server-standalone-2.38.0.jar', log_path: './results', host: '127.0.0.1', port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, Nightwatch.js
  • 37. module.exports = { src_folders: ['./tests'], output_folder: './results', selenium: { start_process: true, server_path: './selenium-server-standalone-2.38.0.jar', log_path: './results', host: '127.0.0.1', port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, Nightwatch.js
  • 38. port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, path: './results/screenshots' }, desiredCapabilities: { browserName: 'firefox', javascriptEnabled: true, acceptSslCerts: true } } } }; Nightwatch.js
  • 39. port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, path: './results/screenshots' }, desiredCapabilities: { browserName: 'firefox', javascriptEnabled: true, acceptSslCerts: true } } } }; Nightwatch.js
  • 40. port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, path: './results/screenshots' }, desiredCapabilities: { browserName: 'firefox', javascriptEnabled: true, acceptSslCerts: true } } } }; Nightwatch.js
  • 41. port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, path: './results/screenshots' }, desiredCapabilities: { browserName: 'firefox', javascriptEnabled: true, acceptSslCerts: true } } } }; Nightwatch.js
  • 42. > nightwatch -c ./Nightwatch.js --env default
  • 43. [Login] Test Suite ================== Running: Fill out form and login ✔ Testing if the page title equals "Awesome App". ✔ Testing if the page title equals "Welcome!". OK. 2 total assertions passed. (2.233s)
  • 44. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 45. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 46. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 47. module.exports = { 'Fill out form and login': function (client) { client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 48. Y U HARDCODE VALUES ???
  • 50. ├── Nightwatch.js ├── data │ ├── dev.js │ └── staging.js └── tests └── login.js
  • 51. module.exports = { username: 'seth', password: 'html5dev', urls: { login: 'http://localhost:8000' } }; data/dev.js
  • 52. test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, screenshots: { enabled: true, path: './results/screenshots' }, desiredCapabilities: { browserName: 'firefox', javascriptEnabled: true, acceptSslCerts: true }, globals: require('./data/dev') } } Nightwatch.js
  • 53. module.exports = { 'Fill out form and login': function (client) { var data = client.globals; client .url(data.urls.login) .assert.title('Awesome App') .setValue('input[name=username]', data.username) .setValue('input[name=password]', data.password) .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 54. module.exports = { 'Fill out form and login': function (client) { var data = client.globals; client .url(data.urls.login) .assert.title('Awesome App') .setValue('input[name=username]', data.username) .setValue('input[name=password]', data.password) .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 55. module.exports = { 'Fill out form and login': function (client) { var data = client.globals; client .url(data.urls.login) .assert.title('Awesome App') .setValue('input[name=username]', data.username) .setValue('input[name=password]', data.password) .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 56. module.exports = { 'Fill out form and login': function (client) { var data = client.globals; client .url(data.urls.login) .assert.title('Awesome App') .setValue('input[name=username]', data.username) .setValue('input[name=password]', data.password) .click('input[type=submit]') .assert.title('Welcome!') .end(); } }; login.js
  • 57. module.exports = { 'Fill out form': function (client) { var data = client.globals; client .url(data.urls.login) .assert.title('Awesome App') .setValue('input[name=username]', data.username) .setValue('input[name=password]', data.password); }, 'Submit form': function (client) { var data = client.globals; client .click('input[type=submit]') .assert.title('Welcome!') .end(); }, }; login.js
  • 58. module.exports = { 'Fill out form': function (client) { var data = client.globals; client .url(data.urls.login) .assert.title('Awesome App') .setValue('input[name=username]', data.username) .setValue('input[name=password]', data.password); }, 'Submit form': function (client) { console.log('previous step is done executing'); var data = client.globals; client .click('input[type=submit]') .assert.title('Welcome!') .end(); }, }; login.js
  • 59. [Login] Test Suite =================== Running: Fill out form ✔ Testing if the page title equals "Awesome App". OK. 1 assertions passed. (1.567s) Running: Submit form ✔ Testing if the page title equals "Welcome!". OK. 1 assertions passed. (204ms)
  • 60. Terminology Login Test suite Fill out form Test Submit form Test
  • 61. Assert vs. Verify assert.title('Awesome App') If false, log failure and stop running current test suite verify.title('Awesome App') If false, log failure and continue running current test suite
  • 62. Debugging tips pause() Pause test execution, leaving browser window open. client .url('http://localhost:8000') .assert.title('Awesome App') .setValue('input[name=username]', 'seth') .setValue('input[name=password]', 'html5dev') .pause() .click('input[type=submit]')
  • 63. Debugging tips debugger; Insert breakpoint (in node.js code) > node debug `which nightwatch` -c ./Nightwatch.js --env default Commands: run (r), cont (c), next (n), step (s), out (o), backtrace (bt), setBreakpoint (sb), clearBreakpoint (cb), watch, unwatch, watchers, repl, restart, kill, list, scripts, breakOnException, breakpoints, version learn more: nodejs.org/api/debugger.html
  • 64. Commands clearValue click deleteCookie deleteCookies end getAttribute getCookie getCookies getCssProperty getElementSize getLocation learn more: nightwatchjs.org/api getLocationInView getTagName getText getTitle getValue init injectScript isVisible maximizeWindow moveToElement pause resizeWindow saveScreenshot setCookie setValue submitForm switchWindow urlHash waitForElementNotPresent waitForElementNotVisible waitForElementPresent waitForElementVisible
  • 65. Assertions attributeEquals containsText cssClassPresent cssClassNotPresent cssProperty elementPresent elementNotPresent learn more: nightwatchjs.org/api hidden title urlContains value valueContains visible
  • 66. Using custom commands and assertions module.exports = { 'Load Netflix.com': function (client) { client .url('http://www.netflix.com') .tagCount('a', function (result) { console.log( 'NOTE: there are %s anchor elements on the pagen', result.value ); }) .assert.tagCountGreaterThan('a', 100) .end(); } }; learn more: nightwatchjs.org/guide#custom-commands
  • 67. Using custom commands and assertions module.exports = { 'Load Netflix.com': function (client) { client .url('http://www.netflix.com') .tagCount('a', function (result) { console.log( 'NOTE: there are %s anchor elements on the pagen', result.value ); }) .assert.tagCountGreaterThan('a', 100) .end(); } }; learn more: nightwatchjs.org/guide#custom-commands
  • 68. Using custom commands and assertions module.exports = { 'Load Netflix.com': function (client) { client .url('http://www.netflix.com') .tagCount('a', function (result) { console.log( 'NOTE: there are %s anchor elements on the pagen', result.value ); }) .assert.tagCountGreaterThan('a', 100) .end(); } }; learn more: nightwatchjs.org/guide#custom-commands
  • 69. Extending Nightwatch: custom commands // command to return the number of elements in a page // which are of a certain tag name exports.command = function (tagName, callback) { callback = callback || function () {}; this.execute(function (tagName) { return document.getElementsByTagName(tagName).length; }, [tagName], function (result) { callback.call(this, result); }); return this; // allows the command to be chained. }; learn more: nightwatchjs.org/guide#custom-commands
  • 70. Extending Nightwatch: custom assertions var util = require('util'); exports.assertion = function(tagName, minCount, msg) { var defaultMessage = 'Testing if there are more than %s <%s> elements on the page'; var errorMessage = 'Error executing command'; // Set default message this.message = msg || util.format(defaultMessage, minCount, tagName); // The expected text this.expected = function () { return 'to find at least ' + (minCount+1) + ' ' + tagName + ' elements on page'; }; // returning true means assertion passed // returning false means assertion failed this.pass = function(value) { return (value > minCount); }; // returning true means element could not be found this.failure = function (result) { var failed = (result === false || (result && result.status === -1)); if (failed) { this.message = msg || errorMessage; } return failed; }; learn more: nightwatchjs.org/guide#custom-assertions // passed result of calling this.command() this.value = function (result) { return result.value;
  • 71. module.exports = { src_folders: ['./tests'], output_folder: './results', custom_commands_path: './commands', custom_assertions_path: './assertions', selenium: { start_process: true, server_path: './selenium-server-standalone-2.38.0.jar', log_path: './results', host: '127.0.0.1', port: 4444 }, test_settings: { default: { selenium_host: '127.0.0.1', selenium_port: 4444, Nightwatch.js
  • 72. more to explore before and after test hooks! take screenshots! use sauce labs to run tests! use tags to organize test suites! learn more: www.nightwatchjs.org create custom commands! create custom assertions! contribute to nightwatch! ...and more
  • 73. Get started prerequisite: node.js 1. Use npm to install nightwatch 2. Download selenium-server-standalone.jar 3. Create Nightwatch config file 4. Create some tests
  • 74.
  • 75. Closing thoughts Nightwatch.js is best selenium testing framework available to JavaScript developers Good community, actively supported Easy to get started, check it out
  • 76. Resources documentation http://nightwatchjs.org/guide & http://nightwatchjs.org/api sample code https://github.com/sethmcl/join-the-dark-side nightwatch generator (quick start) https://github.com/sethmcl/generator-selenium-nightwatch nightwatch page object model https://github.com/beatfactor/nightwatch/issues/242