Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
3 WAYS TO TEST YOUR
COLDFUSION API
Gavin Pickin
cf.Objective() 2017
Agenda
● Who Am I?
● State of the Room?
● CF API
● Ways to test your API?
● Overview of Testing Tools
● Using Testing in y...
Who am I?
Gavin Pickin – developing Web Apps since late 90s
● Software Consultant for Ortus Solutions
● ContentBox Evangel...
State of the Room
● A few questions for you guys
● If you have arms, use them.
APIs in CFML
Most CF Apps are moving towards providing an API for multiple consumers
CF has many REST API Solutions and ev...
Ways to Test your Code
● Click around in the browser yourself
● Setup Selenium / Web Driver to
click around for you
● Stru...
Types of Testing
● Black/White Box
● Unit Testing
● Integration Testing
● Functional Tests
● System Tests
● End to End Tes...
Integration Testing
● Integration Tests several of the pieces together
● Most of the types of tests are variations of an I...
Unit Testing
“unit testing is a software verification and validation method in
which a programmer tests if individual unit...
Unit Testing can...
● Can improve code quality -> quick error discovery
● Code confidence via immediate verification
● Can...
Styles – TDD vs BDD
● TDD = Test Driven Development
○ Write Tests
○ Run them and they Fail
○ Write Functions to Fulfill th...
Styles - TDD vs BDD
● BDD = Behavior Driven Development
Actually similar to TDD except:
● Focuses on Behavior and Specific...
TDD Example
Test( ‘Email address must not be blank’, function(){
notEqual(email, “”, "failed");
});
BDD Example
Describe( ‘Email Address’, function(){
It(‘should not be blank’, function(){
expect(email).not.toBe(“”);
});
}...
Matchers
expect(true).toBe(true);
expect(true).toBe(true);
expect(true).toBe(true);
expect(true).toBe(true);
Matchers
expect(true).not.toBe(true);
expect(true).not.toBe(true);
expect(true).not.toBe(true);
expect(true).not.toBe(true...
Matcher Samples
expect(true).toBe(true);
expect(a).not.toBe(null);
expect(a).toEqual(12);
expect(message).toMatch(/bar/);
...
Different Testing
Environments?
NodeJS - CLI In the Browser
CF Testing Tools
* MxUnit was the standard
* TestBox is the new standard
Other options
TestBox
TestBox is a next generation testing framework for ColdFusion
(CFML) that is based on BDD (Behavior Driven Develop...
TestBox TDD Example
function testHelloWorld(){
          $assert.includes( helloWorld(), ”world" );
     }
TestBox BDD Example
describe("Hello world function", function() {
it(”contains the word world", function() {
expect(helloW...
TestBox New BDD Example
feature( "Box Size", function(){
    describe( "In order to know what size box I need
            ...
JS Testing Tools
*There are a few choices
Main JS Testing Players
Jasmine, Mocha and QUnit
Jasmine
*Jasmine comes ready to go out of the box
*Fluent Syntax – BDD Style
*Includes lots of matchers
*Has spies include...
Jasmine - Cons
Async testing in 1.3 can be a headache
*Async testing in 2.0 is hard to find
blog posts on (I need to write...
Jasmine – Sample Test
describe("Hello world function", function() {
it(”contains the word world", function() {
expect(hell...
Mocha
*Simple Setup
*Simple Async testing
*Works great with other Assertion libraries like Chai ( not
included )
*Solid Su...
Mocha - Cons
*Requires other Libraries for key features
*No Assertion Library included
*No Mocking / Spied included
*Need ...
Mocha – BDD Sample Test
var expect = require('chai').expect;
describe(’Hello World Function', function(){
it('should conta...
QUnit
*The oldest of the main testing frameworks
*Is popular due to use in jQuery and age
*Ember’s default Unit testing Fr...
QUnit - Cons
*Development slowed down since
2013 (but still under development)
*Syntax – No BDD style
*Assertion libraries...
QUnit – Sample Test
QUnit.test( "ok test", function( assert ) {
assert.ok( true, "true succeeds" );
assert.ok( "non-empty"...
Spaghetti Javascript
Photo Credit – Kombination
http://www.kombination.co.za/wp-content/uploads/2012/10/baby_w_spaghetti_m...
Spaghetti Javascript Example
Spaghetti Javascript Example
Refactoring Spaghetti
*Things to refactor to make your code testable
*Code should not be one big chunk of Javascript in
on...
Refactoring Spaghetti
*Lets look at some code
*This isn’t BEST PRACTICE, its BETTER PRACTICE than
you were doing
*Its not ...
Object Literals
var personObjLit = {
ssn: ’xxxxxxxx',
age: '35',
name: 'Gavin Pickin',
getAge: function(){
return this.age...
Module Pattern
var personObjLit2 = function() {
ssn = ’xxxxxxx';
age = '35';
name = 'Gavin Pickin’;
return {
getAge: funct...
Using Testing in your Workflow
*Using HTML Test Runners
*Keep a Browser open
*F5 refresh tests
Command Line Tests
*Run Jasmine – manual
*Run tests at the end of each section of work
*Run Grunt-Watch – automatic
*Runs ...
Testing in your IDE
*Browser Views
*Eclipse allows you to open files in web view
– uses HTML Runner
*Run Jasmine / Grunt /...
Live Demo and Examples
*Install / Run Jasmine Standalone for Browser
*Install / Run Jasmine with NodeJs
*Install / Run Jas...
Install / Run Jasmine for In-Browser Testing
Download standalone package from Github (I have 2.1.3)
https://github.com/jas...
Standalone Jasmine
Installing Jasmine for in Browser Testing
http://www.testableapi.local.com:8504/tests/SpecRunner.html
SpecRunner Setup Jasmine Browser Test
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v2.1...
Installing Jasmine with NodeJS
Assuming you have NodeJs Installed… install Jasmine
$ npm install jasmine
jasmine@2.2.1 nod...
Installing Jasmine with NodeJS
Once Jasmine is installed in your project
$ Jasmine init
Installing Jasmine with NodeJS
Edit Jasmine.json to update Locations for Spec Files and Helper Files
{
"spec_dir": "spec",...
Running Jasmine Tests with NodeJS
$ Jasmine
Started
F
Failures:
1) A suite contains spec with an expectation
Message:
Expe...
Running Jasmine Tests with NodeJS
*Jasmine-Node is great for Node
*Jasmine Node doesn’t have a headless browser
*Hard to t...
Installing Jasmine with Grunt Watcher
*Install Grunt
npm install grunt
*Install Grunt – Jasmine
npm install grunt-contrib-...
Configuring Jasmine with Grunt Watcher
// gruntfile.js - https://gist.github.com/gpickin/1e1e7902d1d3676d23c5
module.expor...
Configuring Jasmine with Grunt Watcher
// gruntfile.js part 2
watch: {
js: {
files: [
'js/*.js',
'specs/*.js',
],
tasks: [...
Configuring Jasmine with Grunt Watcher
// gruntfile.js part 3
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTa...
Example Jasmine Spec with Grunt Watcher
describe("Forgotten Password Form", function() {
it("should warn you if the email ...
Example Jasmine Spec with Grunt Watcher
describe("Login Form", function() {
it("should set status correct status message w...
Example Jasmine Spec with Grunt Watcher
describe("Login API", function() {
it("should return a failing Ajax Response", fun...
Whats wrong with that?
describe("Login API", function() {
it("should return a failing Ajax Response", function() {
spyOn( ...
Unit Tests and Async Calls
*You want Unit Tests to test the unit and not it’s
dependencies
*You want Unit Tests to run qui...
How to wait for Async
describe("Login API", function() {
beforeEach(function( done ) {
spyOn( window, "processLoginAjaxDon...
How to wait for Async
describe("Login API", function() {
beforeEach(function( done ) {
…
});
it("should return a failing A...
Running Jasmine with Grunt Watcher
Running Jasmine with Grunt Watcher
Installing Testbox
*Install Testbox – Easy Thanks to Commandbox
*box install testbox
*Next, decide how you want to run Tes...
Create a runner.cfm
*<cfsetting showDebugOutput="false">
*<!--- Executes all tests in the 'specs' folder with simple repor...
Create a Test Suite
// tests/specs/CFCTest.cfc
component extends="testbox.system.BaseSpec" {
function run() {
it( "will er...
Create a 2nd
Test Suite
// tests/specs/APITest.cfc
component extends="testbox.system.BaseSpec" {
function run() {
describe...
Running Testbox with runner.cfm
Running Testbox with Grunt Watch
*Install Testbox Runner – Thanks Sean Coyne
*npm install testbox-runner
*Install Grunt Sh...
Adding TextBox Config 1
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-shell');
grunt.initConfig({ … })
}
Adding TextBox Config 2
Watch: {
…
cfml: {
files: [ "cfcs/*.cfc"],
tasks: [ "testbox" ]
}
}
Adding TextBox Config 3
shell: {
testbox: {
command:
"./node_modules/testbox-runner/index.js
--colors --runner
http://www....
Adding TextBox Config 4
grunt.registerTask("testbox", [ "shell:testbox" ]);
grunt.loadNpmTasks('grunt-contrib-jasmine');
g...
Adding TextBox Config 5
js: {
files: [
'js/*.js',
'specs/*.js',
"cfcs/*.cfc”
],
tasks: ['jasmine:all']
},
GruntFile.js Gists
Jasmine
https://gist.github.com/gpickin/1e1e7902d1d36
76d23c5
Jasmine + Testbox
https://gist.github.com...
Testbox output with Grunt
Testbox Runner JSON
*Testbox has several runners, you have seen the HTML one, this
Runner uses the JSON runner and then fo...
Running in Sublime Text 2
*Install PackageControl into Sublime Text
*Install Grunt from PackageControl
*https://packagecon...
Running in Sublime Text 2
3 WAYS TO TEST YOUR COLDFUSION API -
3 WAYS TO TEST YOUR COLDFUSION API -
3 WAYS TO TEST YOUR COLDFUSION API -
Upcoming SlideShare
Loading in …5
×

3 WAYS TO TEST YOUR COLDFUSION API -

266 views

Published on

Most projects in CF now involve creating some type of consumable CFC Endpoint or API Service... do you Unit test your API, do you use Integration Tests on your API? How many ways do you test your API? Not all tests are created equal.

We build our CFCs and CF API to be consumed with CF Apps, Mobile Apps, Javascript apps and devices we haven’t even thought about yet. To be smart developers we need to be able to test our CFC endpoints, and the code that uses those endpoints.

We’ll learn how to test your API serverside with Testbox and Clientside with Jasmine.
With Testbox and Jasmine both using BDD, your test code can almost be isomorphic.

Attendees should have some exposure to CFCs as endpoints, or CF API creations, and consuming with other languages/devices, in this case, JavaScript.

Attendees will learn

How to use Testbox to test your CFCs 2 different ways
Different types and ways to test JavaScript
Overview of client/server side testing tools
Building testing into your workflow
You are one of many that are not testing your APIs thoroughly

Published in: Technology
  • Be the first to comment

3 WAYS TO TEST YOUR COLDFUSION API -

  1. 1. 3 WAYS TO TEST YOUR COLDFUSION API Gavin Pickin cf.Objective() 2017
  2. 2. Agenda ● Who Am I? ● State of the Room? ● CF API ● Ways to test your API? ● Overview of Testing Tools ● Using Testing in your Workflow ● Installing Jasmine ● Installing Testbox ● Live Demo
  3. 3. Who am I? Gavin Pickin – developing Web Apps since late 90s ● Software Consultant for Ortus Solutions ● ContentBox Evangelist What else do you need to know? ● Blog - http://www.gpickin.com ● Twitter – http://twitter.com/gpickin ● Github - https://github.com/gpickin Let’s get on with the show.
  4. 4. State of the Room ● A few questions for you guys ● If you have arms, use them.
  5. 5. APIs in CFML Most CF Apps are moving towards providing an API for multiple consumers CF has many REST API Solutions and even more with CF 2016 ● Built in CF ● Built in Railo/Lucee ● Coldbox API ● Taffy
  6. 6. Ways to Test your Code ● Click around in the browser yourself ● Setup Selenium / Web Driver to click around for you ● Structured Programmatic Tests
  7. 7. Types of Testing ● 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
  8. 8. Integration Testing ● 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
  9. 9. Unit Testing “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
  10. 10. Unit Testing can... ● 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
  11. 11. Styles – TDD vs BDD ● 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
  12. 12. Styles - TDD vs BDD ● 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
  13. 13. TDD Example Test( ‘Email address must not be blank’, function(){ notEqual(email, “”, "failed"); });
  14. 14. BDD Example Describe( ‘Email Address’, function(){ It(‘should not be blank’, function(){ expect(email).not.toBe(“”); }); });
  15. 15. Matchers expect(true).toBe(true); expect(true).toBe(true); expect(true).toBe(true); expect(true).toBe(true);
  16. 16. Matchers 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);
  17. 17. Matcher Samples 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();
  18. 18. Different Testing Environments? NodeJS - CLI In the Browser
  19. 19. CF Testing Tools * MxUnit was the standard * TestBox is the new standard Other options
  20. 20. TestBox TestBox is a next generation testing framework for ColdFusion (CFML) that is based on BDD (Behavior Driven Development) for providing a clean obvious syntax for writing tests. It contains not only a testing framework, runner, assertions and expectations library but also ships with MockBox, A Mocking & Stubbing Framework,. It also supports xUnit style of testing and MXUnit compatibilities.
  21. 21. TestBox TDD Example function testHelloWorld(){           $assert.includes( helloWorld(), ”world" );      }
  22. 22. TestBox BDD Example describe("Hello world function", function() { it(”contains the word world", function() { expect(helloWorld()).toContain("world"); }); });
  23. 23. TestBox New BDD Example feature( "Box Size", function(){     describe( "In order to know what size box I need               As a distribution manager               I want to know the volume of the box", function(){         scenario( "Get box volume", function(){             given( "I have entered a width of 20                 And a height of 30                 And a depth of 40", function(){                 when( "I run the calculation", function(){                       then( "the result should be 24000", function(){
  24. 24. JS Testing Tools *There are a few choices
  25. 25. Main JS Testing Players Jasmine, Mocha and QUnit
  26. 26. Jasmine *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
  27. 27. Jasmine - Cons Async testing in 1.3 can be a headache *Async testing in 2.0 is hard to find blog posts on (I need to write one) *Expects *spec.js suffix for test files *This can be modified depending on how you are running the tests
  28. 28. Jasmine – Sample Test describe("Hello world function", function() { it(”contains the word world", function() { expect(helloWorld()).toContain("world"); }); });
  29. 29. Mocha *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
  30. 30. Mocha - Cons *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.
  31. 31. Mocha – BDD Sample Test var expect = require('chai').expect; describe(’Hello World Function', function(){ it('should contain the word world', function(){ expect(helloWorld()).to.contain(’world'); }) })
  32. 32. QUnit *The oldest of the main testing frameworks *Is popular due to use in jQuery and age *Ember’s default Unit testing Framework
  33. 33. QUnit - Cons *Development slowed down since 2013 (but still under development) *Syntax – No BDD style *Assertion libraries – limited matchers
  34. 34. QUnit – Sample Test 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" );
  35. 35. Spaghetti Javascript Photo Credit – Kombination http://www.kombination.co.za/wp-content/uploads/2012/10/baby_w_spaghetti_mess_4987941.jpg
  36. 36. Spaghetti Javascript Example
  37. 37. Spaghetti Javascript Example
  38. 38. Refactoring Spaghetti *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
  39. 39. Refactoring Spaghetti *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” Kev McCabe
  40. 40. Object Literals var personObjLit = { ssn: ’xxxxxxxx', age: '35', name: 'Gavin Pickin', getAge: function(){ return this.age; }, getName: function() { return this.name; } };
  41. 41. Module Pattern var personObjLit2 = function() { ssn = ’xxxxxxx'; age = '35'; name = 'Gavin Pickin’; return { getAge: function(){ return age; }, getName: function() { return name; } }; };
  42. 42. Using Testing in your Workflow *Using HTML Test Runners *Keep a Browser open *F5 refresh tests
  43. 43. Command Line 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
  44. 44. Testing in your IDE *Browser Views *Eclipse allows you to open files in web view – uses HTML Runner *Run Jasmine / Grunt / Karma in IDE Console *Fairly Easy to setup *See Demo– Sublime Text 2 (if we have time)
  45. 45. Live Demo and Examples *Install / Run Jasmine Standalone for Browser *Install / Run Jasmine with NodeJs *Install / Run Jasmine with Grunt Watch *Install / Run Testbox in Browser
  46. 46. Install / Run Jasmine for In-Browser Testing 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
  47. 47. Standalone Jasmine
  48. 48. Installing Jasmine for in Browser Testing http://www.testableapi.local.com:8504/tests/SpecRunner.html
  49. 49. SpecRunner Setup Jasmine Browser Test <!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>
  50. 50. Installing Jasmine with NodeJS 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)
  51. 51. Installing Jasmine with NodeJS Once Jasmine is installed in your project $ Jasmine init
  52. 52. Installing Jasmine with NodeJS Edit Jasmine.json to update Locations for Spec Files and Helper Files { "spec_dir": "spec", "spec_files": [ "**/*[sS]pec.js" ], "helpers": [ "helpers/**/*.js" ] }
  53. 53. Running Jasmine Tests with NodeJS $ 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:1 8) 1 spec, 1 failure
  54. 54. Running Jasmine Tests with NodeJS *Jasmine-Node is great for Node *Jasmine Node doesn’t have a headless browser *Hard to test Browser code *So what should I use?
  55. 55. Installing Jasmine with Grunt Watcher *Install Grunt npm install grunt *Install Grunt – Jasmine npm install grunt-contrib-jasmine *Install Grunt – Watch npm install grunt-contrib-watch
  56. 56. Configuring Jasmine with Grunt Watcher // 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' ], '--web-security': false }
  57. 57. Configuring Jasmine with Grunt Watcher // gruntfile.js part 2 watch: { js: { files: [ 'js/*.js', 'specs/*.js', ], tasks: ['jasmine:all'] } }
  58. 58. Configuring Jasmine with Grunt Watcher // gruntfile.js part 3 grunt.loadNpmTasks('grunt-contrib-jasmine'); grunt.loadNpmTasks('grunt-contrib-watch'); };
  59. 59. Example Jasmine Spec with Grunt Watcher describe("Forgotten Password Form", function() { it("should warn you if the email is invalid before making Ajax Call", function() { expect( isEmailInputInvalid('') ).toBe(true); expect( isEmailInputInvalid('dddddddddd') ).toBe(true); expect( isEmailInputInvalid('dddddd@') ).toBe(true); expect( isEmailInputInvalid('dddddd@ddddd') ).toBe(true); expect( isEmailInputInvalid('dddddd@ddddddd.') ).toBe(true); expect( isEmailInputInvalid('dddddd@ddddddd.com') ).toBe(false);
  60. 60. Example Jasmine Spec with Grunt Watcher describe("Login Form", function() { it("should set status correct status message with successful Ajax Response", function() { spyOn( window, "setStatusMessage"); processLoginAjaxDone('{"RESULT":"200"}'); expect(setStatusMessage).toHaveBeenCalled(); expect(setStatusMessage).toHaveBeenCalledWith( ‘TARDIS Access Granted - Please wait for the Doctor to take you for a spin'); });
  61. 61. Example Jasmine Spec with Grunt Watcher describe("Login API", function() { it("should return a failing Ajax Response", function() { spyOn( window, "processLoginAjaxDone"); loginButtonEventHandlerProcess( 'gavin@gavin.co.nz', 'password'); expect(processLoginAjaxDone).toHaveBeenCalled(); expect(processLoginAjaxDone).toHaveBeenCalledWith( ‘{"RESULT":400}'); expect(processLoginAjaxFail).not.toHaveBeenCalled();
  62. 62. Whats wrong with that? describe("Login API", function() { it("should return a failing Ajax Response", function() { spyOn( window, "processLoginAjaxDone"); loginButtonEventHandlerProcess( 'gavin@gavin.co.nz', 'password'); expect(processLoginAjaxDone).toHaveBeenCalled(); expect(processLoginAjaxDone).toHaveBeenCalledWith( ‘{"RESULT":400}'); expect(processLoginAjaxFail).not.toHaveBeenCalled(); });
  63. 63. Unit Tests and Async Calls *You want Unit Tests to test the unit and not it’s dependencies *You want Unit Tests to run quick *You should mock the API in the Ajax call *But we want to test the API *So essentially, we’re writing an integration test.
  64. 64. How to wait for Async describe("Login API", function() { beforeEach(function( done ) { spyOn( window, "processLoginAjaxDone").and.callFake( function(){ done(); }); spyOn( window, "processLoginAjaxFail").and.callFake( function(){ done(); }); loginButtonEventHandlerProcess('gavin@gavin.co.nz', 'password'); }); it("should return a failing Ajax Response", function() { }); });
  65. 65. How to wait for Async describe("Login API", function() { beforeEach(function( done ) { … }); it("should return a failing Ajax Response", function() { expect(processLoginAjaxDone).toHaveBeenCalled(); expect(processLoginAjaxDone).toHaveBeenCalledWith( '{"RESULT":400}'); expect(processLoginAjaxFail).not.toHaveBeenCalled(); });
  66. 66. Running Jasmine with Grunt Watcher
  67. 67. Running Jasmine with Grunt Watcher
  68. 68. Installing Testbox *Install Testbox – Easy Thanks to Commandbox *box install testbox *Next, decide how you want to run Testbox
  69. 69. Create a runner.cfm *<cfsetting showDebugOutput="false"> *<!--- Executes all tests in the 'specs' folder with simple reporter by default ---> *<cfparam name="url.reporter" default="simple"> *<cfparam name="url.directory" default="tests.specs"> *<cfparam name="url.recurse" default="true" type="boolean"> *<cfparam name="url.bundles" default=""> *<cfparam name="url.labels" default="">
  70. 70. Create a Test Suite // tests/specs/CFCTest.cfc component extends="testbox.system.BaseSpec" { function run() { it( "will error with incorrect login", function(){ var oTest = new cfcs.userServiceRemote(); expect( oTest.login( 'gavin@gavin.com', 'topsecret').result ).toBe('400'); }); }
  71. 71. Create a 2nd Test Suite // tests/specs/APITest.cfc component extends="testbox.system.BaseSpec" { function run() { describe("userService API Login", function(){ it( "will error with incorrect login", function(){ var email = "gavin@gavin.com"; var password = "topsecret”; var result = ""; http url="http://www.testableapi.local.com:8504/cfcs/userServiceRemote.cfc?method=log in&email=#email#&password=#password#" result="result”; expect( DeserializeJSON(result.filecontent).result ).toBe('400'); }); });
  72. 72. Running Testbox with runner.cfm
  73. 73. Running Testbox with Grunt Watch *Install Testbox Runner – Thanks Sean Coyne *npm install testbox-runner *Install Grunt Shell *npm install grunt-shell *Add Grunt Configuration
  74. 74. Adding TextBox Config 1 module.exports = function (grunt) { grunt.loadNpmTasks('grunt-shell'); grunt.initConfig({ … }) }
  75. 75. Adding TextBox Config 2 Watch: { … cfml: { files: [ "cfcs/*.cfc"], tasks: [ "testbox" ] } }
  76. 76. Adding TextBox Config 3 shell: { testbox: { command: "./node_modules/testbox-runner/index.js --colors --runner http://www.testableapi.local.com:8504/tests/r unner.cfm --directory /tests/specs --recurse true”
  77. 77. Adding TextBox Config 4 grunt.registerTask("testbox", [ "shell:testbox" ]); grunt.loadNpmTasks('grunt-contrib-jasmine'); grunt.loadNpmTasks('grunt-contrib-watch');
  78. 78. Adding TextBox Config 5 js: { files: [ 'js/*.js', 'specs/*.js', "cfcs/*.cfc” ], tasks: ['jasmine:all'] },
  79. 79. GruntFile.js Gists Jasmine https://gist.github.com/gpickin/1e1e7902d1d36 76d23c5 Jasmine + Testbox https://gist.github.com/gpickin/9fc82df3667ee b63c7e7
  80. 80. Testbox output with Grunt
  81. 81. Testbox Runner JSON *Testbox has several runners, you have seen the HTML one, this Runner uses the JSON runner and then formats it. *http://www.testableapi.local.com:8504/tests/runner.cfm?rep orter=JSON&directory=%2Ftests%2Fspecs&recurse=true
  82. 82. Running in Sublime Text 2 *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
  83. 83. Running in Sublime Text 2

×