* 
*  * Who Am I? * State of the Room? * Ways to test Javascript? * Different Testing Environments? * Overview of Testing Tools * Using Testing in your Workflow * Spaghetti Javascript * Refactor Spaghetti into Testable Javascript * Installing Jasmine + Live Demo
*  * Gavin Pickin – developing Web Apps since late 90s * What else do you need to know? * Blog - http://www.gpickin.com * Twitter – http://twitter.com/gpickin * Github - https://github.com/gpickin * Lets get on with the show.
*  * A few questions for you guys * If you have arms, use them.
*  * Click around in the browser yourself * Setup Selenium / Web Driver to click around for you * Structured Programmatic Tests
*  * Black/White Box * Unit Testing * Integration Testing * Functional Tests * System Tests * End to End Tests * Sanity Testing * Regression Test * Acceptance Tests * Load Testing * Stress Test * Performance Tests * Usability Tests * + More
*  * Integration Tests several of the pieces together * Most of the types of tests are variations of an Integration Test * Can include mocks but can full end to end tests including DB / APIs
*  “unit testing is a software verification and validation method in which a programmer tests if individual units of source code are fit for use. A unit is the smallest testable part of an application” - wikipedia
*  * Can improve code quality -> quick error discovery * Code confidence via immediate verification * Can expose high coupling * Will encourage refactoring to produce > testable code * Remember: Testing is all about behavior and expectations
*  * TDD = Test Driven Development * Write Tests * Run them and they Fail * Write Functions to Fulfill the Tests * Tests should pass * Refactor in confidence * Test focus on Functionality
*  * BDD = Behavior Driven Development Actually similar to TDD except: * Focuses on Behavior and Specifications * Specs (tests) are fluent and readable * Readability makes them great for all levels of testing in the organization * Hard to find TDD examples in JS that are not using BDD describe and it blocks
*  Test( ‘Email address must not be blank’, function(){ notEqual(email, “”, "failed"); });
*  Describe( ‘Email Address’, function(){ It(‘should not be blank’, function(){ expect(email).not.toBe(“”); }); });
*  expect(true).toBe(true); expect(true).toBe(true); expect(true).toBe(true); expect(true).toBe(true);
*  expect(true).not.toBe(true); expect(true).not.toBe(true); expect(true).not.toBe(true); expect(true).not.toBe(true); expect(true).not.toBe(true);
*  expect(true).toBe(true); expect(a).not.toBe(null); expect(a).toEqual(12); expect(message).toMatch(/bar/); expect(message).toMatch("bar"); expect(message).not.toMatch(/quux/); expect(a.foo).toBeDefined(); expect(a.bar).not.toBeDefined();
*  NodeJS - CLI In the Browser
*  * There are a few choices
*  * Jasmine, Mocha and QUnit
*  * Jasmine comes ready to go out of the box * Fluent Syntax – BDD Style * Includes lots of matchers * Has spies included * Very popular, lots of support * Angular uses Jasmine with Karma (CLI) * Headless running and plays well with CI servers
*  * Async testing in 1.3 can be a headache * Expects *spec.js suffix for test files * This can be modified depending on how you are running the tests
*  describe("Hello world function", function() { it(”contains the word world", function() { expect(helloWorld()).toContain("world"); }); });
*  * Simple Setup * Simple Async testing * Works great with other Assertion libraries like Chai ( not included ) * Solid Support with CI Servers, with Plugins for others * Opinion says Mocha blazing the trail for new features
*  * Requires other Libraries for key features * No Assertion Library included * No Mocking / Spied included * Need to create the runner manually * Newer to the game so not as popular or supported as others but gaining traction.
*  var expect = require('chai').expect; describe(’Hello World Function', function(){ it('should contain the word world', function(){ expect(helloWorld()).to.contain(’world'); }) })
*  * The oldest of the main testing frameworks * Is popular due to use in jQuery and age * Ember’s default Unit testing Framework
*  * Development slowed down since 2013 (but still under development) * Syntax – No BDD style * Assertion libraries – limited matchers
*  QUnit.test( "ok test", function( assert ) { assert.ok( true, "true succeeds" ); assert.ok( "non-empty", "non-empty string succeeds" ); assert.ok( false, "false fails" ); assert.ok( 0, "0 fails" ); assert.ok( NaN, "NaN fails" ); assert.ok( "", "empty string fails" ); assert.ok( null, "null fails" ); assert.ok( undefined, "undefined fails" ); });
*  Photo Credit – Kombination http://www.kombination.co.za/wp-content/uploads/2012/10/baby_w_spaghetti_mess_4987941.jpg
* 
* 
*  * Things to refactor to make your code testable * Code should not be one big chunk of Javascript in onReady() * Deep nested callbacks & Anon functions cannot easily be singled out and tested * Remove Tight Coupling – DOM access for example
*  * Lets look at some code * This isn’t BEST PRACTICE, its BETTER PRACTICE than you were doing * Its not really refactoring if you don’t have tests, its “moving code and asking for trouble”
*  var personObjLit = { ssn: ’xxxxxxxx', age: '35', name: 'Gavin Pickin', getAge: function(){ return this.age; }, getName: function() { return this.name; } };
*  var personObjLit2 = function() { ssn = ’xxxxxxx'; age = '35'; name = 'Gavin Pickin’; return { getAge: function(){ return age; }, getName: function() { return name; } }; };
*  * Using HTML Test Runners * Keep a Browser open * F5 refresh tests
*  * Run Jasmine – manual * Run tests at the end of each section of work * Run Grunt-Watch – automatic * Runs Jasmine on every file change * Grunt can run other tasks as well, minification etc
*  * Browser Views * Eclipse allows you to open files in web view – uses HTML Runner * Run Jasmine / Grunt / Karma in IDE Console * Easy to setup – See Demo– Sublime Text 2
*  * Install / Run Jasmine Standalone for Browser * Install / Run Jasmine with NodeJs * Install/ Run Jasmine with Grunt Watch * Install / Run Grunt Watch inside Sublime Text 2
*  Download standalone package from Github (I have 2.1.3) https://github.com/jasmine/jasmine/tree/master/dist Unzip into your /tests folder Run /tests/SpecRunner.html to see example tests
* 
* 
*  <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Jasmine Spec Runner v2.1.3</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.1.3/jasmine_favicon.png"> <link rel="stylesheet" href="lib/jasmine-2.1.3/jasmine.css”> <script src="lib/jasmine-2.1.3/jasmine.js"></script> <script src="lib/jasmine-2.1.3/jasmine-html.js"></script> <script src="lib/jasmine-2.1.3/boot.js"></script> <!-- include source files here... --> <script src="../js/services/loginService.js"></script> <!-- include spec files here... --> <script src="spec/loginServiceSpec.js"></script> </head> <body> </body> </html>
*  Assuming you have NodeJs Installed… install Jasmine $ npm install jasmine jasmine@2.2.1 node_modules/jasmine ├── exit@0.1.2 ├── jasmine-core@2.2.0 └── glob@3.2.11 (inherits@2.0.1, minimatch@0.3.0)
*  Once Jasmine is installed in your project $ Jasmine init
*  Edit Jasmine.json to update Locations for Spec Files and Helper Files { "spec_dir": "spec", "spec_files": [ "**/*[sS]pec.js" ], "helpers": [ "helpers/**/*.js" ] }
*  $ Jasmine Started F Failures: 1) A suite contains spec with an expectation Message: Expected true to be false. Stack: Error: Expected true to be false. at Object.<anonymous> (/Users/gavinpickin/Dropbox/Apps/ testApp/www/spec/test_spec.js:3:18) 1 spec, 1 failure Finished in 0.009 seconds
*  * Jasmine-Node is great for Node * Jasmine Node doesn’t have a headless browser * Hard to test Browser code * So what should I use?
*  * Install Grunt npm install grunt * Install Grunt – Jasmine npm install grunt-contrib-jasmine * Install Grunt – Watch npm install grunt-contrib-watch * Note: On Mac, I also needed to install Grunt CLI npm install –g grunt-cli
*  // gruntfile.js - https://gist.github.com/gpickin/1e1e7902d1d3676d23c5 module.exports = function (grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('node_modules/grunt/package.json'), jasmine: { all: { src: ['js/*.js' ], options: { //'vendor': ['path/to/vendor/libs/*.js'], 'specs': ['specs/*.js' ] } } },
*  // gruntfile.js part 2 watch: { js: { files: [ 'js/*.js', 'specs/*.js', ], tasks: ['jasmine:all'] } } });
*  // gruntfile.js part 3 grunt.loadNpmTasks('grunt-contrib-jasmine'); grunt.loadNpmTasks('grunt-contrib-watch'); };
*  describe("A suite", function() { it("contains spec with an expectation", function() { expect(true).toBe(true); }); });
* 
* 
*  * Install PackageControl into Sublime Text * Install Grunt from PackageControl * https://packagecontrol.io/packages/Grunt * Update Grunt Sublime Settings for paths { "exec_args": { "path": "/bin:/usr/bin:/usr/local/bin” } } * Then Command Shift P – grunt
* 
*  * Any questions? * Come check out my Cordova Hooks session and see how you can run Unit Tests (and much more) whenever you’re preparing a build for your cordova app.

How do I write Testable Javascript?

  • 1.
  • 2.
    *  * Who Am I? * Stateof the Room? * Ways to test Javascript? * Different Testing Environments? * Overview of Testing Tools * Using Testing in your Workflow * Spaghetti Javascript * Refactor Spaghetti into Testable Javascript * Installing Jasmine + Live Demo
  • 3.
    *  * Gavin Pickin –developing Web Apps since late 90s * What else do you need to know? * Blog - http://www.gpickin.com * Twitter – http://twitter.com/gpickin * Github - https://github.com/gpickin * Lets get on with the show.
  • 4.
    *  * A few questionsfor you guys * If you have arms, use them.
  • 5.
    *  * Click around inthe browser yourself * Setup Selenium / Web Driver to click around for you * Structured Programmatic Tests
  • 6.
    *  * Black/White Box * Unit Testing * IntegrationTesting * Functional Tests * System Tests * End to End Tests * Sanity Testing * Regression Test * Acceptance Tests * Load Testing * Stress Test * Performance Tests * Usability Tests * + More
  • 7.
    *  * Integration Tests severalof the pieces together * Most of the types of tests are variations of an Integration Test * Can include mocks but can full end to end tests including DB / APIs
  • 8.
    *  “unit testing isa software verification and validation method in which a programmer tests if individual units of source code are fit for use. A unit is the smallest testable part of an application” - wikipedia
  • 9.
    *  * Can improve codequality -> quick error discovery * Code confidence via immediate verification * Can expose high coupling * Will encourage refactoring to produce > testable code * Remember: Testing is all about behavior and expectations
  • 10.
    *  * TDD = TestDriven Development * Write Tests * Run them and they Fail * Write Functions to Fulfill the Tests * Tests should pass * Refactor in confidence * Test focus on Functionality
  • 11.
    *  * BDD = BehaviorDriven Development Actually similar to TDD except: * Focuses on Behavior and Specifications * Specs (tests) are fluent and readable * Readability makes them great for all levels of testing in the organization * Hard to find TDD examples in JS that are not using BDD describe and it blocks
  • 12.
    *  Test( ‘Email addressmust not be blank’, function(){ notEqual(email, “”, "failed"); });
  • 13.
    *  Describe( ‘Email Address’, function(){ It(‘shouldnot be blank’, function(){ expect(email).not.toBe(“”); }); });
  • 14.
  • 15.
  • 16.
  • 17.
    *  NodeJS - CLIIn the Browser
  • 18.
  • 19.
  • 20.
    *  * Jasmine comes readyto go out of the box * Fluent Syntax – BDD Style * Includes lots of matchers * Has spies included * Very popular, lots of support * Angular uses Jasmine with Karma (CLI) * Headless running and plays well with CI servers
  • 21.
    *  * Async testing in1.3 can be a headache * Expects *spec.js suffix for test files * This can be modified depending on how you are running the tests
  • 22.
    *  describe("Hello world function",function() { it(”contains the word world", function() { expect(helloWorld()).toContain("world"); }); });
  • 23.
    *  * Simple Setup * Simple Asynctesting * Works great with other Assertion libraries like Chai ( not included ) * Solid Support with CI Servers, with Plugins for others * Opinion says Mocha blazing the trail for new features
  • 24.
    *  * Requires other Librariesfor key features * No Assertion Library included * No Mocking / Spied included * Need to create the runner manually * Newer to the game so not as popular or supported as others but gaining traction.
  • 25.
    *  var expect =require('chai').expect; describe(’Hello World Function', function(){ it('should contain the word world', function(){ expect(helloWorld()).to.contain(’world'); }) })
  • 26.
    *  * The oldest ofthe main testing frameworks * Is popular due to use in jQuery and age * Ember’s default Unit testing Framework
  • 27.
    *  * Development slowed downsince 2013 (but still under development) * Syntax – No BDD style * Assertion libraries – limited matchers
  • 28.
    *  QUnit.test( "ok test",function( assert ) { assert.ok( true, "true succeeds" ); assert.ok( "non-empty", "non-empty string succeeds" ); assert.ok( false, "false fails" ); assert.ok( 0, "0 fails" ); assert.ok( NaN, "NaN fails" ); assert.ok( "", "empty string fails" ); assert.ok( null, "null fails" ); assert.ok( undefined, "undefined fails" ); });
  • 29.
    *  Photo Credit –Kombination http://www.kombination.co.za/wp-content/uploads/2012/10/baby_w_spaghetti_mess_4987941.jpg
  • 30.
  • 31.
  • 32.
    *  * Things to refactorto make your code testable * Code should not be one big chunk of Javascript in onReady() * Deep nested callbacks & Anon functions cannot easily be singled out and tested * Remove Tight Coupling – DOM access for example
  • 33.
    *  * Lets look atsome code * This isn’t BEST PRACTICE, its BETTER PRACTICE than you were doing * Its not really refactoring if you don’t have tests, its “moving code and asking for trouble”
  • 34.
    *  var personObjLit ={ ssn: ’xxxxxxxx', age: '35', name: 'Gavin Pickin', getAge: function(){ return this.age; }, getName: function() { return this.name; } };
  • 35.
    *  var personObjLit2 =function() { ssn = ’xxxxxxx'; age = '35'; name = 'Gavin Pickin’; return { getAge: function(){ return age; }, getName: function() { return name; } }; };
  • 36.
    *  * Using HTML TestRunners * Keep a Browser open * F5 refresh tests
  • 37.
    *  * Run Jasmine –manual * Run tests at the end of each section of work * Run Grunt-Watch – automatic * Runs Jasmine on every file change * Grunt can run other tasks as well, minification etc
  • 38.
    *  * Browser Views * Eclipse allowsyou to open files in web view – uses HTML Runner * Run Jasmine / Grunt / Karma in IDE Console * Easy to setup – See Demo– Sublime Text 2
  • 39.
    *  * Install / RunJasmine Standalone for Browser * Install / Run Jasmine with NodeJs * Install/ Run Jasmine with Grunt Watch * Install / Run Grunt Watch inside Sublime Text 2
  • 40.
    *  Download standalone packagefrom Github (I have 2.1.3) https://github.com/jasmine/jasmine/tree/master/dist Unzip into your /tests folder Run /tests/SpecRunner.html to see example tests
  • 41.
  • 42.
  • 43.
    *  <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JasmineSpec Runner v2.1.3</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.1.3/jasmine_favicon.png"> <link rel="stylesheet" href="lib/jasmine-2.1.3/jasmine.css”> <script src="lib/jasmine-2.1.3/jasmine.js"></script> <script src="lib/jasmine-2.1.3/jasmine-html.js"></script> <script src="lib/jasmine-2.1.3/boot.js"></script> <!-- include source files here... --> <script src="../js/services/loginService.js"></script> <!-- include spec files here... --> <script src="spec/loginServiceSpec.js"></script> </head> <body> </body> </html>
  • 44.
    *  Assuming you haveNodeJs Installed… install Jasmine $ npm install jasmine jasmine@2.2.1 node_modules/jasmine ├── exit@0.1.2 ├── jasmine-core@2.2.0 └── glob@3.2.11 (inherits@2.0.1, minimatch@0.3.0)
  • 45.
    *  Once Jasmine isinstalled in your project $ Jasmine init
  • 46.
    *  Edit Jasmine.json toupdate Locations for Spec Files and Helper Files { "spec_dir": "spec", "spec_files": [ "**/*[sS]pec.js" ], "helpers": [ "helpers/**/*.js" ] }
  • 47.
    *  $ Jasmine Started F Failures: 1) Asuite contains spec with an expectation Message: Expected true to be false. Stack: Error: Expected true to be false. at Object.<anonymous> (/Users/gavinpickin/Dropbox/Apps/ testApp/www/spec/test_spec.js:3:18) 1 spec, 1 failure Finished in 0.009 seconds
  • 48.
    *  * Jasmine-Node is greatfor Node * Jasmine Node doesn’t have a headless browser * Hard to test Browser code * So what should I use?
  • 49.
    *  * Install Grunt npm installgrunt * Install Grunt – Jasmine npm install grunt-contrib-jasmine * Install Grunt – Watch npm install grunt-contrib-watch * Note: On Mac, I also needed to install Grunt CLI npm install –g grunt-cli
  • 50.
    *  // gruntfile.js -https://gist.github.com/gpickin/1e1e7902d1d3676d23c5 module.exports = function (grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('node_modules/grunt/package.json'), jasmine: { all: { src: ['js/*.js' ], options: { //'vendor': ['path/to/vendor/libs/*.js'], 'specs': ['specs/*.js' ] } } },
  • 51.
    *  // gruntfile.js part2 watch: { js: { files: [ 'js/*.js', 'specs/*.js', ], tasks: ['jasmine:all'] } } });
  • 52.
    *  // gruntfile.js part3 grunt.loadNpmTasks('grunt-contrib-jasmine'); grunt.loadNpmTasks('grunt-contrib-watch'); };
  • 53.
    *  describe("A suite", function(){ it("contains spec with an expectation", function() { expect(true).toBe(true); }); });
  • 54.
  • 55.
  • 56.
    *  * Install PackageControl intoSublime Text * Install Grunt from PackageControl * https://packagecontrol.io/packages/Grunt * Update Grunt Sublime Settings for paths { "exec_args": { "path": "/bin:/usr/bin:/usr/local/bin” } } * Then Command Shift P – grunt
  • 57.
  • 58.
    *  * Any questions? * Come checkout my Cordova Hooks session and see how you can run Unit Tests (and much more) whenever you’re preparing a build for your cordova app.