際際滷

際際滷Share a Scribd company logo
Javascript Specs
  with Jasmine
  A Primer for Rubyists
Why Test Javascript?
Seems like a


lot of work
    just for some lousy

regression tests...
Enforces Good Design

Object Oriented-er
 Modular and Namespaced
 Flexible, Updatable, Reusable
Focus and Process

   Driven by Business
    Requirements
   Red, Green, Refactor
 Know When Youre Done
Free Documentation

Legible Output
 Expresses Object Behavior
 Get Devs Up to Speed
Oh yeah...
     plus you get a
regression test suite
Why Use Jasmine?
Friends with RSpec
Very Similar Syntax
 BDD Approach
 Continuous Integration
 Borrows Directory Structure
 Generative Fixture Support
Pals with Ruby / Rails


$ gem install jasmine
$ script/generate jasmine
$ rake jasmine
Jasmine / RSpec
  Comparisons
   Lets get cookin...
Spec Suites
describe Cook do
  describe baking a pie do
    # ...
  end
end
                                    RSpec


describe(Cook, function() {
  describe(baking pie, function() {
    // ...
  });
});
                                  Jasmine
Before / After
before(:each) do
  @pie = Pie.new
end

after(:each) { @pie.cleanup }
                                    RSpec

                                  Jasmine
var pie;
beforeEach(function(){
  pie = new Pie();
});
afterEach(function() {pie.cleanup()});
Before All / After All
before(:all) { setup_code }
after(:all) { cleanup_code }
describe something do
  # ... tests here
end
                                      RSpec



setupCode();
describe(something, function() {
  // ... tests here
});
cleanupCode();
                                     Jasmine
Examples / Expectations
it should be tasty do
  pie = Pie.new
  pie.should be_tasty
end
                                      RSpec


it(should be tasty, function() {
  var pie = new Pie();
  expect(pie).toBeTasty();
});
                                     Jasmine
Negative Expectations
it should not be burned do
  pie = Pie.new
  pie.bake!
  pie.should_not be_burned
end
                                    RSpec


it(should not be burned, function(){
  var pie = new Pie();
  pie.bake();
  expect(pie).not.toBeBurned();
});
                                  Jasmine
Custom Matchers
Spec::Matchers.define :be_burned do
  match do |actual|
    actual.color == black
  end
end
                                         RSpec


beforeEach(function() {
  this.addMatchers({
    toBeBurned: function() {
      return this.actual.color == black;
    }
  });
});
                                       Jasmine
Stubbing Values
it should cook until 160 degrees do
  pie = Pie.new
  pie.stub!(:temperature).and_return(160)
  pie.done_baking?.should be_true
end
                                              RSpec



it(should cook until 160 degrees, function() {
  var pie = new Pie();
  spyOn(pie, temperature).andReturn(160);
  expect(pie.doneBaking()).toBeTruthy();
});
                                            Jasmine
Message Expectations
it should bake a pie for dinner do
  cook = Cook.new
  cook.should_receive(:bake_a_pie!)
  cook.make_dinner!
end
                                             RSpec


it(should bake a pie, function() {
  var cook = new Cook();
  spyOn(cook, bakePie);
  cook.makeDinner();
  expect(cook.bakePie).toHaveBeenCalled();
});
                                         Jasmine
Expectations w/ Args
it should bake a TASTY pie do
  cook = Cook.new
  cook.should_receive(:bake_a_pie!).with(TASTY)
  cook.make_dinner!
end
                                              RSpec


it(should bake a TASTY pie, function() {
  var cook = new Cook();
  spyOn(cook, bakePie);
  cook.makeDinner();
  expect(cook.bakePie)
    .toHaveBeenCalledWith(TASTY);
});
                                             Jasmine
Stub Call-Through

            RSpec
it(should bake a TASTY pie, function() {
  var cook = new Cook();
  spyOn(cook, bakePie).andCallThrough();
  cook.makeDinner();
  expect(cook.bakePie)
    .toHaveBeenCalledWith(TASTY);
});
                                             Jasmine
Number of Times
it should check the pie twice do
  cook = Cook.new
  cook.should_receive(:check_the_pie).twice
  cook.bake_a_pie!
end
                                               RSpec



it(should check the pie twice, function() {
  var cook = new Cook();
  spyOn(cook, checkThePie);
  cook.bakePie();
  expect(cook.checkThePie.callCount).toEqual(2);
});
                                              Jasmine
Error Expectations
it should refuse to bake a pie do
  cook = Cook.new(cranky)
  lambda do
    cook.bake_a_pie!
  end.should raise_error(MakeYourOwnDamnPie)
end
                                                 RSpec



it(should refuse to bake a pie, function() {
  var cook = new Cook(cranky);
  var msg = Make Your Own Damn Pie!;
  expect(cook.bakePie).toThrow(msg);
});
                                               Jasmine
Simulating Errors
it should catch errs & retry with sudo do
  cook = Cook.new
  cook.stub!(:bake_a_pie!).
       and_raise(MakeYourOwnDamnPie)
  cook.should_receive(:sudo_bake_a_pie!)
  cook.make_dinner!
end
                                        RSpec
Simulating Errors
it(should retry with sudo, function() {
  var cook = new Cook();
  spyOn(cook, bakePie)
    .andThrow(Make Your Own Damn Pie!);
  spyOn(cook, sudoBakePie);
  expect(cook.sudoBakePie).toHaveBeenCalled();
});
                                         Jasmine
Well now that Im

HUNGRY
lets write some code...

More Related Content

Jasmine

  • 1. Javascript Specs with Jasmine A Primer for Rubyists
  • 3. Seems like a lot of work just for some lousy regression tests...
  • 4. Enforces Good Design Object Oriented-er Modular and Namespaced Flexible, Updatable, Reusable
  • 5. Focus and Process Driven by Business Requirements Red, Green, Refactor Know When Youre Done
  • 6. Free Documentation Legible Output Expresses Object Behavior Get Devs Up to Speed
  • 7. Oh yeah... plus you get a regression test suite
  • 9. Friends with RSpec Very Similar Syntax BDD Approach Continuous Integration Borrows Directory Structure Generative Fixture Support
  • 10. Pals with Ruby / Rails $ gem install jasmine $ script/generate jasmine $ rake jasmine
  • 11. Jasmine / RSpec Comparisons Lets get cookin...
  • 12. Spec Suites describe Cook do describe baking a pie do # ... end end RSpec describe(Cook, function() { describe(baking pie, function() { // ... }); }); Jasmine
  • 13. Before / After before(:each) do @pie = Pie.new end after(:each) { @pie.cleanup } RSpec Jasmine var pie; beforeEach(function(){ pie = new Pie(); }); afterEach(function() {pie.cleanup()});
  • 14. Before All / After All before(:all) { setup_code } after(:all) { cleanup_code } describe something do # ... tests here end RSpec setupCode(); describe(something, function() { // ... tests here }); cleanupCode(); Jasmine
  • 15. Examples / Expectations it should be tasty do pie = Pie.new pie.should be_tasty end RSpec it(should be tasty, function() { var pie = new Pie(); expect(pie).toBeTasty(); }); Jasmine
  • 16. Negative Expectations it should not be burned do pie = Pie.new pie.bake! pie.should_not be_burned end RSpec it(should not be burned, function(){ var pie = new Pie(); pie.bake(); expect(pie).not.toBeBurned(); }); Jasmine
  • 17. Custom Matchers Spec::Matchers.define :be_burned do match do |actual| actual.color == black end end RSpec beforeEach(function() { this.addMatchers({ toBeBurned: function() { return this.actual.color == black; } }); }); Jasmine
  • 18. Stubbing Values it should cook until 160 degrees do pie = Pie.new pie.stub!(:temperature).and_return(160) pie.done_baking?.should be_true end RSpec it(should cook until 160 degrees, function() { var pie = new Pie(); spyOn(pie, temperature).andReturn(160); expect(pie.doneBaking()).toBeTruthy(); }); Jasmine
  • 19. Message Expectations it should bake a pie for dinner do cook = Cook.new cook.should_receive(:bake_a_pie!) cook.make_dinner! end RSpec it(should bake a pie, function() { var cook = new Cook(); spyOn(cook, bakePie); cook.makeDinner(); expect(cook.bakePie).toHaveBeenCalled(); }); Jasmine
  • 20. Expectations w/ Args it should bake a TASTY pie do cook = Cook.new cook.should_receive(:bake_a_pie!).with(TASTY) cook.make_dinner! end RSpec it(should bake a TASTY pie, function() { var cook = new Cook(); spyOn(cook, bakePie); cook.makeDinner(); expect(cook.bakePie) .toHaveBeenCalledWith(TASTY); }); Jasmine
  • 21. Stub Call-Through RSpec it(should bake a TASTY pie, function() { var cook = new Cook(); spyOn(cook, bakePie).andCallThrough(); cook.makeDinner(); expect(cook.bakePie) .toHaveBeenCalledWith(TASTY); }); Jasmine
  • 22. Number of Times it should check the pie twice do cook = Cook.new cook.should_receive(:check_the_pie).twice cook.bake_a_pie! end RSpec it(should check the pie twice, function() { var cook = new Cook(); spyOn(cook, checkThePie); cook.bakePie(); expect(cook.checkThePie.callCount).toEqual(2); }); Jasmine
  • 23. Error Expectations it should refuse to bake a pie do cook = Cook.new(cranky) lambda do cook.bake_a_pie! end.should raise_error(MakeYourOwnDamnPie) end RSpec it(should refuse to bake a pie, function() { var cook = new Cook(cranky); var msg = Make Your Own Damn Pie!; expect(cook.bakePie).toThrow(msg); }); Jasmine
  • 24. Simulating Errors it should catch errs & retry with sudo do cook = Cook.new cook.stub!(:bake_a_pie!). and_raise(MakeYourOwnDamnPie) cook.should_receive(:sudo_bake_a_pie!) cook.make_dinner! end RSpec
  • 25. Simulating Errors it(should retry with sudo, function() { var cook = new Cook(); spyOn(cook, bakePie) .andThrow(Make Your Own Damn Pie!); spyOn(cook, sudoBakePie); expect(cook.sudoBakePie).toHaveBeenCalled(); }); Jasmine
  • 26. Well now that Im HUNGRY lets write some code...

Editor's Notes