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
73
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
220
Over Mt. Stupid to Deep Learning
casarock
0
320
Mixed Realities for Web
casarock
0
220
Everything Web! And why OPEN matters
casarock
0
12
Mixed Realities in your browsers - BEDCon 2018
casarock
0
70
Mixed Realities in your browsers
casarock
1
460
WebVR - Virtual Reality in your browsers
casarock
0
110
Everything web and why open matters
casarock
0
210
WebVR - Virtual Realities in your Browsers
casarock
0
110
Other Decks in Technology
See All in Technology
開発生産性向上! 育成を「改善」と捉えるエンジニア育成戦略
shoota
2
460
AWS環境におけるランサムウェア攻撃対策の設計
nrinetcom
PRO
0
170
効率的な技術組織が作れる!書籍『チームトポロジー』要点まとめ
iwamot
1
110
怖くない!ゼロから始めるPHPソースコードコンパイル入門
colopl
0
160
ゼロから創る横断SREチーム 挑戦と進化の軌跡
rvirus0817
3
280
サイボウズフロントエンドエキスパートチームについて / FrontendExpert Team
cybozuinsideout
PRO
5
38k
Opcodeを読んでいたら何故かphp-srcを読んでいた話
murashotaro
0
320
PHP ユーザのための OpenTelemetry 入門 / phpcon2024-opentelemetry
shin1x1
3
1.4k
組み込みアプリパフォーマンス格闘記 検索画面編
wataruhigasi
1
140
React Routerで実現する型安全なSPAルーティング
sansantech
PRO
2
280
多領域インシデントマネジメントへの挑戦:ハードウェアとソフトウェアの融合が生む課題/Challenge to multidisciplinary incident management: Issues created by the fusion of hardware and software
bitkey
PRO
2
120
小学3年生夏休みの自由研究「夏休みに Copilot で遊んでみた」
taichinakamura
0
180
Featured
See All Featured
Bash Introduction
62gerente
609
210k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
111
49k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
169
50k
Building Adaptive Systems
keathley
38
2.3k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
910
It's Worth the Effort
3n
183
28k
KATA
mclloyd
29
14k
Done Done
chrislema
182
16k
Making Projects Easy
brettharned
116
6k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.1k
How to Ace a Technical Interview
jacobian
276
23k
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 (◡‿◡✿)