Automated Testing in JavaScript

Dbfa12cd7e1ff8b06a588609369d6e49?s=47 高見龍
December 22, 2011

Automated Testing in JavaScript

@WebDev Party #1

Dbfa12cd7e1ff8b06a588609369d6e49?s=128

高見龍

December 22, 2011
Tweet

Transcript

  1. photo by quaziefoto Auomaed Testing in JavaScript ৷ԈᎲ @WebDev Party

    #1
  2. None
  3. You can get this slide on www.eddie.com.tw/slides

  4. a.k.a Eddie or Aquarianboy Live and work in Taipei, Taiwan.

    Serving in my own little tiny company. Flash / AS3 / Ruby / Rails / Python programming for living. A little bit Objective-C for personal inerests. Technical Education and Consulant. PTT Flash BM (since 2007/4). Adobe Certificaed Flash Developer (Since 2006/7). Linux Professional Institue Certification (Since 2005/3). ৷ԈᎲ photo by Eddie
  5. anyone do est?

  6. people don’t est..

  7. In your company, who does these ests?

  8. does they really know how o do est?

  9. not just launch a browser, and click.. click.. click..

  10. how do you developers est?

  11. Sep1: Wrie some code!

  12. Sep 2: Ctrl + S = Save!

  13. Sep 3: Alt + Tab

  14. Sep 4: F5

  15. Sep 5: and.. repeat the Sep 1

  16. Browser plugins or console!

  17. LiveReload!

  18. Selenium

  19. What’s Auomaed Testing?

  20. Auomaed esting means that ests are run every single time

    a file is saved.
  21. Test Level 1: by eyes, hands, and your instinct.

  22. Test Level 2: ALERT, or Console.log()

  23. Test Level 3: Test Runner

  24. Test Level 4: Test Framework

  25. Test Level 5: Test Framework + Auomaed Testing Tools

  26. Why est?

  27. Cross-browser issues !! some browsers just don’t die.

  28. less bugs == you have more time developing new features.

  29. Why est JavaScript? cause JS is popular now, and it’s

    getting more and more complicaed.
  30. Why est JavaScript auomatically? cause we’re Lazzzzzzzzzzzy!!

  31. What’s Unit Test?

  32. Unit est is a piece of code that ests a

    piece of production code. so, unit est might be also Buggy!
  33. a good unit est should be short and focus on

    a single behavior of a function/method.
  34. the heart of a unit est is the assertion.

  35. How can code be esable?

  36. Not every code can be easily esed.

  37. TDD

  38. Twiter-Driven Development

  39. Test-Driven Development

  40. Test-first development is hard — it’s hard because it forward-shifts

    your confusion.
  41. Test != Debug

  42. xUnit

  43. Test should be fast, and easy o run repeaedly.

  44. est case, est suie, est runner

  45. Spy, Stub, and Mock FAKE!! something not REALLY!

  46. spy “Spies are functions that keep track of how and

    ofen they were called, and what values were returned.” This is useful in asynchronous and event- driven applications.
  47. Sinon.js it "check if 'strip_tag' method was triggered", -> spy

    = sinon.spy() namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' namecard.bind 'strip_tag', spy namecard.trigger 'strip_tag' # Expect the spy was called at least once expect(spy.called).toBeTruthy()
  48. Sinon.js it "check if 'strip_tag' method was triggered", -> spy

    = sinon.spy() namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' namecard.bind 'strip_tag', spy namecard.trigger 'strip_tag' # Expect the spy was called at least once expect(spy.called).toBeTruthy()
  49. Sinon.js it "check if 'strip_tag' method was triggered", -> spy

    = sinon.spy() namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' namecard.bind 'strip_tag', spy namecard.trigger 'strip_tag' # Expect the spy was called at least once expect(spy.called).toBeTruthy()
  50. Sinon.js it "check if 'strip_tag' method was triggered", -> spy

    = sinon.spy() namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' namecard.bind 'strip_tag', spy namecard.trigger 'strip_tag' # Expect the spy was called at least once expect(spy.called).toBeTruthy()
  51. Sinon.js it "check if 'strip_tag' method was triggered", -> spy

    = sinon.spy() namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' namecard.bind 'strip_tag', spy namecard.trigger 'strip_tag' # Expect the spy was called at least once expect(spy.called).toBeTruthy()
  52. Sinon.js it "check if ajax method was triggered while saving",

    -> namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' spy = sinon.spy jQuery, 'ajax' namecard.save(); # check Spy was called expect(spy).toHaveBeenCalled() # Check url property of first argument expect(spy.getCall(0).args[0].url).toEqual "/namecard/1"
  53. Sinon.js it "check if ajax method was triggered while saving",

    -> namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' spy = sinon.spy jQuery, 'ajax' namecard.save(); # check Spy was called expect(spy).toHaveBeenCalled() # Check url property of first argument expect(spy.getCall(0).args[0].url).toEqual "/namecard/1"
  54. Sinon.js it "check if ajax method was triggered while saving",

    -> namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' spy = sinon.spy jQuery, 'ajax' namecard.save(); # check Spy was called expect(spy).toHaveBeenCalled() # Check url property of first argument expect(spy.getCall(0).args[0].url).toEqual "/namecard/1"
  55. Sinon.js it "check if ajax method was triggered while saving",

    -> namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' spy = sinon.spy jQuery, 'ajax' namecard.save(); # check Spy was called expect(spy).toHaveBeenCalled() # Check url property of first argument expect(spy.getCall(0).args[0].url).toEqual "/namecard/1"
  56. Sinon.js it "check if ajax method was triggered while saving",

    -> namecard = new app.NameCard name: 'eddie' tel: '0928617687' address: 'Taipei, Taiwan' spy = sinon.spy jQuery, 'ajax' namecard.save(); # check Spy was called expect(spy).toHaveBeenCalled() # Check url property of first argument expect(spy.getCall(0).args[0].url).toEqual "/namecard/1"
  57. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  58. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  59. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  60. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  61. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  62. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  63. Sinon.js it "check if ajax method was triggered while saving",

    -> server = sinon.fakeServer.create() spy = sinon.spy() server.respondWith("GET", "/namecard/1", [200, {"Content-Type": "application/json"}, '{"id":1,"name":"eddie", "tel":"0928617687""}']); namecard = new NameCard({id: 1}) namecard.bind 'change', spy namecard.fetch() server.respond() # Expect that the spy was called with the new model expect(spy.called).toBeTruthy() expect(spy.getCall(0).args[0].attributes).toEqual id: 1 name: "eddie" name: "0928617687" server.restore()
  64. Demo

  65. Demo Browser Console

  66. Demo QUnit

  67. Demo Zombie.js with Node.js

  68. None
  69. None
  70. Demo Jasmine in Ruby on Rails 3.1

  71. Demo Jasmine + Guard + Phanom.js in Ruby on Rails

    3.1
  72. Conclusions

  73. Writing ests is an investment.

  74. not all ests are good!

  75. If you wrie bad ests, you might find that you

    gain none of the benefits, and insead are stuck with a bunch of ests that are time-consuming and hard o mainain.
  76. In est-driven development ests are writen as specification before writing

    production.
  77. Proper est-driven development ensures that a sysem will never conain

    code that is not being execued.
  78. TDD will not auomatically make great designs.

  79. TDD requires us o think about the results before providing

    the solution.
  80. Don’t fear hard-coding!

  81. Unit Test = You Need Test!

  82. Just give it a try!

  83. Any Question? photo by jamuraa

  84. ৷ԈᎲ Conacts photo by Eddie Websie Blog Plurk Facebook Google

    Plus Twiter Email Mobile http://www.eddie.com.tw http://blog.eddie.com.tw http://www.plurk.com/aquarianboy http://www.facebook.com/eddiekao http://www.eddie.com.tw/+ https://twiter.com/#!/eddiekao eddie@digik.com.tw +886-928-617-687