Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Wird geladen in …3
×

Hier ansehen

1 von 78 Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Anzeige

Ähnlich wie Testing tools (20)

Weitere von Sebastian Springer (19)

Anzeige

Aktuellste (20)

Testing tools

  1. 1. JavaScript- Testwerkzeuge im Überblick
  2. 2. WHO AM I? • Sebastian Springer • aus München • arbeite bei Mayflower • https://github.com/sspringer82 • @basti_springer • Consultant,Trainer,Autor
  3. 3. 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
  4. 4. cucumber.js w.r.wagner / pixelio.de
  5. 5. cucumber.js Behaviour-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.
  6. 6. Ziel Formulierung von Tests in menschlicher Sprache. Eigentlich sollten auch Nicht-Entwickler Tests schreiben können.
  7. 7. Installation npm install -g cucumber
  8. 8. Aufbau Ein Feature besteht aus einem oder mehreren Szenarien. Diese Szenarien setzen sich aus verschiedenen Steps zusammen. Aufbau eines Szenarios: - Given - When - Then Optionale Erweiterung: - And - But
  9. 9. Aufbau Die Dateien werden standardmäßig im aktuellen Verzeichnis in einem Unterverzeichnis features erwartet. Die Dateien enden auf .feature.
  10. 10. addition.feature 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
 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
  11. 11. Ausführung I-vista / pixelio.de
  12. 12. $ 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)
  13. 13. 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(); });
  14. 14. Implementierung Anja Schweppe-Rahe / pixelio.de
  15. 15. 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.
  16. 16. Step-Definitionen module.exports = function () {
 
 var result;
 
 this.Given(/^I have a calculator instance$/, function (callback) {
 calc = new Calculator();
 callback();
 }); };
  17. 17. 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)
  18. 18. Fehlschlag? Alfred Heiler / pixelio.de
  19. 19. 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)
  20. 20. Hooks Werden 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();
 });
 };
  21. 21. Für weitere Informationen: https://github.com/cucumber/cucumber-js https://cucumber.io/docs/reference/javascript
  22. 22. CasperJS https://twitter.com/casperjs_org
  23. 23. CasperJS Tests für Headless-Browser PhantomJS - WebKit SlimerJS - Gecko
  24. 24. Installation npm install -g casperjs
  25. 25. Engines Standardmäßig wird PhantomJS verwendet. Mit der Option --engine=slimerjs kann SlimerJS verwendet werden.
  26. 26. Aufbau var casper = require('casper').create();
 
 casper.start('http://google.de', function () {
 this.echo(this.getTitle());
 });
 
 casper.run();
  27. 27. Ausführung $ casperjs index.test.js Google
  28. 28. Navigation var casper = require('casper').create();
 
 casper.start();
 
 //casper.open('http://google.de');
 casper.open('http://google.de', {
 method: 'get',
 data: {}
 });
 
 casper.then(function () {
 
 });
 
 
 casper.run();
  29. 29. Eingaben casper.then(function () {
 this.fill('#myForm', {
 name: 'Klaus',
 age: 42
 }, true);
 }); Formular wählen Daten eingeben Abschicken
  30. 30. Clicks casper.then(function () {
 this.click('div.result button.show');
 });
  31. 31. Evaluate casper.thenEvaluate(function (searchTerm) {
 document.querySelector('input[name="q"]').setAttribute('value', searchTerm);
 document.querySelector('form[name="f"]').submit();
 console.log('foo');
 }, 'Hello Kitty');
  32. 32. Screenshots var casper = require('casper').create();
 
 casper.start('http://google.de');
 
 casper.then(function() {
 this.captureSelector('google.png', 'body');
 }); 
 casper.run();
  33. 33. Test Rike / pixelio.de
  34. 34. Test function Calculator() {}
 
 Calculator.prototype.add = function (a, b) {
 return a + b;
 };
  35. 35. 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();
 });
  36. 36. 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.
  37. 37. Test casper.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();
 })
 });
  38. 38. 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.
  39. 39. CasperJS CasperJS hat eine sehr umfangreiche API. Allerdings auch eine gute Dokumentation mit vielen Beispielen dazu. http://docs.casperjs.org/
  40. 40. Protractor/Selenium
  41. 41. Protractor/Selenium End2End Tests für AngularJS. Protractor baut auf Selenium WebDriver auf. Kann verschiedene Browser steuern.
  42. 42. Protractor/Selenium $ npm install -g protractor $ webdriver-manager update $ webdriver-manager start
  43. 43. Protractor/Selenium describe('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);
 });
 });
  44. 44. Jasmine
  45. 45. 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, …
  46. 46. Installation http://jasmine.github.io/
  47. 47. 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);
 });
 });
  48. 48. Matcher Matcher 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
  49. 49. 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);
 });
 });
  50. 50. Async? Erich Westendarp / pixelio.de
  51. 51. Karma Das 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
  52. 52. Infrastruktur Sources Client Server Config BrowserSlaves
  53. 53. Installation http://karma-runner.github.io/ $ npm install karma --save-dev $ npm install karma-jasmine karma-chrome- launcher --save-dev $ npm install -g karma-cli
  54. 54. 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".
  55. 55. Sinon.js
  56. 56. Sinon.js Hilfsbibliothek für Tests mit Unterstützung für Test Doubles.
  57. 57. Test Doubles Regina Kaute / pixelio.de
  58. 58. Spy Gabi Eder / pixelio.de
  59. 59. 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.
  60. 60. Spy it("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();
 });
  61. 61. Stub Bernd Kasper / pixelio.de
  62. 62. 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.
  63. 63. Stub it('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');
 });
  64. 64. Mock Andreas Morlok / pixelio.de
  65. 65. 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.
  66. 66. Mock it ('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();
 });
  67. 67. Timers Tim Reckmann / pixelio.de
  68. 68. Timers Die Zeit im Browser ist nicht vertrauenswürdig. Fake Timers für eine stabile Testumgebung. Bieten Kontrolle über Datum und Zeit.
  69. 69. Timers
  70. 70. Server cre8tive / pixelio.de
  71. 71. Server Wrapper um XMLHttpRequest bzw. ActiveXObject. Tests werden unabhängig von einer Server-Infrastruktur ausgeführt. Kontrolle über die Antworten des Fake Servers.
  72. 72. Server
  73. 73. Fixtures Harald Wanetschka / pixelio.de
  74. 74. 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.
  75. 75. 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);
 });
  76. 76. Fragen? Rainer Sturm / pixelio.de
  77. 77. KONTAKT Sebastian Springer sebastian.springer@mayflower.de Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland @basti_springer https://github.com/sspringer82

×