SlideShare a Scribd company logo
1 of 29
Download to read offline
JavaScript
unit testing
    with
@rsim




                          github.com/rsim
Raimonds Simanovskis
The easiest Business Intelligence tool on the Web
Using threads
in Ruby applications
Using threads
in JavaScript
 applications
You can’t :)
JavaScript
unit testing
    with
RSpec-like testing for
    JavaScript
Syntax
describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});




describe("A suite is just a function", function() {
  var a;

  it("and so is a spec", function() {
    a = true;

    expect(a).toBe(true);
  });
});
Matchers

describe("The 'toBe' matcher compares with ===", function() {

  it("and has a positive case ", function() {
    expect(true).toBe(true);
  });

  it("and can have a negative case", function() {
    expect(false).not.toBe(true);
  });

});
Included matchers

 toBe            toContain
 toEqual         toBeLessThan
 toMatch         toBeGreaterThan
 toBeDefined     toBeCloseTo
 toBeUndefined   toThrow
 toBeNull
 toBeTruthy
 toBeFalsy
Setup & teardown
describe("A spec (with setup and tear-down)", function() {
  var foo;

  beforeEach(function() {
    foo = 0;
    foo += 1;
  });

  afterEach(function() {
    foo = 0;
  });

  it("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });

  it("can have more than one expectation", function() {
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });
});
describe("A spec", function() {
  var foo;
  beforeEach(function() {
                                          Nesting
    foo = 0;
    foo += 1;
  });
  afterEach(function() {
    foo = 0;
  });
  it("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });
  it("can have more than one expectation", function() {
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });
  describe("nested inside a second describe", function() {
    var bar;
    beforeEach(function() {
      bar = 1;
    });
    it("can reference both scopes as needed ", function() {
      expect(foo).toEqual(bar);
    });
  });
});
Disabling
xdescribe("A spec", function() {
  var foo;

  beforeEach(function() {
    foo = 0;
    foo += 1;
  });

  xit("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });
});
describe("A spy", function() {


                                                         Spies
  var foo, bar = null;
  beforeEach(function() {
    foo = {
       setBar: function(value) {
         bar = value;
       }
    };
    spyOn(foo, 'setBar');
    foo.setBar(123);
    foo.setBar(456, 'another param');
  });
  it("tracks that the spy was called", function() {
    expect(foo.setBar).toHaveBeenCalled();
  });
  it("tracks its number of calls", function() {
    expect(foo.setBar.calls.length).toEqual(2);
  });
  it("tracks all the arguments of its calls", function() {
    expect(foo.setBar).toHaveBeenCalledWith(123);
    expect(foo.setBar).toHaveBeenCalledWith(456, 'another param');
  });
  it("allows access to the most recent call", function() {
    expect(foo.setBar.mostRecentCall.args[0]).toEqual(456);
  });
  it("allows access to other calls", function() {
    expect(foo.setBar.calls[0].args[0]).toEqual(123);
  });
  it("stops all execution on a function", function() {
    expect(bar).toBeNull();
  });
});
describe("A spy, when faking a return value", function() {
  var foo, bar, fetchedBar;
  beforeEach(function() {


                                            andReturn
    foo = {
       setBar: function(value) {
          bar = value;
       },
       getBar: function() {
          return bar;
       }
    };
    spyOn(foo, 'getBar').andReturn(745);
    foo.setBar(123);
    fetchedBar = foo.getBar();
  });
  it("tracks that the spy was called", function() {
    expect(foo.getBar).toHaveBeenCalled();
  });
  it("should not effect other functions", function() {
    expect(bar).toEqual(123);
  });
  it("when called returns the requested value", function() {
    expect(fetchedBar).toEqual(745);
  });
});
Async tests
describe("Asynchronous specs", function() {
  var value, flag;
  it("should support async execution of test preparation and
exepectations", function() {
    runs(function() {
      flag = false;
      value = 0;
      setTimeout(function() {
        flag = true;
      }, 500);
    });
    waitsFor(function() {
      value++;
      return flag;
    }, "The Value should be incremented", 750);
    runs(function() {
      expect(value).toBeGreaterThan(0);
    });
  });
});
Jasmine tests runner


      Demo
Works nice
with CoffeeScript
and Backbone.js
Testing Backbone.js
          model
describe "Todo", ->
  todo = null
  ajaxCall = (param) -> jQuery.ajax.mostRecentCall.args[0][param]

  beforeEach ->
    todo = new TodoApp.Todo
    todos = new TodoApp.TodoList [todo]

  it "should initialize with empty content", ->
    expect(todo.get "content").toEqual "empty todo..."

  it "should initialize as not done", ->
    expect(todo.get "done").toBeFalsy()

  it "should save after toggle", ->
    spyOn jQuery, "ajax"
    todo.toggle()
    expect(ajaxCall "url").toEqual "/todos"
    expect(todo.get "done").toBeTruthy()
and collection
describe "TodoList", ->
  attributes = [
    content: "First"
    done: true
  ,
    content: "Second"
  ]
  todos = null

  beforeEach ->
    todos = new TodoApp.TodoList attributes

  it "should return done todos", ->
    expect(_.invoke todos.done(), "toJSON").toEqual [attributes[0]]

  it "should return remaining todos", ->
    expect(_.invoke todos.remaining(), "toJSON").toEqual [attributes[1]]
jasmine-jquery

• a set of custom matchers for jQuery
  framework
• an API for handling HTML, CSS, and
  JSON fixtures in your specs
expect($('<div id="some-id"></div>')).toBe('div#some-id')

expect($('<input type="checkbox" checked="checked"/>')).toBeChecked()

expect($('<div style="display: none; margin: 10px;"></
div>')).toHaveCss({display: "none", margin: "10px"})

expect($('<option selected="selected"></option>')).toBeSelected()

expect($('<div><span class="some-class"></span></
div>')).toContain('span.some-class')

expect($('<div class="some-class"></div>')).toHaveClass("some-class")

expect($('<div><span></span></div>')).toHaveHtml('<span></span>')

expect($('<div><ul></ul><h1>header</h1></div>')).toContainHtml('<ul></
ul>')

expect($('<div>some text</div>')).toHaveText('some text')

expect($('<input type="text" value="some text"/>')).toHaveValue('some
text')

expect('<input type='submit' disabled='disabled'/>').toBeDisabled()

expect($('<input type='text' />').focus()).toBeFocused()
HTML fixtures

In myfixture.html file:

<div id="my-fixture">some complex content here</div>


Inside your test:

loadFixtures('myfixture.html');
$('#my-fixture').myTestedPlugin();
expect($('#my-fixture')).to...;
jasmine-fixture
// Let's say you want to write a Jasmine spec for some code
// that needs to select elements from the DOM with jQuery:

$('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]')

// In the good ol' days of manually crafting your HTML fixtures,
// you'd have to append some raw HTML to the DOM like this:

beforeEach(function(){
  $('<div id="toddler"><div class="hidden toy"><input name="toyName"
value="cuddle bunny"></div></div>').appendTo('body');
});

afterEach(function(){
  $('#toddler').remove()
});


// But jasmine-fixture's affix method lets you do this instead:

beforeEach(function(){
  affix('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]')
});
jasmine-given
describe("assigning stuff to this", function() {
  Given(function() { this.number = 24; });
  Given(function() { this.number++; });
  When(function() { this.number *= 2; });
  Then(function() { return this.number === 50; });
  // or
  Then(function() { expect(this.number).toBe(50) });
});

describe("assigning stuff to variables", function() {
  var subject;
  Given(function() { subject = []; });
  When(function() { subject.push('foo'); });
  Then(function() { return subject.length === 1; });
  // or
  Then(function() { expect(subject.length).toBe(1); });
});
jasmine-given
describe "assigning stuff to this", ->
  Given -> @number = 24
  Given -> @number++
  When -> @number *= 2
  Then -> @number == 50
  # or
  Then -> expect(@number).toBe(50)

describe "assigning stuff to variables", ->
  subject=null
  Given -> subject = []
  When -> subject.push('foo')
  Then -> subject.length == 1
  # or
  Then -> expect(subject.length).toBe(1)
jasmine-stealth
describe("multiple stubbings", function() {
  var someSpy;
  beforeEach(function() {
    someSpy = jasmine.createSpy();
    someSpy.when("pirate", { booty: ["jewels",jasmine.any(String)]}).thenReturn("argh!");
    someSpy.when("panda",1).thenReturn("sad");
  });

  it("stubs the first accurately", function() {
    expect(someSpy("pirate",{ booty: ["jewels","coins"]})).toBe("argh!");
  });

  it("stubs the second too", function() {
    expect(someSpy("panda",1)).toBe("sad");
  });

  it("doesn't return anything when a stubbing isn't satisfied",function(){
    expect(someSpy("anything else at all")).not.toBeDefined();
  });
});
References
          http://pivotal.github.io/jasmine/
  http://searls.testdouble.com/posts/2013-03-21-
           jasmine-tactics-screencast.html

https://github.com/rsim/backbone_coffeescript_demo
       https://github.com/rsim/rpn_calculator
            http://vimeo.com/53655205

More Related Content

What's hot

Unit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and NodeUnit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and Node
Josh Mock
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
Juriy Zaytsev
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
Chris Saylor
 

What's hot (20)

Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
Unit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and NodeUnit testing JavaScript using Mocha and Node
Unit testing JavaScript using Mocha and Node
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
 
Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express Middleware
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit TestingAdvanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
 
Testing JavaScript Applications
Testing JavaScript ApplicationsTesting JavaScript Applications
Testing JavaScript Applications
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
SilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringSilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript Refactoring
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 

Similar to JavaScript Unit Testing with Jasmine

Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}
.toster
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
Morgan Cheng
 
深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscex
jeffz
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
jeffz
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 

Similar to JavaScript Unit Testing with Jasmine (20)

AngularJS Testing
AngularJS TestingAngularJS Testing
AngularJS Testing
 
Introduccion a Jasmin
Introduccion a JasminIntroduccion a Jasmin
Introduccion a Jasmin
 
Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
 
Test-driven JavaScript Development - OPITZ CONSULTING - Tobias Bosch - Stefa...
Test-driven JavaScript Development - OPITZ CONSULTING -  Tobias Bosch - Stefa...Test-driven JavaScript Development - OPITZ CONSULTING -  Tobias Bosch - Stefa...
Test-driven JavaScript Development - OPITZ CONSULTING - Tobias Bosch - Stefa...
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
 
Call stack, event loop and async programming
Call stack, event loop and async programmingCall stack, event loop and async programming
Call stack, event loop and async programming
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love Affair
 
Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
 
深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscex
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Nevermore Unit Testing
Nevermore Unit TestingNevermore Unit Testing
Nevermore Unit Testing
 

More from Raimonds Simanovskis

Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
How to Adopt Agile at Your Organization
How to Adopt Agile at Your OrganizationHow to Adopt Agile at Your Organization
How to Adopt Agile at Your Organization
Raimonds Simanovskis
 
Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)
Raimonds Simanovskis
 

More from Raimonds Simanovskis (20)

Profiling Mondrian MDX Requests in a Production Environment
Profiling Mondrian MDX Requests in a Production EnvironmentProfiling Mondrian MDX Requests in a Production Environment
Profiling Mondrian MDX Requests in a Production Environment
 
Improve Mondrian MDX usability with user defined functions
Improve Mondrian MDX usability with user defined functionsImprove Mondrian MDX usability with user defined functions
Improve Mondrian MDX usability with user defined functions
 
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
 
Data Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data AnalysisData Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data Analysis
 
mondrian-olap JRuby library
mondrian-olap JRuby librarymondrian-olap JRuby library
mondrian-olap JRuby library
 
eazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applicationseazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applications
 
Atvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze LatvijāAtvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze Latvijā
 
JRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMJRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVM
 
Agile Operations or How to sleep better at night
Agile Operations or How to sleep better at nightAgile Operations or How to sleep better at night
Agile Operations or How to sleep better at night
 
TDD - Why and How?
TDD - Why and How?TDD - Why and How?
TDD - Why and How?
 
Analyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and ProfitAnalyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and Profit
 
PL/SQL Unit Testing Can Be Fun
PL/SQL Unit Testing Can Be FunPL/SQL Unit Testing Can Be Fun
PL/SQL Unit Testing Can Be Fun
 
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizationsopendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
 
RailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRuby
 
Multidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyMultidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRuby
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
 
How to Adopt Agile at Your Organization
How to Adopt Agile at Your OrganizationHow to Adopt Agile at Your Organization
How to Adopt Agile at Your Organization
 
Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)
 
PL/SQL Unit Testing Can Be Fun!
PL/SQL Unit Testing Can Be Fun!PL/SQL Unit Testing Can Be Fun!
PL/SQL Unit Testing Can Be Fun!
 

Recently uploaded

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 

JavaScript Unit Testing with Jasmine

  • 2. @rsim github.com/rsim Raimonds Simanovskis
  • 3. The easiest Business Intelligence tool on the Web
  • 4. Using threads in Ruby applications
  • 9. Syntax describe("A suite", function() { it("contains spec with an expectation", function() { expect(true).toBe(true); }); }); describe("A suite is just a function", function() { var a; it("and so is a spec", function() { a = true; expect(a).toBe(true); }); });
  • 10. Matchers describe("The 'toBe' matcher compares with ===", function() { it("and has a positive case ", function() { expect(true).toBe(true); }); it("and can have a negative case", function() { expect(false).not.toBe(true); }); });
  • 11. Included matchers toBe toContain toEqual toBeLessThan toMatch toBeGreaterThan toBeDefined toBeCloseTo toBeUndefined toThrow toBeNull toBeTruthy toBeFalsy
  • 12. Setup & teardown describe("A spec (with setup and tear-down)", function() { var foo; beforeEach(function() { foo = 0; foo += 1; }); afterEach(function() { foo = 0; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); it("can have more than one expectation", function() { expect(foo).toEqual(1); expect(true).toEqual(true); }); });
  • 13. describe("A spec", function() { var foo; beforeEach(function() { Nesting foo = 0; foo += 1; }); afterEach(function() { foo = 0; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); it("can have more than one expectation", function() { expect(foo).toEqual(1); expect(true).toEqual(true); }); describe("nested inside a second describe", function() { var bar; beforeEach(function() { bar = 1; }); it("can reference both scopes as needed ", function() { expect(foo).toEqual(bar); }); }); });
  • 14. Disabling xdescribe("A spec", function() { var foo; beforeEach(function() { foo = 0; foo += 1; }); xit("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); });
  • 15. describe("A spy", function() { Spies var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar'); foo.setBar(123); foo.setBar(456, 'another param'); }); it("tracks that the spy was called", function() { expect(foo.setBar).toHaveBeenCalled(); }); it("tracks its number of calls", function() { expect(foo.setBar.calls.length).toEqual(2); }); it("tracks all the arguments of its calls", function() { expect(foo.setBar).toHaveBeenCalledWith(123); expect(foo.setBar).toHaveBeenCalledWith(456, 'another param'); }); it("allows access to the most recent call", function() { expect(foo.setBar.mostRecentCall.args[0]).toEqual(456); }); it("allows access to other calls", function() { expect(foo.setBar.calls[0].args[0]).toEqual(123); }); it("stops all execution on a function", function() { expect(bar).toBeNull(); }); });
  • 16. describe("A spy, when faking a return value", function() { var foo, bar, fetchedBar; beforeEach(function() { andReturn foo = { setBar: function(value) { bar = value; }, getBar: function() { return bar; } }; spyOn(foo, 'getBar').andReturn(745); foo.setBar(123); fetchedBar = foo.getBar(); }); it("tracks that the spy was called", function() { expect(foo.getBar).toHaveBeenCalled(); }); it("should not effect other functions", function() { expect(bar).toEqual(123); }); it("when called returns the requested value", function() { expect(fetchedBar).toEqual(745); }); });
  • 17. Async tests describe("Asynchronous specs", function() { var value, flag; it("should support async execution of test preparation and exepectations", function() { runs(function() { flag = false; value = 0; setTimeout(function() { flag = true; }, 500); }); waitsFor(function() { value++; return flag; }, "The Value should be incremented", 750); runs(function() { expect(value).toBeGreaterThan(0); }); }); });
  • 20. Testing Backbone.js model describe "Todo", -> todo = null ajaxCall = (param) -> jQuery.ajax.mostRecentCall.args[0][param] beforeEach -> todo = new TodoApp.Todo todos = new TodoApp.TodoList [todo] it "should initialize with empty content", -> expect(todo.get "content").toEqual "empty todo..." it "should initialize as not done", -> expect(todo.get "done").toBeFalsy() it "should save after toggle", -> spyOn jQuery, "ajax" todo.toggle() expect(ajaxCall "url").toEqual "/todos" expect(todo.get "done").toBeTruthy()
  • 21. and collection describe "TodoList", -> attributes = [ content: "First" done: true , content: "Second" ] todos = null beforeEach -> todos = new TodoApp.TodoList attributes it "should return done todos", -> expect(_.invoke todos.done(), "toJSON").toEqual [attributes[0]] it "should return remaining todos", -> expect(_.invoke todos.remaining(), "toJSON").toEqual [attributes[1]]
  • 22. jasmine-jquery • a set of custom matchers for jQuery framework • an API for handling HTML, CSS, and JSON fixtures in your specs
  • 23. expect($('<div id="some-id"></div>')).toBe('div#some-id') expect($('<input type="checkbox" checked="checked"/>')).toBeChecked() expect($('<div style="display: none; margin: 10px;"></ div>')).toHaveCss({display: "none", margin: "10px"}) expect($('<option selected="selected"></option>')).toBeSelected() expect($('<div><span class="some-class"></span></ div>')).toContain('span.some-class') expect($('<div class="some-class"></div>')).toHaveClass("some-class") expect($('<div><span></span></div>')).toHaveHtml('<span></span>') expect($('<div><ul></ul><h1>header</h1></div>')).toContainHtml('<ul></ ul>') expect($('<div>some text</div>')).toHaveText('some text') expect($('<input type="text" value="some text"/>')).toHaveValue('some text') expect('<input type='submit' disabled='disabled'/>').toBeDisabled() expect($('<input type='text' />').focus()).toBeFocused()
  • 24. HTML fixtures In myfixture.html file: <div id="my-fixture">some complex content here</div> Inside your test: loadFixtures('myfixture.html'); $('#my-fixture').myTestedPlugin(); expect($('#my-fixture')).to...;
  • 25. jasmine-fixture // Let's say you want to write a Jasmine spec for some code // that needs to select elements from the DOM with jQuery: $('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]') // In the good ol' days of manually crafting your HTML fixtures, // you'd have to append some raw HTML to the DOM like this: beforeEach(function(){ $('<div id="toddler"><div class="hidden toy"><input name="toyName" value="cuddle bunny"></div></div>').appendTo('body'); }); afterEach(function(){ $('#toddler').remove() }); // But jasmine-fixture's affix method lets you do this instead: beforeEach(function(){ affix('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]') });
  • 26. jasmine-given describe("assigning stuff to this", function() { Given(function() { this.number = 24; }); Given(function() { this.number++; }); When(function() { this.number *= 2; }); Then(function() { return this.number === 50; }); // or Then(function() { expect(this.number).toBe(50) }); }); describe("assigning stuff to variables", function() { var subject; Given(function() { subject = []; }); When(function() { subject.push('foo'); }); Then(function() { return subject.length === 1; }); // or Then(function() { expect(subject.length).toBe(1); }); });
  • 27. jasmine-given describe "assigning stuff to this", -> Given -> @number = 24 Given -> @number++ When -> @number *= 2 Then -> @number == 50 # or Then -> expect(@number).toBe(50) describe "assigning stuff to variables", -> subject=null Given -> subject = [] When -> subject.push('foo') Then -> subject.length == 1 # or Then -> expect(subject.length).toBe(1)
  • 28. jasmine-stealth describe("multiple stubbings", function() { var someSpy; beforeEach(function() { someSpy = jasmine.createSpy(); someSpy.when("pirate", { booty: ["jewels",jasmine.any(String)]}).thenReturn("argh!"); someSpy.when("panda",1).thenReturn("sad"); }); it("stubs the first accurately", function() { expect(someSpy("pirate",{ booty: ["jewels","coins"]})).toBe("argh!"); }); it("stubs the second too", function() { expect(someSpy("panda",1)).toBe("sad"); }); it("doesn't return anything when a stubbing isn't satisfied",function(){ expect(someSpy("anything else at all")).not.toBeDefined(); }); });
  • 29. References http://pivotal.github.io/jasmine/ http://searls.testdouble.com/posts/2013-03-21- jasmine-tactics-screencast.html https://github.com/rsim/backbone_coffeescript_demo https://github.com/rsim/rpn_calculator http://vimeo.com/53655205