F09: Testing!
End-to-end & Node (Angular senere)
What, why?
- Core-funksjonalitet er i grunnen ferdig
- Stabilitet!
- Burde ha testet fra begynnelsen av – no time!
Tre typer tester
- End-to-end testing
- "Unit" testing (Node)
- Unit testing (Angular)
Sidenotat: dev dependencies
- Egen blokk til bare development
- Gulp med dependencies
- Code coverage
- Testing framework
- Store binærfiler (Protractor)
- ...
- Installeres per default
- $ npm install --production
{
"name": "first-end-to-end-project",
"dependencies": {
"express": "^4.12.3"
},
"devDependencies": {
"chai": "^2.2.0",
"mocha": "^2.2.4",
"protractor": "^2.0.0"
}
}End-to-end testing (e2e)
- Tester hele applikasjonen, fra UI til DB
- Automatisert klikking i interfacet (nettsida)
- Automatiserer workflows
- "user signs up for an account"
- "user looks at her previously saved items"
- Tregt som fy, men veldig effektivt til å fange bugs
Toolchain
- Test runner: Protractor
- Test framework: Mocha
- Assertion framework: Chai
-
Browser
- Execution: Selenium
- Verification: WebDriver
Protractor
- Test runner for Angular
- Node.js-applikasjon
- Kan require-e ting!
- Kan require-e ting!
- Designet for (men ikke begrenset til) Angular
- Bruker WebDriver og Selenium for å kjøre en browser
- $ npm install --save-dev protractor
Protractor config
Automatisert oppsett av WebDriver med Selenium
$ ./node_modules/.bin/webdriver-manager update
Updating selenium standalone
downloading https://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar...
Updating chromedriver
downloading https://chromedriver.storage.googleapis.com/2.14/chromedriver_mac32.zip...
chromedriver_2.14.zip downloaded to /the-project/node_modules/protractor/selenium/chromedriver_2.14.zip
selenium-server-standalone-2.45.0.jar downloaded to \
/the-project/node_modules/protractor/selenium/selenium-server-standalone-2.45.0.jar
Protractor er bare en
test runner
- Testing framework time: Mocha!
Mocha

Flexible testing framework
"Tilsvarer" XUnit (JUnit for Java, NUnit for .NET), XCTest for Swift/Objective-C
Krever litt config (men ikke noe ille)
Basic Protractor-test
Putt alle tester i project-root/test (konvensjon)
Lag et directory for hver type test

Første test
describe('making a post', function() {
it('logs in and creates a new item', function() {
// go to homepage
// click 'login'
// fill out and submit login form
// submit a new item on the home page
// The new item should be visible as the first item on the page
});
});test/e2e/making-an-item.spec.js
- Protractor beskriver user stories
- E-commerce:
- Enter site,
- find a product,
- add it to cart,
- complete order
Ting å legge merke til
- Sørger for at applikasjonen er stabil fra brukers perspektiv
- Fanger bugs som direkte bruker direkte
- e2e-testing er tregt
- Kan ta lang tid å skrive testene
- For spesifikke tester må endres ofte hvis spec endres (tar lang tid)
- Final assertion: hva skal egentlig testes?
- Resonner baklengs
Navngiving
- Vi definerer selv hvilke filer som er tester (protractor.conf.js)
- Kommer til å kalle testene *.spec.js
- Gjør det mulig å ha utility-filer (*.js) blant testene
Protractor-config
- project-root/protractor.conf.js
exports.config = {
framework: 'mocha',
specs: [
'test/e2e/**/*.spec.js'
]
};Bruk Mocha & kjør tester med navn *.spec.js
(husk $ npm install --save-dev mocha)
En faktisk test
describe('making a post', function() {
it('logs in and creates a new post', function() {
// go to homepage
browser.get('http://localhost:3000');
// click 'login'
// fill out and submit login form
// submit a new post on the posts page
// The new post should be visible as the first post on the page
});
});Kjør Protractor igjen
$ ./node_modules/.bin/protractor
Starting selenium standalone server...
[launcher] Running 1 instances of WebDriver
Selenium standalone server started at http://10.21.24.161:63592/wd/hub
Listening on port 3001
making a post logs in and creates a new post: Connected to MongoDB!
․ making a post logs in and creates a new post: 1289ms
1 passing (1s)
Shutting down selenium standalone server.
[launcher] 0 instance(s) of WebDriver still running
[launcher] chrome #1 passed(Samme kommando som før, uten update)
Siden må være en faktisk Angular-app
Hva hvis serveren er nede?
Start serveren fra Protractor
exports.config = {
framework: 'mocha',
specs: [
'test/e2e/**/*.spec.js'
],
onPrepare: function() {
require('./server-node/hello-tests-server.js');
}
};Hva hvis den allerede kjører?
Start server på annen port


project root/protractor.conf.js
project root/server-node/the-server.js

project root/test/e2e/the-test.js
Protractor Locators
// find an element using css selector
by.css('.someclass');
// find an element using id
by.id('someid');
// find an element by ng-model (e.g. username)
by.model('username');
// find an element by binding (e.g., {{currentUser}})
by.binding('currentUser');
// find an element by repeater (e.g., item in items
by.repeater('item in items');Interager med DOM
// click a button or link
element(by.css('.mybutton')).click();
// fill out a text input
element(by.css('.username-input')).sendKeys('theneva');NB: Events er asynkrone
Eksempel: Fyll inn et login form
// fill out and submit login form
var usernameInput = element(by.model('username'));
usernameInput.sendKeys('theneva');
var passwordInput = element(by.model('password'));
passwordInput.sendKeys('1234');
// Click the login button
var loginButton = element(by.css('.button-login'));
loginButton.click();
// save a new item on the home page
var nameInput = element(by.model('newItem.name'));
nameInput.sendKeys('Some random item');
var saveButton = element(by.css('.button-save'));
saveButton.click();
Hent ut første items-element
// the new item should be visible as the first item on the page
element.all(by.repeater('item in items')).then(function(items) {
var firstItem = items[0];
firstItem.element(by.css('.item-name')).getText().then(function(firstItemName) {
console.log(firstItemName);
});
firstItem.element(by.css('.item-author')).getText().then(function(firstItemAuthor) {
console.log(firstItemAuthor);
});
});Assertion time!
... vent, Mocha har ikke assertions?
Assertion lib/framework: Chai
$ npm install --save-dev chai
var expect = require(’chai ’).expect;
...
firstItem.element(by.css(’.item−name’)).getText().then(function(firstItemName) {
expect(firstItemName).to.equal(itemContent);
});
firstItem.element(by.css(’.item−author’)).getText().then(function(firstItemAuthor) {
expect(firstItemAuthor).to.equal(username);
});
Ex: wrong assertion:
Vi messer med databasen?
- Vi jobber mot den faktiske databasen
- Mange måter å håndtere dette
- dev-database med env-variabel (som med port)
- dropp databasen etter hver test (eller når fullført)
- du er uansett i dev-miljø
- Protractor afterEach-filter
- Krever planlegging (og kanskje dokumentasjon)
- dev-database med env-variabel (som med port)
Stacken (igjen)
- Test runner: Protractor -> WebDriver + Selenium
- Test framework: Mocha
- Assertion library/framework: Chai
Avsluttende tanker og pekere
- e2e-testing er (kanskje) den viktigste typen testing
- Tester fra brukers perspektiv
- Fanger bugs som ikke oppdages under utvikling
- Uttrykker requirements (user stories)
- Dokumentasjon? Psh
- Lar applikasjonen holde høy kvalitet
Unit testing

Node "unit" testing
- Ikke egentlig unit testing
- Treffer databasen i stedet for å mocke
- Samme problem som tidligere
- Samme problem som tidligere
- Mulig å skrive ekte unit tests, men...
- Det tar lang tid
- Det er lite fleksibelt
- Hver test er uavhengig
- Rekkefølge har ikke noe å si
- Vet ikke om de andre testene
Unit testing i Node
- Bruker bare Mocha og Chai (ikke Protractor)
- Kjører testene direkte med Mocha
- Nøyaktig samme format som e2e-testene
var expect = require('chai').expect;
var controller = require('../../../server-node/controllers/items');
describe('controllers.items', function() {
it('should exist', function() {
expect(controller).to.exist;
});
});$ mocha test/node/controllers/items.spec.js
test/mocha.opts: finds all tests in test/node recursively
test/node
−−recursiveReporters
- Standard reporter er ofte nok
- Forteller hvilke biter av koden som er testet
- Forteller hvilke biter av koden som er testet
- Mer konsise reporters finnes: $ mocha -R nyan
Test coverage
$npm install --save-dev blanket
Neste gang
$ npm test
Endelig noe annet enn dependencies i package.json!
{
"name": "itemsApp",
"dependencies: "<@\dots@>",
"devDependencies": "<@\dots@>",
"scripts": {
"test: "./node_modules/.bin/mocha && ./node_modules/.bin/protractor"
}
}package.json
$ npm test
PS: Man kan definere andre scripts også!
Øving
- Sett opp (eller bruk) en side med registrering og innlogging
- Les kapittel 10 i boka
- Skriv e2e-tester for både registrering og innlogging
- Skriv e2e-tester for både registrering og innlogging
- Les kapittel 11 i boka
- Organiser controllers i en "Base Router" (pp. 168)
- Skriv Node "unit" tests for Sessions-controlleren
- Les kapittel 10 i boka
PG6300-14-09: Testing
By theneva
PG6300-14-09: Testing
- 668