SlideShare une entreprise Scribd logo
1  sur  61
Test Driven JavaScript Development


Tobias Bosch
OPITZ CONSULTING Deutschland GmbH
Who am I?



tobias.bosch@opitz-consulting.com
            (@tigbro)
Mission                                                                  Markets
The company's ambition is to help                                         Branchspreading
organizations to be better than their                                     Over 600 customers
competitors.                                                                                                  29%
                                                                                                              Trade / Logistics /
Our services take place in partnership and                                                29%                 Supplier
                                                                          Industry / Services /
are aimed at a co-operation of many years.                               Telecommunications

                                                                                                      42%
                                                                                                      Public Clients / Banks and Insurance
                                                                                                      Associations and Federations



Portfolio                                                                Basic Data
 Business IT Alignment                                                   Founded in 1990
 Business Information Management                                         400 employees
 Business Process Management                                             8 offices
 Application Development
 SOA and System Integration
 IT Infrastructure Management


                   <Präsentationstitel – bitte im Folienmaster ändern>                            © OPITZ CONSULTING GmbH 2011           Seite 3
Who are you?
This talk is about...

    ... automatic tests
... written by developers
Why should I test?
Why should I test JavaScript code?
Runtime environments for
       JavaScript




                       ...
In this talk




Icon Set by Paul Irish (http://paulirish.com/2010/high-res-browser-icons/)
The example
Writing tests
„Classic style“ with
    xUnit asserts

„BDD style“ à la RSpec
Demo: BDD with Jasmine
Hello Jasmine!

  expect(x).toEqual(y);
    expect(x).toBe(y);
 expect(x).toBeDefined();
expect(x).toBeUndefined();
 expect(x).toBeTruthy();
  expect(x).toBeFalsy();
           ...
Advanced concepts
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");
        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");
        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");
        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");
        jasmine.Clock.useMock();
        spyOn(util, 'opacity');
        fadein.execute(element);
        jasmine.Clock.tick(1000);of 'element' to 'opacity'
                  // set opacity
        var mostRecentCall = util.opacity.mostRecentCall;
                  util.opacity = function (element, opacity) {
                      ...
        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");
        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");
        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");
        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 () {
                 // set opacity of 'element' to 'opacity'
                 util.opacity = function (element, opacity) {
        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);
    });
});
Function                    The spy should...

spy.andCallThrough()        ... call the original function

spy.andReturn(argument)     ... return the given argument

spy.andThrow(exception)     ... throw the given exception

spy.andCallFake(function)   ... call the given function


                Functions of spies
Function                      Checks whether the spy...
toHaveBeenCalled()            ... has been called
                              ... has been called with the given
toHaveBeenCalledWith(args)
                                  arguments
                     Matcher for spies


Function                      Description
spy.callCount                 Number of calls

spy.argsForCall[i]            Arguments of the i-th call

spy.mostRecentCall.args       Arguments of the last call

                     Properties of spies
Asynchronous tests
Asynchronous 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);
    });
});
Asynchronous 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);
    });
});
Asynchronous 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);
    });
});
Asynchronous 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)
    });               ...
});               };
Asynchronous 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 with Jasmine UI
Jasmine UI

  Extension of JS test framework Jasmine

Allows to load, instrument and test a webapp
                in the browser

  Supports testing asynchronous behaviour
Analyse             HTML Session Storage   Show
            specs                                    results


    Scripts:                     Load                          Scripts:
                                 app
jasmine-ui.js                                            jasmine-ui.js
jasmine-html.js                                          jasmine-html.js
"uiSpec.js"                             Collect          "uiSpec.js"
                                        results

UiSpecRunner.html                                       UiSpecRunner.html
                                   Scripts:

                               "app.js"
                    Execute    "uiSpec.js"
                      specs
                                  index.html
<html>
<body>

<div id="hello">Hello World!</div>

<button id="fadein">Fade in</button>

</body>
</html>




                                       UI tests with 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 tests with 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 tests with 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 tests with 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 tests with 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 tests with 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 tests with Jasmine-UI
Instrument

describeUi("index", "/js-fadein/index.html", function () {

      beforeLoad(function() {
          mockBackend();
      });

      ...

});
Instrument

describeUi("index", "/js-fadein/index.html", function () {

      beforeLoad(function() {
          mockBackend();
      });

      ...

});
Instrument

describeUi("index", "/js-fadein/index.html", function () {

      beforeLoad(function() {
          mockBackend();
      });

      ...

});
Jasmine UI: Roadmap


 Support other test runners
     (e.g. testacular)

Support other test frameworks
         (e.g. QUnit)
Present: describeUi



describeUi('todo', '/todo-mobile', function() {
    // ...
});
Future: loadUi
jasmineui.loadUi('/todo-mobile', function() {

      // Jasmine specs
      describe('todo', function() {
          it('should do smth', function() { ... });
      });

      // QUnit tests
      module("todo");
      test("should do smth", function() {
          // ...
      });

});
Automated test execution
Pro               Examples

                Browser from       QUnit
 Testing in
                 production        YUI Test
the browser
                environment        Jasmine

                                   Envjs
              Easier to automate
 Headless                          PhantomJS
                Easier to embed
 browser                           Zombie.js
                      into CI
                                   HtmlUnit
Remote browser control
JsTestDriver




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

There are a lot of tools for testing JavaScript
                     code.

               Test your code!
    Especially test your JavaScript code!
           You have no excuse ...
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/)
Thanks for listening!
       @tigbro
www.opitz-consulting.com/go_mobile

Contenu connexe

Plus 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
 
OC|Weekly Talk - Mitarbeiterführung in Zeiten von Social Distance
OC|Weekly Talk - Mitarbeiterführung in Zeiten von Social DistanceOC|Weekly Talk - Mitarbeiterführung in Zeiten von Social Distance
OC|Weekly Talk - Mitarbeiterführung in Zeiten von Social DistanceOPITZ CONSULTING Deutschland
 

Plus de OPITZ CONSULTING Deutschland (20)

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
 
OC|Weekly Talk - Mitarbeiterführung in Zeiten von Social Distance
OC|Weekly Talk - Mitarbeiterführung in Zeiten von Social DistanceOC|Weekly Talk - Mitarbeiterführung in Zeiten von Social Distance
OC|Weekly Talk - Mitarbeiterführung in Zeiten von Social Distance
 
OC|Weekly Talk Remote Design Thinking
OC|Weekly Talk Remote Design ThinkingOC|Weekly Talk Remote Design Thinking
OC|Weekly Talk Remote Design Thinking
 
OC|Webcast Smart Innovation am 7. April 2020
OC|Webcast Smart Innovation am 7. April 2020OC|Webcast Smart Innovation am 7. April 2020
OC|Webcast Smart Innovation am 7. April 2020
 

Dernier

MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 

Dernier (20)

MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 

Test Driven JavaScript Development – WebTechConference 2012

  • 1. Test Driven JavaScript Development Tobias Bosch OPITZ CONSULTING Deutschland GmbH
  • 3. Mission Markets The company's ambition is to help  Branchspreading organizations to be better than their  Over 600 customers competitors. 29% Trade / Logistics / Our services take place in partnership and 29% Supplier Industry / Services / are aimed at a co-operation of many years. Telecommunications 42% Public Clients / Banks and Insurance Associations and Federations Portfolio Basic Data  Business IT Alignment  Founded in 1990  Business Information Management  400 employees  Business Process Management  8 offices  Application Development  SOA and System Integration  IT Infrastructure Management <Präsentationstitel – bitte im Folienmaster ändern> © OPITZ CONSULTING GmbH 2011 Seite 3
  • 4.
  • 6. This talk is about... ... automatic tests ... written by developers
  • 7. Why should I test?
  • 8. Why should I test JavaScript code?
  • 9. Runtime environments for JavaScript ...
  • 10. In this talk Icon Set by Paul Irish (http://paulirish.com/2010/high-res-browser-icons/)
  • 13. „Classic style“ with xUnit asserts „BDD style“ à la RSpec
  • 14. Demo: BDD with Jasmine
  • 15. Hello Jasmine! expect(x).toEqual(y); expect(x).toBe(y); expect(x).toBeDefined(); expect(x).toBeUndefined(); expect(x).toBeTruthy(); expect(x).toBeFalsy(); ...
  • 17. Spies
  • 18. 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); }); });
  • 19. 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); }); });
  • 20. 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); }); });
  • 21. 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); }); });
  • 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);of 'element' to 'opacity' // set opacity var mostRecentCall = util.opacity.mostRecentCall; util.opacity = function (element, opacity) { ... 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"); 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); }); });
  • 24. 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); }); });
  • 25. 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); }); });
  • 26. Spies describe("execute fadein", function() { it("should eventually set opacity to 1", function () { // set opacity of 'element' to 'opacity' util.opacity = function (element, opacity) { 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); }); });
  • 27. Function The spy should... spy.andCallThrough() ... call the original function spy.andReturn(argument) ... return the given argument spy.andThrow(exception) ... throw the given exception spy.andCallFake(function) ... call the given function Functions of spies
  • 28. Function Checks whether the spy... toHaveBeenCalled() ... has been called ... has been called with the given toHaveBeenCalledWith(args) arguments Matcher for spies Function Description spy.callCount Number of calls spy.argsForCall[i] Arguments of the i-th call spy.mostRecentCall.args Arguments of the last call Properties of spies
  • 30. Asynchronous 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); }); });
  • 31. Asynchronous 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); }); });
  • 32. Asynchronous 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. Asynchronous 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) }); ... }); };
  • 34. Asynchronous 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. UI tests with Jasmine UI
  • 36. Jasmine UI Extension of JS test framework Jasmine Allows to load, instrument and test a webapp in the browser Supports testing asynchronous behaviour
  • 37. Analyse HTML Session Storage Show specs results Scripts: Load Scripts: app jasmine-ui.js jasmine-ui.js jasmine-html.js jasmine-html.js "uiSpec.js" Collect "uiSpec.js" results UiSpecRunner.html UiSpecRunner.html Scripts: "app.js" Execute "uiSpec.js" specs index.html
  • 38. <html> <body> <div id="hello">Hello World!</div> <button id="fadein">Fade in</button> </body> </html> UI tests with 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 tests with 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 tests with 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 tests with 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 tests with 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 tests with Jasmine-UI
  • 44. 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 tests with Jasmine-UI
  • 45. Instrument describeUi("index", "/js-fadein/index.html", function () { beforeLoad(function() { mockBackend(); }); ... });
  • 46. Instrument describeUi("index", "/js-fadein/index.html", function () { beforeLoad(function() { mockBackend(); }); ... });
  • 47. Instrument describeUi("index", "/js-fadein/index.html", function () { beforeLoad(function() { mockBackend(); }); ... });
  • 48. Jasmine UI: Roadmap Support other test runners (e.g. testacular) Support other test frameworks (e.g. QUnit)
  • 50. Future: loadUi jasmineui.loadUi('/todo-mobile', function() { // Jasmine specs describe('todo', function() { it('should do smth', function() { ... }); }); // QUnit tests module("todo"); test("should do smth", function() { // ... }); });
  • 52. Pro Examples Browser from QUnit Testing in production YUI Test the browser environment Jasmine Envjs Easier to automate Headless PhantomJS Easier to embed browser Zombie.js into CI HtmlUnit
  • 56. Conclusion There are a lot of tools for testing JavaScript code. Test your code! Especially test your JavaScript code! You have no excuse ...
  • 57. 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/
  • 58. 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/)
  • 59. 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/)