SlideShare uma empresa Scribd logo
1 de 53
Testgetriebene Entwicklung
      mit JavaScript
  Tobias Bosch & Stefan Scheidt
   OPITZ CONSULTING GmbH
Wer sind wir?

tobias.bosch@opitz-consulting.com
            (@tigbro)

stefan.scheidt@opitz-consulting.com
          (@stefanscheidt)
Mission                                                        Märkte
Wir entwickeln gemeinsam mit allen                              Branchenübergreifend
Branchen Lösungen, die dazu führen, dass                        Über 600 Kunden
sich diese Organisationen besser entwickeln                                                         29%
als ihr Wettbewerb.                                                              29%
                                                                                                    Handel / Logistik /
                                                                                                    Dienstleistungen
                                                               Industrie / Versorger /
Unsere Dienstleistung erfolgt                                    Telekommunikation
partnerschaftlich und ist auf eine langjährige                                               42%
Zusammenarbeit angelegt.                                                                     Öffentliche Auftraggeber / Banken und
                                                                                             Versicherungen / Vereine und Verbände



Leistungsangebot                                               Eckdaten
 Business IT Alignment                                         Gründung 1990
 Business Information Management                               400 Mitarbeiter
 Business Process Management                                   8 Standorte
 Anwendungsentwicklung
 SOA und System-Integration
 IT-Infrastruktur-Management


                   Testgetriebene Entwicklung mit JavaScript                             © OPITZ CONSULTING GmbH 2011         Seite 3
Wer sind Sie?
In diesem Vortrag geht‘s um ...

  ... automatisiertes Testen
      ... durch Entwickler
Warum testen?
Warum JavaScript-Code testen?
Laufzeitumgebungen für
       JavaScript




                         ...
In diesem Vortrag:




Icon Set by Paul Irish (http://paulirish.com/2010/high-res-browser-icons/)
Unser Beispiel
Tests formulieren
„Klassisch“ mit xUnit-Asserts



   „BDD-Style“ à la RSpec
Demo: BDD mit Jasmine
Hello Jasmine!
describe("parseFloat", function() {

      it("should return undefined for undefined", function () {
          expect(util.parseFloat(undefined)).toBeUndefined();
      });

      it("should return 0 for empty string", function () {
          expect(util.parseFloat('')).toEqual(0);
      });

      it("should return number for number strings", function () {
          expect(util.parseFloat('1.5')).toEqual(1.5);
      });

      // ...

});
Hello Jasmine!
describe("parseFloat", function() {

      it("should return undefined for undefined", function () {
          expect(util.parseFloat(undefined)).toBeUndefined();
      });

      it("should return 0 for empty string", function () {
          expect(util.parseFloat('')).toEqual(0);
      });

      it("should return number for number strings", function () {
          expect(util.parseFloat('1.5')).toEqual(1.5);
      });

      // ...

});
Hello Jasmine!
describe("parseFloat", function() {

      it("should return undefined for undefined", function () {
          expect(util.parseFloat(undefined)).toBeUndefined();
      });

      it("should return 0 for empty string", function () {
          expect(util.parseFloat('')).toEqual(0);
      });

      it("should return number for number strings", function () {
          expect(util.parseFloat('1.5')).toEqual(1.5);
      });

      // ...

});
Hello Jasmine!
describe("parseFloat", function() {

      it("should return undefined for undefined", function () {
          expect(util.parseFloat(undefined)).toBeUndefined();
      });

      it("should return 0 for empty string", function () {
          expect(util.parseFloat('')).toEqual(0);
      });

      it("should return number for number strings", function () {
          expect(util.parseFloat('1.5')).toEqual(1.5);
      });

      // ...

});
Hello Jasmine!

  expect(x).toEqual(y);
    expect(x).toBe(y);
 expect(x).toBeDefined();
expect(x).toBeUndefined();
 expect(x).toBeTruthy();
  expect(x).toBeFalsy();
           ...
Hello Jasmine!
Fortgeschrittene Konzepte
Spies
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        jasmine.Clock.useMock();
        spyOn(util, 'opacity');
        fadein.execute(element);
        jasmine.Clock.tick(1000);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        spyOn(window, 'setTimeout').andCallFake(
            function(callback) {
                callback();
            });
        spyOn(util, 'opacity');
        fadein.execute(element);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        spyOn(window, 'setTimeout').andCallFake(
            function(callback) {
                callback();
            });
        spyOn(util, 'opacity');
        fadein.execute(element);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        spyOn(window, 'setTimeout').andCallFake(
            function(callback) {
                callback();
            });
        spyOn(util, 'opacity');
        fadein.execute(element);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        spyOn(window,set opacity of 'element' to 'opacity'
                  // 'setTimeout').andCallFake(
                  util.opacity = function (element, opacity) {
            function(callback) {
                      ...
                callback();
                  };
            });
        spyOn(util, 'opacity');
        fadein.execute(element);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        spyOn(window, 'setTimeout').andCallFake(
            function(callback) {
                callback();
            });
        spyOn(util, 'opacity');
        fadein.execute(element);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Spies
describe("execute fadein", function() {
    it("should eventually set opacity to 1", function () {
        var element = document.createElement("div");
        spyOn(window,set opacity of 'element' to 'opacity'
                  // 'setTimeout').andCallFake(
            function(callback) = function (element, opacity) {
                  util.opacity {
                      ...
                callback();
            }); };
        spyOn(util, 'opacity');
        fadein.execute(element);
        var mostRecentCall = util.opacity.mostRecentCall;
        expect(mostRecentCall.args[0]).toBe(element);
        expect(mostRecentCall.args[1]).toEqual(1);
    });
});
Funktion                    Der Spy soll ...

spy.andCallThrough()
                            ... die ursprüngliche Funktion
                                aufrufen
                            ... das übergebene Argumente
spy.andReturn(argument)
                                zurückgeben
                            ... die übergebene Exception
spy.andThrow(exception)
                                werfen

spy.andCallFake(function)
                            ... die übergebene Funktion
                                aufrufen

              Funktionen von Spies
Funktion                      Prüft, ob der Spy ...
toHaveBeenCalled()            ... aufrufen wurde
                              ... mit den übergebenen
toHaveBeenCalledWith(args)
                                  Argumenten aufgerufen wurde
                     Matcher für Spies


Funktion                      Bedeutung
spy.callCount                 Anzahl der Aufrufe

spy.argsForCall[i]            Argumente des i-ten Aufrufs

spy.mostRecentCall.args       Argumente des letzten Aufrufs

                Eigenschaften von Spies
Asynchrone Tests
Asynchrone Tests
it("should eventually set opacity to 1", function() {
    var element = document.createElement("div");
    spyOn(util, 'opacity');
    runs(function() {
        fadein.execute(element);
    });
    waitsFor(function () {
        return opacitySpy.mostRecentCall.args[1] === 1;
    });
    runs(function() {
        // some other expectations
        expect(opacitySpy.mostRecentCall.args[1]).toEqual(1);
    });
});
Asynchrone Tests
it("should eventually set opacity to 1", function() {
    var element = document.createElement("div");
    spyOn(util, 'opacity');
    runs(function() {
        fadein.execute(element);
    });
    waitsFor(function () {
        return opacitySpy.mostRecentCall.args[1] === 1;
    });
    runs(function() {
        // some other expectations
        expect(opacitySpy.mostRecentCall.args[1]).toEqual(1);
    });
});
Asynchrone Tests
it("should eventually set opacity to 1", function() {
    var element = document.createElement("div");
    spyOn(util, 'opacity');
    runs(function() {
        fadein.execute(element);
    });
    waitsFor(function () {
        return opacitySpy.mostRecentCall.args[1] === 1;
    });
    runs(function() {
        // some other expectations
        expect(opacitySpy.mostRecentCall.args[1]).toEqual(1);
    });
});
Asynchrone Tests
it("should eventually set opacity to 1", function() {
    var element = document.createElement("div");
    spyOn(util, 'opacity');
    runs(function() {
        fadein.execute(element);
    });
    waitsFor(function () {
        return opacitySpy.mostRecentCall.args[1] === 1;
    });
    runs(function() {
        // some other expectations
                  // set opacity of 'element' to 'opacity'
        expect(opacitySpy.mostRecentCall.args[1]).toEqual(1); {
                  util.opacity = function (element, opacity)
    });               ...
});               };
Asynchrone Tests
it("should eventually set opacity to 1", function() {
    var element = document.createElement("div");
    spyOn(util, 'opacity');
    runs(function() {
        fadein.execute(element);
    });
    waitsFor(function () {
        return opacitySpy.mostRecentCall.args[1] === 1;
    });
    runs(function() {
        // some other expectations
        expect(opacitySpy.mostRecentCall.args[1]).toEqual(1);
    });
});
UI-Tests
describeUi("index", "/js-fadein/index.html", function () {

      it("should fade in hello div on button click", function () {
          var win, field, button;
          runs(function() {
              field = document.getElementById('hello');
              button = document.getElementById('fadein');
              expect(util.opacity(field)).toEqual(0);
              simulate(button, 'click');
          });
          runs(function () {
              expect(util.opacity(field)).toEqual(1);
          });
      });

});

                                               UI-Test mit Jasmine-UI
describeUi("index", "/js-fadein/index.html", function () {

      it("should fade in hello div on button click", function () {
          var win, field, button;
          runs(function() {
              field = document.getElementById('hello');
              button = document.getElementById('fadein');
              expect(util.opacity(field)).toEqual(0);
              simulate(button, 'click');
          });
          runs(function () {
              expect(util.opacity(field)).toEqual(1);
          });
      });

});

                                               UI-Test mit Jasmine-UI
describeUi("index", "/js-fadein/index.html", function () {

      it("should fade in hello div on button click", function () {
          var win, field, button;
          runs(function() {
              field = document.getElementById('hello');
              button = document.getElementById('fadein');
              expect(util.opacity(field)).toEqual(0);
              simulate(button, 'click');
          });
          runs(function () {
              expect(util.opacity(field)).toEqual(1);
          });
      });

});

                                               UI-Test mit Jasmine-UI
describeUi("index", "/js-fadein/index.html", function () {

      it("should fade in hello div on button click", function () {
          var win, field, button;
          runs(function() {
              field = document.getElementById('hello');
              button = document.getElementById('fadein');
              expect(util.opacity(field)).toEqual(0);
              simulate(button, 'click');
          });
          runs(function () {
              expect(util.opacity(field)).toEqual(1);
          });
      });

});

                                               UI-Test mit Jasmine-UI
describeUi("index", "/js-fadein/index.html", function () {

      it("should fade in hello div on button click", function () {
          var win, field, button;
          runs(function() {
              field = document.getElementById('hello');
              button = document.getElementById('fadein');
              expect(util.opacity(field)).toEqual(0);
              simulate(button, 'click');
          });
          runs(function () {
              expect(util.opacity(field)).toEqual(1);
          });
      });

});

                                               UI-Test mit Jasmine-UI
describeUi("index", "/js-fadein/index.html", function () {

      it("should fade in hello div on button click", function () {
          var win, field, button;
          runs(function() {
              field = document.getElementById('hello');
              button = document.getElementById('fadein');
              expect(util.opacity(field)).toEqual(0);
              simulate(button, 'click');
          });
          runs(function () {
              expect(util.opacity(field)).toEqual(1);
          });
      });

});

                                               UI-Test mit Jasmine-UI
Testausführung automatisieren
Pro              Contra          Beispiele
                          - Schwerer zu
   Im       Laufen in                        QUnit
                            automatisieren
Browser   Produktions-                       YUI Test
 testen                   - Schwerer in CI
           umgebung                          Jasmine
                            einzubetten
         - Leicht zu                         Envjs
Headless automatisieren     Browser wird     PhantomJS
Browser - Leicht in CI      nur simuliert    Zombie.js
           einzubetten                       HtmlUnit
Browser fernsteuern
JsTestDriver




http://code.google.com/p/js-test-driver/
Demo: JsTestDriver
Fazit

Es gibt ein umfangreiches Toolset zum Testen
             von JavaScript-Code.

             Testen Sie Ihren Code!
Testen Sie insbesondere Ihren JavaScript-Code!
          Sie haben keine Ausrede ...
Links


Jasmine        http://pivotal.github.com/jasmine/
Jasmine UI     https://github.com/tigbro/jasmine-ui
js-fadein      https://github.com/stefanscheidt/js-fadein
JsTestDriver   http://code.google.com/p/js-test-driver/
saturated writing
    (By Eduordo, http://www.flickr.com/photos/tnarik/366393127/)

                           Smiley Keyboard
   (By ~Prescott, http://www.flickr.com/photos/ppym1/93571524/)

                             Spyhole, Paris
(By smith of smiths, http://www.flickr.com/photos/hesketh/232015302/)

                       Sorta synchronised diving
   (By Aaron Retz, http://www.flickr.com/photos/aretz/309469339/)
Stamp Collector
(By C. Castillo, http://www.flickr.com/photos/carolinedecastillo/2750577684/)

                                bios [bible]
      (By Gastev, http://www.flickr.com/photos/gastev/2174505811/)

                          Day 276/365: in hot pursuit
    (By Tina Vega, http://www.flickr.com/photos/tinavega/3066602429/)
Vielen Dank
für Ihr Interesse!
     @tigbro
  @stefanscheidt

Mais conteúdo relacionado

Mais procurados

Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2André Tapia
 
Curso Symfony - Clase 5
Curso Symfony - Clase 5Curso Symfony - Clase 5
Curso Symfony - Clase 5Javier Eguiluz
 
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorProgramming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorFedor Lavrentyev
 
Jasmine - Sinon - BrazilJS
Jasmine - Sinon - BrazilJSJasmine - Sinon - BrazilJS
Jasmine - Sinon - BrazilJSSergio Azevedo
 

Mais procurados (7)

Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2
 
Java
JavaJava
Java
 
Curso Symfony - Clase 5
Curso Symfony - Clase 5Curso Symfony - Clase 5
Curso Symfony - Clase 5
 
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorProgramming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
 
Programa
ProgramaPrograma
Programa
 
Jasmine - Sinon - BrazilJS
Jasmine - Sinon - BrazilJSJasmine - Sinon - BrazilJS
Jasmine - Sinon - BrazilJS
 
Testování prakticky
Testování praktickyTestování prakticky
Testování prakticky
 

Mais de OPITZ CONSULTING Deutschland

Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"OPITZ CONSULTING Deutschland
 
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der PraxisOC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der PraxisOPITZ CONSULTING Deutschland
 
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und CloudOC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und CloudOPITZ CONSULTING Deutschland
 
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!OPITZ CONSULTING Deutschland
 
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...OPITZ CONSULTING Deutschland
 
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...OPITZ CONSULTING Deutschland
 
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?OPITZ CONSULTING Deutschland
 
OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring OPITZ CONSULTING Deutschland
 
Effiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud NutzungEffiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud NutzungOPITZ CONSULTING Deutschland
 

Mais de OPITZ CONSULTING Deutschland (20)

OC|Webcast: Grundlagen der Oracle Lizenzierung
OC|Webcast: Grundlagen der Oracle LizenzierungOC|Webcast: Grundlagen der Oracle Lizenzierung
OC|Webcast: Grundlagen der Oracle Lizenzierung
 
OC|Webcast "Java heute" vom 28.09.2021
OC|Webcast "Java heute" vom 28.09.2021OC|Webcast "Java heute" vom 28.09.2021
OC|Webcast "Java heute" vom 28.09.2021
 
OC|Webcast "Java heute" vom 24.08.2021
OC|Webcast "Java heute" vom 24.08.2021OC|Webcast "Java heute" vom 24.08.2021
OC|Webcast "Java heute" vom 24.08.2021
 
OC|Webcast "Daten wirklich nutzen"
OC|Webcast "Daten wirklich nutzen"OC|Webcast "Daten wirklich nutzen"
OC|Webcast "Daten wirklich nutzen"
 
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
 
OC|Webcast "Willkommen in der Cloud!"
OC|Webcast "Willkommen in der Cloud!"OC|Webcast "Willkommen in der Cloud!"
OC|Webcast "Willkommen in der Cloud!"
 
OC|Webcast "Die neue Welt der Virtualisierung"
OC|Webcast "Die neue Welt der Virtualisierung"OC|Webcast "Die neue Welt der Virtualisierung"
OC|Webcast "Die neue Welt der Virtualisierung"
 
10 Thesen zur professionellen Softwareentwicklung
10 Thesen zur professionellen Softwareentwicklung10 Thesen zur professionellen Softwareentwicklung
10 Thesen zur professionellen Softwareentwicklung
 
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
 
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der PraxisOC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
 
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und CloudOC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
 
OC|Webcast: Grundlagen der Oracle-Lizenzierung
OC|Webcast: Grundlagen der Oracle-LizenzierungOC|Webcast: Grundlagen der Oracle-Lizenzierung
OC|Webcast: Grundlagen der Oracle-Lizenzierung
 
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
 
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
 
OC|Weekly Talk The Power of DevOps…
OC|Weekly Talk  The Power of DevOps…OC|Weekly Talk  The Power of DevOps…
OC|Weekly Talk The Power of DevOps…
 
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
 
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
 
OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring
 
OC|Weekly Talk - Beratung remote
OC|Weekly Talk - Beratung remoteOC|Weekly Talk - Beratung remote
OC|Weekly Talk - Beratung remote
 
Effiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud NutzungEffiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud Nutzung
 

Testgetriebene Entwicklung mit JavaScript – Jax 2012

  • 1. Testgetriebene Entwicklung mit JavaScript Tobias Bosch & Stefan Scheidt OPITZ CONSULTING GmbH
  • 2. Wer sind wir? tobias.bosch@opitz-consulting.com (@tigbro) stefan.scheidt@opitz-consulting.com (@stefanscheidt)
  • 3. Mission Märkte Wir entwickeln gemeinsam mit allen  Branchenübergreifend Branchen Lösungen, die dazu führen, dass  Über 600 Kunden sich diese Organisationen besser entwickeln 29% als ihr Wettbewerb. 29% Handel / Logistik / Dienstleistungen Industrie / Versorger / Unsere Dienstleistung erfolgt Telekommunikation partnerschaftlich und ist auf eine langjährige 42% Zusammenarbeit angelegt. Öffentliche Auftraggeber / Banken und Versicherungen / Vereine und Verbände Leistungsangebot Eckdaten  Business IT Alignment  Gründung 1990  Business Information Management  400 Mitarbeiter  Business Process Management  8 Standorte  Anwendungsentwicklung  SOA und System-Integration  IT-Infrastruktur-Management Testgetriebene Entwicklung mit JavaScript © OPITZ CONSULTING GmbH 2011 Seite 3
  • 5. In diesem Vortrag geht‘s um ... ... automatisiertes Testen ... durch Entwickler
  • 8. Laufzeitumgebungen für JavaScript ...
  • 9. In diesem Vortrag: Icon Set by Paul Irish (http://paulirish.com/2010/high-res-browser-icons/)
  • 12. „Klassisch“ mit xUnit-Asserts „BDD-Style“ à la RSpec
  • 13. Demo: BDD mit Jasmine
  • 14. Hello Jasmine! describe("parseFloat", function() { it("should return undefined for undefined", function () { expect(util.parseFloat(undefined)).toBeUndefined(); }); it("should return 0 for empty string", function () { expect(util.parseFloat('')).toEqual(0); }); it("should return number for number strings", function () { expect(util.parseFloat('1.5')).toEqual(1.5); }); // ... });
  • 15. Hello Jasmine! describe("parseFloat", function() { it("should return undefined for undefined", function () { expect(util.parseFloat(undefined)).toBeUndefined(); }); it("should return 0 for empty string", function () { expect(util.parseFloat('')).toEqual(0); }); it("should return number for number strings", function () { expect(util.parseFloat('1.5')).toEqual(1.5); }); // ... });
  • 16. Hello Jasmine! describe("parseFloat", function() { it("should return undefined for undefined", function () { expect(util.parseFloat(undefined)).toBeUndefined(); }); it("should return 0 for empty string", function () { expect(util.parseFloat('')).toEqual(0); }); it("should return number for number strings", function () { expect(util.parseFloat('1.5')).toEqual(1.5); }); // ... });
  • 17. Hello Jasmine! describe("parseFloat", function() { it("should return undefined for undefined", function () { expect(util.parseFloat(undefined)).toBeUndefined(); }); it("should return 0 for empty string", function () { expect(util.parseFloat('')).toEqual(0); }); it("should return number for number strings", function () { expect(util.parseFloat('1.5')).toEqual(1.5); }); // ... });
  • 18. Hello Jasmine! expect(x).toEqual(y); expect(x).toBe(y); expect(x).toBeDefined(); expect(x).toBeUndefined(); expect(x).toBeTruthy(); expect(x).toBeFalsy(); ...
  • 21. Spies
  • 22. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); jasmine.Clock.useMock(); spyOn(util, 'opacity'); fadein.execute(element); jasmine.Clock.tick(1000); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 23. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); spyOn(window, 'setTimeout').andCallFake( function(callback) { callback(); }); spyOn(util, 'opacity'); fadein.execute(element); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 24. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); spyOn(window, 'setTimeout').andCallFake( function(callback) { callback(); }); spyOn(util, 'opacity'); fadein.execute(element); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 25. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); spyOn(window, 'setTimeout').andCallFake( function(callback) { callback(); }); spyOn(util, 'opacity'); fadein.execute(element); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 26. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); spyOn(window,set opacity of 'element' to 'opacity' // 'setTimeout').andCallFake( util.opacity = function (element, opacity) { function(callback) { ... callback(); }; }); spyOn(util, 'opacity'); fadein.execute(element); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 27. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); spyOn(window, 'setTimeout').andCallFake( function(callback) { callback(); }); spyOn(util, 'opacity'); fadein.execute(element); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 28. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { var element = document.createElement("div"); spyOn(window,set opacity of 'element' to 'opacity' // 'setTimeout').andCallFake( function(callback) = function (element, opacity) { util.opacity { ... callback(); }); }; spyOn(util, 'opacity'); fadein.execute(element); var mostRecentCall = util.opacity.mostRecentCall; expect(mostRecentCall.args[0]).toBe(element); expect(mostRecentCall.args[1]).toEqual(1); }); });
  • 29. Funktion Der Spy soll ... spy.andCallThrough() ... die ursprüngliche Funktion aufrufen ... das übergebene Argumente spy.andReturn(argument) zurückgeben ... die übergebene Exception spy.andThrow(exception) werfen spy.andCallFake(function) ... die übergebene Funktion aufrufen Funktionen von Spies
  • 30. Funktion Prüft, ob der Spy ... toHaveBeenCalled() ... aufrufen wurde ... mit den übergebenen toHaveBeenCalledWith(args) Argumenten aufgerufen wurde Matcher für Spies Funktion Bedeutung spy.callCount Anzahl der Aufrufe spy.argsForCall[i] Argumente des i-ten Aufrufs spy.mostRecentCall.args Argumente des letzten Aufrufs Eigenschaften von Spies
  • 32. Asynchrone Tests it("should eventually set opacity to 1", function() { var element = document.createElement("div"); spyOn(util, 'opacity'); runs(function() { fadein.execute(element); }); waitsFor(function () { return opacitySpy.mostRecentCall.args[1] === 1; }); runs(function() { // some other expectations expect(opacitySpy.mostRecentCall.args[1]).toEqual(1); }); });
  • 33. Asynchrone Tests it("should eventually set opacity to 1", function() { var element = document.createElement("div"); spyOn(util, 'opacity'); runs(function() { fadein.execute(element); }); waitsFor(function () { return opacitySpy.mostRecentCall.args[1] === 1; }); runs(function() { // some other expectations expect(opacitySpy.mostRecentCall.args[1]).toEqual(1); }); });
  • 34. Asynchrone Tests it("should eventually set opacity to 1", function() { var element = document.createElement("div"); spyOn(util, 'opacity'); runs(function() { fadein.execute(element); }); waitsFor(function () { return opacitySpy.mostRecentCall.args[1] === 1; }); runs(function() { // some other expectations expect(opacitySpy.mostRecentCall.args[1]).toEqual(1); }); });
  • 35. Asynchrone Tests it("should eventually set opacity to 1", function() { var element = document.createElement("div"); spyOn(util, 'opacity'); runs(function() { fadein.execute(element); }); waitsFor(function () { return opacitySpy.mostRecentCall.args[1] === 1; }); runs(function() { // some other expectations // set opacity of 'element' to 'opacity' expect(opacitySpy.mostRecentCall.args[1]).toEqual(1); { util.opacity = function (element, opacity) }); ... }); };
  • 36. Asynchrone Tests it("should eventually set opacity to 1", function() { var element = document.createElement("div"); spyOn(util, 'opacity'); runs(function() { fadein.execute(element); }); waitsFor(function () { return opacitySpy.mostRecentCall.args[1] === 1; }); runs(function() { // some other expectations expect(opacitySpy.mostRecentCall.args[1]).toEqual(1); }); });
  • 38. describeUi("index", "/js-fadein/index.html", function () { it("should fade in hello div on button click", function () { var win, field, button; runs(function() { field = document.getElementById('hello'); button = document.getElementById('fadein'); expect(util.opacity(field)).toEqual(0); simulate(button, 'click'); }); runs(function () { expect(util.opacity(field)).toEqual(1); }); }); }); UI-Test mit Jasmine-UI
  • 39. describeUi("index", "/js-fadein/index.html", function () { it("should fade in hello div on button click", function () { var win, field, button; runs(function() { field = document.getElementById('hello'); button = document.getElementById('fadein'); expect(util.opacity(field)).toEqual(0); simulate(button, 'click'); }); runs(function () { expect(util.opacity(field)).toEqual(1); }); }); }); UI-Test mit Jasmine-UI
  • 40. describeUi("index", "/js-fadein/index.html", function () { it("should fade in hello div on button click", function () { var win, field, button; runs(function() { field = document.getElementById('hello'); button = document.getElementById('fadein'); expect(util.opacity(field)).toEqual(0); simulate(button, 'click'); }); runs(function () { expect(util.opacity(field)).toEqual(1); }); }); }); UI-Test mit Jasmine-UI
  • 41. describeUi("index", "/js-fadein/index.html", function () { it("should fade in hello div on button click", function () { var win, field, button; runs(function() { field = document.getElementById('hello'); button = document.getElementById('fadein'); expect(util.opacity(field)).toEqual(0); simulate(button, 'click'); }); runs(function () { expect(util.opacity(field)).toEqual(1); }); }); }); UI-Test mit Jasmine-UI
  • 42. describeUi("index", "/js-fadein/index.html", function () { it("should fade in hello div on button click", function () { var win, field, button; runs(function() { field = document.getElementById('hello'); button = document.getElementById('fadein'); expect(util.opacity(field)).toEqual(0); simulate(button, 'click'); }); runs(function () { expect(util.opacity(field)).toEqual(1); }); }); }); UI-Test mit Jasmine-UI
  • 43. describeUi("index", "/js-fadein/index.html", function () { it("should fade in hello div on button click", function () { var win, field, button; runs(function() { field = document.getElementById('hello'); button = document.getElementById('fadein'); expect(util.opacity(field)).toEqual(0); simulate(button, 'click'); }); runs(function () { expect(util.opacity(field)).toEqual(1); }); }); }); UI-Test mit Jasmine-UI
  • 45. Pro Contra Beispiele - Schwerer zu Im Laufen in QUnit automatisieren Browser Produktions- YUI Test testen - Schwerer in CI umgebung Jasmine einzubetten - Leicht zu Envjs Headless automatisieren Browser wird PhantomJS Browser - Leicht in CI nur simuliert Zombie.js einzubetten HtmlUnit
  • 49. Fazit Es gibt ein umfangreiches Toolset zum Testen von JavaScript-Code. Testen Sie Ihren Code! Testen Sie insbesondere Ihren JavaScript-Code! Sie haben keine Ausrede ...
  • 50. Links Jasmine http://pivotal.github.com/jasmine/ Jasmine UI https://github.com/tigbro/jasmine-ui js-fadein https://github.com/stefanscheidt/js-fadein JsTestDriver http://code.google.com/p/js-test-driver/
  • 51. saturated writing (By Eduordo, http://www.flickr.com/photos/tnarik/366393127/) Smiley Keyboard (By ~Prescott, http://www.flickr.com/photos/ppym1/93571524/) Spyhole, Paris (By smith of smiths, http://www.flickr.com/photos/hesketh/232015302/) Sorta synchronised diving (By Aaron Retz, http://www.flickr.com/photos/aretz/309469339/)
  • 52. Stamp Collector (By C. Castillo, http://www.flickr.com/photos/carolinedecastillo/2750577684/) bios [bible] (By Gastev, http://www.flickr.com/photos/gastev/2174505811/) Day 276/365: in hot pursuit (By Tina Vega, http://www.flickr.com/photos/tinavega/3066602429/)
  • 53. Vielen Dank für Ihr Interesse! @tigbro @stefanscheidt