of 78 /78
JavaScript- Testwerkzeuge im Überblick

Testing tools

Embed Size (px)

Text of Testing tools

Page 1: Testing tools

JavaScript-Testwerkzeuge im

Überblick

Page 2: Testing tools

WHO AM I?

• Sebastian Springer

• aus München

• arbeite bei Mayflower

• https://github.com/sspringer82

• @basti_springer

• Consultant, Trainer, Autor

Page 3: Testing tools
Page 4: Testing tools

Was erwartet euch heute?

BDD Tests mit CucumberJS End2End Tests mit CasperJS

Unittesting mit Jasmine ein paar Tools

und hoffentlich viele Antworten auf eure Fragen

Page 5: Testing tools

cucumber.js

w.r.wagner / pixelio.de

Page 6: Testing tools

cucumber.jsBehaviour-Driven Development (BDD) für JavaScript.

Basiert auf Node.js

Port von Cucumber auf JavaScript.

Tests werden in der DSL Gherkin geschrieben und auf der Kommandozeile ausgeführt.

Getestet mit Node, Firefox, Chrome, Opera, Safari.

Page 7: Testing tools

Ziel

Formulierung von Tests in menschlicher Sprache. Eigentlich sollten auch Nicht-Entwickler Tests schreiben können.

Page 8: Testing tools

Installation

npm install -g cucumber

Page 9: Testing tools

Aufbau

Ein Feature besteht aus einem oder mehreren Szenarien. Diese Szenarien setzen sich aus verschiedenen Steps

zusammen.

Aufbau eines Szenarios: - Given- When- ThenOptionale Erweiterung: - And - But

Page 10: Testing tools

Aufbau

Die Dateien werden standardmäßig im aktuellen Verzeichnis in einem Unterverzeichnis features erwartet.

Die Dateien enden auf .feature.

Page 11: Testing tools

addition.featureFeature: Calculator can add two numbers As a user of a calculator I want to add two numbers So I get the result and don't have to calculate it by myself Scenario: Add 1 and 1 Given I have a calculator instance When I add 1 and 1 Then the result is 2 Scenario: Add 1 and "Hello" Given I have a calculator instance When I add 1 and "Hello" Then an exception will be thrown

Page 12: Testing tools

Ausführung

I-vista / pixelio.de

Page 13: Testing tools

$ cucumber-js

Feature: Calculator can add two numbers As a user of a calculator I want to add two numbers So I get the result and don't have to calculate it by myself

Scenario: Add 1 and 1 # features/addition.feature:6 Given I have a calculator instance # features/addition.feature:7 When I add 1 and 1 # features/addition.feature:8 Then the result is 2 # features/addition.feature:9

Scenario: Add 1 and "Hello" # features/addition.feature:11 Given I have a calculator instance # features/addition.feature:12 When I add 1 and "Hello" # features/addition.feature:13 Then an exception will be thrown # features/addition.feature:14

2 scenarios (2 undefined) 6 steps (6 undefined)

Page 14: Testing tools

You can implement step definitions for undefined steps with these snippets:

this.Given(/^I have a calculator instance$/, function (callback) { // Write code here that turns the phrase above into concrete actions callback.pending(); });

Page 15: Testing tools

Implementierung

Anja Schweppe-Rahe / pixelio.de

Page 16: Testing tools

Step-Definitionen

Hier verlassen wir die schöne Welt der verständlichen Sprache und wenden uns wieder der Programmierung zu.

Die Step-Definitionen liegen im features-Verzeichnis in einem eigenen Ordner mit dem Namen step_definitions.

Die Step-Definitionen werden als Node.js-Module erstellt. Es kann auf den kompletten Funktionsumfang von Node.js

zurückgegriffen werden.

Page 17: Testing tools

Step-Definitionen

module.exports = function () { var result; this.Given(/^I have a calculator instance$/, function (callback) { calc = new Calculator(); callback(); }); };

Page 18: Testing tools

Ausführung$ cucumber-js

Feature: Calculator can add two numbers As a user of a calculator I want to add two numbers So I get the result and don't have to calculate it by myself

Scenario: Add 1 and 1 # features/addition.feature:6 Given I have a calculator instance # features/addition.feature:7 When I add 1 and 1 # features/addition.feature:8 Then the result is 2 # features/addition.feature:9

Scenario: Add 1 and "Hello" # features/addition.feature:11 Given I have a calculator instance # features/addition.feature:12 When I add 1 and Hello # features/addition.feature:13 Then an exception will be thrown # features/addition.feature:14

2 scenarios (2 passed) 6 steps (6 passed)

Page 19: Testing tools

Fehlschlag?

Alfred Heiler / pixelio.de

Page 20: Testing tools

Fehlschlag$ cucumber-js

Feature: Calculator can add two numbers As a user of a calculator I want to add two numbers So I get the result and don't have to calculate it by myself

Scenario: Add 1 and 1 # features/addition.feature:6 Given I have a calculator instance # features/addition.feature:7 When I add 1 and 1 # features/addition.feature:8 Then the result is 2 # features/addition.feature:9 AssertionError: result should be 4 at World.<anonymous> (/Use…

Failing scenarios: /Use…ator/features/addition.feature:6 # Scenario: Add 1 and 1

2 scenarios (1 failed, 1 passed) 6 steps (1 failed, 5 passed)

Page 21: Testing tools

HooksWerden verwendet um die Umgebung vorzubereiten oder

aufzuräumen.

Empfehlung: unter features/support/hooks.js ablegen.module.exports = function () { this.Before(function (callback) { // before each test callback(); });};module.exports = function () { this.After(function (callback) { // after each scenario callback(); });};

Page 22: Testing tools

Für weitere Informationen:

https://github.com/cucumber/cucumber-js

https://cucumber.io/docs/reference/javascript

Page 23: Testing tools

CasperJS

https://twitter.com/casperjs_org

Page 24: Testing tools

CasperJS

Tests für Headless-Browser

PhantomJS - WebKit SlimerJS - Gecko

Page 25: Testing tools

Installation

npm install -g casperjs

Page 26: Testing tools

Engines

Standardmäßig wird PhantomJS verwendet. Mit der Option --engine=slimerjs kann SlimerJS verwendet werden.

Page 27: Testing tools

Aufbau

var casper = require('casper').create();casper.start('http://google.de', function () { this.echo(this.getTitle());});casper.run();

Page 28: Testing tools

Ausführung

$ casperjs index.test.js Google

Page 29: Testing tools

Navigationvar casper = require('casper').create();casper.start();//casper.open('http://google.de');casper.open('http://google.de', { method: 'get', data: {}});casper.then(function () { });casper.run();

Page 30: Testing tools

Eingaben

casper.then(function () { this.fill('#myForm', { name: 'Klaus', age: 42 }, true);});

Formular wählenDaten eingeben

Abschicken

Page 31: Testing tools

Clicks

casper.then(function () { this.click('div.result button.show'); });

Page 32: Testing tools

Evaluate

casper.thenEvaluate(function (searchTerm) { document.querySelector('input[name="q"]').setAttribute('value', searchTerm); document.querySelector('form[name="f"]').submit(); console.log('foo');}, 'Hello Kitty');

Page 33: Testing tools

Screenshots

var casper = require('casper').create();casper.start('http://google.de');casper.then(function() { this.captureSelector('google.png', 'body'); }); casper.run();

Page 34: Testing tools

Test

Rike / pixelio.de

Page 35: Testing tools

Test

function Calculator() {}Calculator.prototype.add = function (a, b) { return a + b;};

Page 36: Testing tools

Test

casper.test.begin('add 1 and 1', 1, function suite(test) { var calc = new Calculator(); test.assertEquals(calc.add(1, 1), 2); test.done();});

Page 37: Testing tools

Test

$ casperjs test test2.js Test file: test2.js # add 1 and 1 PASS Subject equals the expected value PASS 1 test executed in 0.024s, 1 passed, 0 failed, 0 dubious, 0 skipped.

Page 38: Testing tools

Testcasper.test.begin('Submit Google Form', function suite(test) { casper.start('http://www.google.de', function () { test.assertExists('input[name="q"]'); this.fill('form', { q: 'Hello Kitty' }, true) }); casper.then(function () { test.assertTextExists('Hello Kitty – Wikipedia', 'there is a wiki entry'); }); casper.run(function () { test.done(); })});

Page 39: Testing tools

Test

$ casperjs test test3.js Test file: test3.js # Submit Google Form PASS Find an element matching: input[name="q"] PASS there is a wiki entry PASS 2 tests executed in 1.852s, 2 passed, 0 failed, 0 dubious, 0 skipped.

Page 40: Testing tools

CasperJS

CasperJS hat eine sehr umfangreiche API. Allerdings auch eine gute Dokumentation mit vielen Beispielen dazu.

http://docs.casperjs.org/

Page 41: Testing tools

Protractor/Selenium

Page 42: Testing tools

Protractor/Selenium

End2End Tests für AngularJS. Protractor baut auf Selenium WebDriver auf. Kann verschiedene Browser steuern.

Page 43: Testing tools

Protractor/Selenium

$ npm install -g protractor

$ webdriver-manager update

$ webdriver-manager start

Page 44: Testing tools

Protractor/Seleniumdescribe('angularjs homepage todo list', function() { it('should add a todo', function() { browser.get('https://angularjs.org'); element(by.model('todoList.todoText')).sendKeys('write 1 protractor test'); element(by.css('[value="add"]')).click(); var todoList = element.all(by.repeater('todo in todoList.todos')); expect(todoList.count()).toEqual(3); expect(todoList.get(2).getText()).toEqual('write first protractor test'); // You wrote your first test, cross it off the list todoList.get(2).element(by.css('input')).click(); var completedAmount = element.all(by.css('.done-true')); expect(completedAmount.count()).toEqual(2); });});

Page 45: Testing tools

Jasmine

Page 46: Testing tools

Jasmine

BDD-Framework zur Erstellung von Unittests für Applikationen.

Sehr weit verbreitet und gute Community-Unterstützung.

Unabhängig von Frameworks.

Alternativen: Mocha, QUnit, …

Page 47: Testing tools

Installation

http://jasmine.github.io/

Page 48: Testing tools

Ein erster Test

describe('Calculator', function () { it('should add 1 and 1 and return 2', function () { var calc = new Calculator(); var result = calc.add(1, 1); expect(result).toBe(2); });});

Page 49: Testing tools

MatcherMatcher Bedeutung

toBe Typsichere Prüfung auf Gleichheit

toEqual Erweiterte Prüfung auf Gelichheit anhand einer internenFunktion

toMatch Prüfung gegen einen regulären Ausdruck

toBeDefined Prüft, ob ein Ausdruck definiert ist

toBeTruthy Prüft, ob ein Ausdruck wahr ist, nicht typsicher

toBeFalsy Prüft, ob ein Ausdruck falsch ist, nicht typsicher

Page 50: Testing tools

Hooks

describe('Calculator', function () { var calc; beforeEach(function () { calc = new Calculator(); }); afterEach(function () { calc = null; }); it('should add 1 and 1 and return 2', function () { var result = calc.add(1, 1); expect(result).toBe(2); });});

Page 51: Testing tools

Async?

Erich Westendarp / pixelio.de

Page 52: Testing tools

KarmaDas Standalone-Release von Jasmine ist für den täglichen

Gebrauch nicht geeignet. Ein Entwickler muss ständig zwischen IDE und Browser hin und her wechseln.

Besser: Infrastruktur und Einbettung in die Entwicklungsumgebung

Page 53: Testing tools

Infrastruktur

Sources Client Server

Config

Brow

ser S

lave

s

Page 54: Testing tools

Installationhttp://karma-runner.github.io/

$ npm install karma --save-dev $ npm install karma-jasmine karma-chrome-launcher --save-dev $ npm install -g karma-cli

Page 55: Testing tools

Initialisierung$ karma init

Which testing framework do you want to use ? Press tab to list possible options. Enter to move to the next question. > jasmine

Do you want to use Require.js ? This will add Require.js plugin. Press tab to list possible options. Enter to move to the next question. > no

Do you want to capture any browsers automatically ? Press tab to list possible options. Enter empty string to move to the next question. > Chrome >

What is the location of your source and test files ? You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js". Enter empty string to move to the next question. >

Should any of the files included by the previous patterns be excluded ? You can use glob patterns, eg. "**/*.swp". Enter empty string to move to the next question. >

Do you want Karma to watch all the files and run the tests on change ? Press tab to list possible options. > yes

Config file generated at "/Users/sspringer/srv/conf/2015/enterjs/karma/karma.conf.js".

Page 56: Testing tools

Sinon.js

Page 57: Testing tools

Sinon.js

Hilfsbibliothek für Tests mit Unterstützung für Test Doubles.

Page 58: Testing tools

Test Doubles

Regina Kaute / pixelio.de

Page 59: Testing tools

Spy

Gabi Eder / pixelio.de

Page 60: Testing tools

Spy

Wrapper um eine Funktion. Aufrufe werden direkt an die ursprüngliche Funktion weitergeleitet. Aufrufe werden

aufgezeichnet. Spy-Objekt kann später abgefragt werden. Spys sollten später zurückgesetzt werden.

Page 61: Testing tools

Spyit("should create a spy for a method", function () { var myObj = { name: 'Klaus', getName: function () { return this.name; } }; var spy = sinon.spy(myObj, 'getName'); myObj.getName(); expect(spy.calledOnce).toBeTruthy(); myObj.getName.restore();});

Page 62: Testing tools

Stub

Bernd Kasper / pixelio.de

Page 63: Testing tools

Stub

Wrapper um eine Funktion wie Spys. Weisen ein definiertes Verhalten auf. Leiten den Aufruf nicht direkt an die

ursprüngliche Funktion weiter. Reduzieren Abhängigkeiten und vereinfachen

Testumgebungen.

Page 64: Testing tools

Stubit('should return and throw', function () { var myObj = { getName: function () {}, setName: function () {} } var stub1 = sinon.stub(myObj, 'getName').returns('Klaus'); var stub2 = sinon.stub(myObj, ‘setName').throws( new Error(‘BOOH!’) ); expect(stub1()).toBe('Klaus'); });

Page 65: Testing tools

Mock

Andreas Morlok / pixelio.de

Page 66: Testing tools

Mock

Ebenfalls Wrapper um eine Funktion. Dienen dazu, die korrekte Verwendung einer Funktion sicherzustellen. Wird die Funktion nicht korrekt verwendet, wird eine Exception

geworfen.

Best Practice: Nicht mehr als ein Mock pro Test.

Page 67: Testing tools

Mockit ('should work with mocks', function () { var myObj = { name: 'Klaus', getName: function () { return this.name; } } var mock = sinon.mock(myObj); mock.expects('getName').once(); myObj.getName(); myObj.getName(); mock.verify();});

Page 68: Testing tools

Timers

Tim Reckmann / pixelio.de

Page 69: Testing tools

Timers

Die Zeit im Browser ist nicht vertrauenswürdig. Fake Timers für eine stabile Testumgebung.

Bieten Kontrolle über Datum und Zeit.

Page 70: Testing tools

Timers

Page 71: Testing tools

Server

cre8tive / pixelio.de

Page 72: Testing tools

Server

Wrapper um XMLHttpRequest bzw. ActiveXObject. Tests werden unabhängig von einer Server-Infrastruktur ausgeführt.

Kontrolle über die Antworten des Fake Servers.

Page 73: Testing tools

Server

Page 74: Testing tools

Fixtures

Harald Wanetschka / pixelio.de

Page 75: Testing tools

Fixtures

HTML-Struktur, die für die Tests benötigt wird. Unabhängigkeit der Tests soll verbessert werden. Durch

vorbereitete Strukturen können Ausschnitte von Workflows getestet werden.

Auslieferung von HTML über den html2js preprocessor von Karma.

jasmine-jquery als Helper für den Umgang mit Fixtures.

Page 76: Testing tools

Fixtures

beforeEach(function () { $('body').append(window.__html__['fixtures/fx.html']); $('#registerForm').on('submit', validate);});

it ("should show four messages", function () { $('#firstname').val('Klaus'); $('#registerForm').submit(); expect($('.message.visible').length).toBe(4); });

Page 77: Testing tools

Fragen?

Rainer Sturm / pixelio.de

Page 78: Testing tools

KONTAKT

Sebastian Springer [email protected]

Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland

@basti_springer

https://github.com/sspringer82