Test driven java script development

55
TestDriven JavaScript Development Tobias Bosch & Stefan Scheidt / OPITZ CONSULTING GmbH

description

JavaScript ist eine sehr dynamische Sprache und verhält sich zudem je nach Browser unterschiedlich. Daher sind automatisierte Tests besonders wertvoll. Dieser Vortrag zeigt, wie Cross-Browser-Tests für JavaScript entwickelt werden können.Vortrag von der MobileTech Conference 2011

Transcript of Test driven java script development

Page 1: Test driven java script development

Test-­‐Driven  JavaScript  Development  

Tobias  Bosch  &  Stefan  Scheidt  /  OPITZ  CONSULTING  GmbH  

Page 2: Test driven java script development

Wer  sind  wir?  

tobias.bosch@opitz-­‐consulLng.com  (@Lgbro)  

 stefan.scheidt@opitz-­‐consulLng.com  

(@beezlebug)    

Page 3: Test driven java script development

© OPITZ CONSULTING GmbH 2011 Seite 3

OPITZ CONSULTING Vorlage Powerpoint 2011; Version 1.3; 10.05.2011; TGA, KSH

1Pager •  Layout ausschließlich für den

1Pager •  Einsatz ist bei Konferenzen,

ext. Veranstaltungen etc. obligatorisch. Die Folie ist Folie 2 (nach der Titelfolie)

•  Der Inhalt darf nicht verändert werden.

•  Ausnahme: Der Block Märkte darf situativ um Partnerlogos (ORACLE, etc.) ergänzt werden

© OPITZ CONSULTING GmbH 2011

Märkte n Java n SOA n ORACLE n BI/DWH n Outtasking

Kunden n Branchen-

übergreifend n Über 600

Kunden

Leistungs- angebot n IT-Strategie n Beratung n Implementierung n Betrieb n Training

Fakten n Gründung 1990 n 400 Mitarbeiter n 8 Standorte in D/

PL

Industrie / Versorger / Telekommunikation

29%

Handel / Logistik / Dienstleistungen 29%

42% Öffentliche Auftraggeber /

Banken & Versicherungen / Vereine & Verbände

Page 4: Test driven java script development

Wer  sind  Sie?  

Page 5: Test driven java script development

In  diesem  Vortrag  geht‘s  um...    

...automaLsiertes  Testen  ...durch  Entwickler  

Page 6: Test driven java script development

Warum  testen?  

Page 7: Test driven java script development

Warum  JavaScript-­‐Code  testen?  

Page 8: Test driven java script development

Laufzeitumgebungen  für  JavaScript  

          ...  

Page 9: Test driven java script development

In  diesem  Vortrag:            

Icon  Set  by  Paul  Irish  (h4p://paulirish.com/2010/high-­‐res-­‐browser-­‐icons/)    

Page 10: Test driven java script development

Tests  formulieren  

Page 11: Test driven java script development

„Klassisch“  mit  xUnit-­‐Asserts      

„BDD-­‐Style“    à  la  RSpec  

Page 12: Test driven java script development

Demo:  BDD  mit  Jasmine  

Page 13: Test driven java script development

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!  

Page 14: Test driven java script development

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!  

Suite  

Page 15: Test driven java script development

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!  

Specs  

Page 16: Test driven java script development

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!  

Matcher  

Page 17: Test driven java script development

Hello  Jasmine!  

expect(x).toEqual(y);  

expect(x).toBe(y);  

expect(x).toBeDefined();  

expect(x).toBeUndefined();  

expect(x).toBeTruthy();  

expect(x).toBeFalsy();  

...  

Matcher  

Page 18: Test driven java script development

Hello  Jasmine!  

Spec  Runner  

Page 19: Test driven java script development

Fortgeschriaene  Konzepte  

Page 20: Test driven java script development

Spies  

Page 21: Test driven java script development

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

Page 22: Test driven java script development

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

Page 23: Test driven java script development

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

Arrange  

Page 24: Test driven java script development

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

//  waits  for  'delay'  seconds  //  then  calls  callback  window.setTimeout  =  function  (callback,  delay)  {          ...  };    

Arrange  

Page 25: Test driven java script development

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

Arrange  //  set  opacity  of  'element'  to  'opacity'  util.opacity  =  function  (element,  opacity)  {          ...  };    

Page 26: Test driven java script development

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

Act  

Page 27: Test driven java script development

Spies  

Assert  

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);                  expect(util.opacity.mostRecentCall.args[1]).toEqual(1);          });    });  

//  set  opacity  of  'element'  to  'opacity'  util.opacity  =  function  (element,  opacity)  {          ...  };    

Page 28: Test driven java script development

FunkLon   Der  Spy  soll...  

spy.andCallThrough()   ...  die  ursprüngliche  FunkLon  aufrufen  

spy.andReturn(argument)   ...  das  übergebene  Argumente  zurückgeben  

spy.andThrow(exception)   ...  die  übergebene  ExcepLon  werfen  

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

FunkLonen  von  Spies  

Page 29: Test driven java script development

FunkLon   Prüb,  ob  der  Spy...  

toHaveBeenCalled()   ...  aufrufen  wurde  

toHaveBeenCalledWith(args)   ...  mit  den  übergebenen  Argumenten  aufgerufen  wurde  

Matcher  für  Spies  

FunkLon   Bedeutung  

spy.callCount   Anzahl  der  Aufrufe  

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

spy.mostRecentCall.args   Argumente  des  letzten  Aufrufs  

Eigenschaben  von  Spies  

Page 30: Test driven java script development

Asynchrone  Tests  

Page 31: Test driven java script development

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  

Page 32: Test driven java script development

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  

Arrange  

Page 33: Test driven java script development

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  

Act  

Page 34: Test driven java script development

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  

Wait...  

//  set  opacity  of  'element'  to  'opacity'  util.opacity  =  function  (element,  opacity)  {          ...  };    

Page 35: Test driven java script development

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  

Assert  

Page 36: Test driven java script development

UI-­‐Tests  

Page 37: Test driven java script development
Page 38: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 39: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

The  index  pa

ge...  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 40: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

Arrange,  Part  1  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 41: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

Arrange,  Part  2  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 42: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

Act  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 43: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

Wait...  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 44: Test driven java script development

it("should  fade  in  hello  div  on  button  click",  function  ()  {          var  win,  field,  button;          loadHtml("/js-­‐fadein/index.html");          runs(function()  {                  win  =  testwindow();                  field  =  win.document.getElementById('hello');                  button  =  win.document.getElementById('fadein');          });          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(0);                  jasmine.ui.simulate(button,  'click');          });          waitsForAsync();          runs(function  ()  {                  expect(win.util.opacity(field)).toEqual(1);          });  });  

Assert  

 UI-­‐Test  mit  Jasmine-­‐UI    

Page 45: Test driven java script development

Testausführung  automaLsieren  

Page 46: Test driven java script development

Pro   Contra   Beispiele  

Im  Browser  testen  

Laufen  in  ProdukLons-­‐umgebung  

-­‐  Schwerer  zu  automaLsieren  

-­‐  Schwerer  in  CI  einzubeaen  

 QUnit    YUI  Test    Jasmine  

Headless  Browser  

-­‐  Leicht  zu  automaLsieren  

-­‐    Leicht  in  CI  einzubeaen  

Browser  wird  nur  simuliert  

 Envjs  

 PhantomJS    Zombie.js    HtmlUnit  

Page 47: Test driven java script development

Browser  fernsteuern  

Page 48: Test driven java script development

JsTestDriver  

h4p://code.google.com/p/js-­‐test-­‐driver/  

Page 49: Test driven java script development

Demo:  JsTestDriver  

Page 50: Test driven java script development

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...  

Page 51: Test driven java script development

Links  

Jasmine   hap://pivotal.github.com/jasmine/  

Jasmine  UI   haps://github.com/Lgbro/jasmine-­‐ui  

JsTestDriver   hap://code.google.com/p/js-­‐test-­‐driver/  

Page 52: Test driven java script development

saturated  wriLng  (By  Eduordo,  hap://www.flickr.com/photos/tnarik/366393127/)  

 Smiley  Keyboard  

(By  ~Prescoa,  hap://www.flickr.com/photos/ppym1/93571524/)    

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

 Sorta  synchronised  diving  

(By  Aaron  Retz,  hap://www.flickr.com/photos/aretz/309469339/)  

Page 53: Test driven java script development

Stamp  Collector  (By  C.  CasLllo,  hap://www.flickr.com/photos/carolinedecasLllo/2750577684/)  

 bios  [bible]  

(By  Gastev,  hap://www.flickr.com/photos/gastev/2174505811/)    

Day  276/365:  in  hot  pursuit  (By  Tina  Vega,  hap://www.flickr.com/photos/Lnavega/3066602429/)  

 

Page 54: Test driven java script development

Besuchen  Sie  uns  Morgen  beim  Vortrag    

JavaScript  Data  Binding  mit  jQuery  Mobile  

 um  10:00  Uhr  im  Watordsaal  

Page 55: Test driven java script development

Vielen  Dank  für  Ihr  Interesse!  

 @Lgbro  

@beezlebug