Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Night Watch with QA
Search
Carsten Sandtner
October 24, 2016
Technology
0
81
Night Watch with QA
My slides for my talk at WebTech Conference in Munich, October 2016.
Carsten Sandtner
October 24, 2016
Tweet
Share
More Decks by Carsten Sandtner
See All by Carsten Sandtner
THE AI THAT WENT OUT TO DESTROY MANKIND
casarock
0
290
Over Mt. Stupid to Deep Learning
casarock
0
410
Mixed Realities for Web
casarock
0
330
Everything Web! And why OPEN matters
casarock
0
12
Mixed Realities in your browsers - BEDCon 2018
casarock
0
100
Mixed Realities in your browsers
casarock
1
550
WebVR - Virtual Reality in your browsers
casarock
0
150
Everything web and why open matters
casarock
0
280
WebVR - Virtual Realities in your Browsers
casarock
0
160
Other Decks in Technology
See All in Technology
AI駆動PjMの理想像 と現在地 -実践例を添えて-
masahiro_okamura
1
110
What happened to RubyGems and what can we learn?
mikemcquaid
0
300
Agile Leadership Summit Keynote 2026
m_seki
1
620
SREチームをどう作り、どう育てるか ― Findy横断SREのマネジメント
rvirus0817
0
250
Bedrock PolicyでAmazon Bedrock Guardrails利用を強制してみた
yuu551
0
230
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.8k
顧客との商談議事録をみんなで読んで顧客解像度を上げよう
shibayu36
0
230
Embedded SREの終わりを設計する 「なんとなく」から計画的な自立支援へ
sansantech
PRO
3
2.4k
2026年、サーバーレスの現在地 -「制約と戦う技術」から「当たり前の実行基盤」へ- /serverless2026
slsops
2
240
We Built for Predictability; The Workloads Didn’t Care
stahnma
0
140
Data Hubグループ 紹介資料
sansan33
PRO
0
2.7k
ブロックテーマでサイトをリニューアルした話 / 2026-01-31 Kansai WordPress Meetup
torounit
0
470
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Crafting Experiences
bethany
1
49
How STYLIGHT went responsive
nonsquared
100
6k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.2k
GraphQLとの向き合い方2022年版
quramy
50
14k
Abbi's Birthday
coloredviolet
1
4.7k
Utilizing Notion as your number one productivity tool
mfonobong
3
220
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
120
SEO for Brand Visibility & Recognition
aleyda
0
4.2k
WENDY [Excerpt]
tessaabrams
9
36k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.1k
Transcript
Night watch …with QA Carsten Sandtner (@casarock) mediaman// Gesellschaft für
Kommunikation mbH
about:me Carsten Sandtner @casarock Head of Software Development //mediaman GmbH
None
Testing
Unit Tests
Integration Tests
System Tests National Museum of American History Smithsonian Institution -
https://flic.kr/p/e6s1Lr
User Acceptance Tests Brett Jordan - https://flic.kr/p/7ZRSzA
UAT System Test Integration Test Unit Test Preliminary design Detailed
design Implementation Requirements
UAT Integration Test Unit Test Detailed design Implementation Requirements System
Test Preliminary design
by 7263255 - https://flic.kr/p/6YgDNN
None
None
Testing pyramid # of Tests easy to automate
Implementation Unit Test TDD
Integration Test Unit Test Detailed design Implementation Unit Test
System Test Integration Test Unit Test Preliminary design Detailed design
Implementation
Automated E2E Test
None
None
None
– http://nightwatchjs.org/ „Nightwatch.js is an easy to use Node.js based
End- to-End (E2E) testing solution for browser based apps and websites. It uses the powerful Selenium WebDriver API to perform commands and assertions on DOM elements.“
Nightwatch & WebDriver
Features • Clean syntax • Build-in test runner • support
for CSS and Xpath Selectors • Grouping and filtering of Tests • Saucelab and Browserstack support • Extendable (Custom Commands) • CI support!
Installation $ npm install [-g] nightwatch … and Download Selenium-Server-Standalone!
Done.
Nightwatch project structure ├──bin/ | ├──chromedriver | └──seleniumdriver.jar | ├──data/
| └──globals.js | ├──reports/ | └──fancyreports.xml | ├──tests/ | ├──meaningfultest1.js | ├──meaningfultest2.js | └── … └──nightwatch.js[on]
Nightwatch.js module.exports = { "src_folders": ["tests"], "output_folder": "reports", "custom_commands_path": "",
"custom_assertions_path": "", "page_objects_path": "./objects/", "globals_path": "", "selenium": { "start_process": true, "server_path": "bin/selenium-server-standalone-2.53.1.jar", "log_path": "", "host": "127.0.0.1", "port": 4444, "cli_args": { "webdriver.chrome.driver": "./bin/chromedriver", "webdriver.ie.driver": "", "webdriver.gecko.driver" : "./bin/geckodriver090" } },
Nightwatch.js - Test setup. "test_settings": { "default": { "launch_url": "http://localhost",
"selenium_port": 4444, "selenium_host": "localhost", "silent": true, "screenshots": { "enabled": false, "path": "" }, "desiredCapabilities": { "browserName": "chrome", "marionette": true } }, “staging“: { . . . },
Nightwatch.js - Browser setup "chrome": { "desiredCapabilities": { "browserName": "chrome",
"javascriptEnabled": true, "acceptSslCerts": true } } } };
Simple Nightwatch test module.exports = { 'Google Webtechcon' : function
(client) { client .url('http://www.google.com') .waitForElementVisible('body', 1000) .assert.title('Google') .assert.visible('input[type=text]') .setValue('input[type=text]', 'webtechcon') .waitForElementVisible('button[name=btnG]', 1000) .click('button[name=btnG]') .pause(1000) .assert.containsText('#rso > div.g > div > div > h3 > a', 'WebTech Conference 2016') .end(); } };
Test execution $ nightwatch [-c nightwatch.js] tests/simplegoogle.js
None
Tests in detail
Arrange and assert module.exports = { 'Google Webtechcon' : function
(client) { client .url('http://www.google.com') .waitForElementVisible('body', 1000) .assert.title('Google') .assert.visible('input[type=text]') .end(); } }; arrange assert
Arrange, action and assert module.exports = { 'Google Webtechcon' :
function (client) { client .url('http://www.google.com') .waitForElementVisible('body', 1000) .assert.title('Google') .assert.visible('input[type=text]') .setValue('input[type=text]', 'webtechcon') .waitForElementVisible('button[name=btnG]', 1000) .click('button[name=btnG]') .pause(1000) .assert.containsText('#rso > div.g > div > div > h3 > a', 'WebTech Conference 2016') .end(); } arrange assert assert action
Hardcoded values?
Hardcoded values module.exports = { 'Google Webtechcon' : function (client)
{ client .url('http://www.google.com') .waitForElementVisible('body', 1000) .assert.title('Google') .assert.visible('input[type=text]') .end(); } };
Using globals module.exports = { 'Google Webtechcon' : function (client)
{ var globals = client.globals; client .url(globals.url) .waitForElementVisible('body', 1000) .assert.title(globals.static.pageTitle) .assert.visible(globals.selectors.searchField) .end(); } };
Define globals module.exports = { url: 'http://www.google.com', selectors: { 'searchField':
'input[type=text]' }, static: { 'pageTitle': 'Google' } } Save as data/google.js
Add to config (test-settings) module.exports = { . . .
"test_settings": { "default": { "launch_url": "http://localhost", "selenium_port": 4444, "selenium_host": "localhost", "silent": true, "screenshots": { "enabled": false, "path": "" }, "desiredCapabilities": { "browserName": "chrome", "marionette": true }, "globals": require('./data/google') }, . . .
None
Use Page Objects!
Using Page Objects module.exports = { 'url': 'http://www.google.com', 'elements': {
'searchField': 'input[type=text]' } }; Save as object/google.js
Add objects to config module.exports = { "src_folders": ["tests"], "output_folder":
"reports", "custom_commands_path": "", "custom_assertions_path": "", "page_objects_path": "./objects/", "globals_path": "", "selenium": {. . .}, "test_settings": {. . .} };
Add objects to config module.exports = { 'Google Webtechcon' :
function (client) { var googlePage = client.page.google(), globals = client.globals; googlePage.navigate() .waitForElementVisible('body', 1000) .assert.title(globals.static.pageTitle) .assert.visible('@searchField') .end(); } };
More PageObjects awesomeness module.exports = { 'url': 'http://www.some.url', 'elements': {
'passwordField': 'input[type=text]', 'usernameField': 'input[type=password]', 'submit': 'input[type=submit]' }, commands: [{ signInAsAdmin: function() { return this.setValue('@usernameField', 'admin') .setValue('@passwordField', 'password') .click('@submit'); } }] };
In your test module.exports = { 'Admin log in' :
function (browser) { var login = browser.page.admin.login(); login.navigate() .signInAsAdmin(); browser.end(); } };
Grouping tests $ nightwatch --group smoketests $ nightwatch --skipgroup smoketests
$ nightwatch --skipgroup login,whatever
Test groups | ├──tests/ | ├──smoketests/ | | ├──meaningfulTest1.js |
| ├──meaningfulTest2.js | | └── …… | └──login/ | ├──authAndLogin.js | └── ……
Tag your tests $ nightwatch --tag login $ nightwatch --tag
login --tag something_else $ nightwatch --skiptags login $ nightwatch --skiptags login,something_else
In your test module.exports = { '@tags': ['login', 'sanity'], 'Admin
log in' : function (browser) { var login = browser.page.admin.login(); login.navigate() .signInAsAdmin(); browser.end(); } };
Demo
Nightwatch is extendable! • Write custom commands • add custom
assertions • write custom reporter
Nightwatch is Javascript! • Using Filereaders • CSV, Excel etc.
• write helpers if needed!
None
Nightwatch @Mediaman
The problem
Before Nightwatch
The solution
UAT System Test Integration Test Unit Test Preliminary design Detailed
design Implementation Requirements ✓ ✓ ✓ ✓ ✓ ✓
Thanks! Carsten Sandtner @casarock
[email protected]
https://github.com/casarock (◡‿◡✿)