Js testing

22
Javascript Testing Jasmine, Chai, and Phantom by Brandon D'Imperio

Transcript of Js testing

Page 1: Js testing

Javascript TestingJasmine, Chai, and Phantomby Brandon D'Imperio

Page 2: Js testing

Developers test more than enough, right?● Our quality is so high, we don't need to test.● We don't have dedicated testers● Our testers find everything just fine.● Where we're going we don't need roads. -

Doc

Page 3: Js testing

Manual testing is the way to go● They remember to test everything every time

a change is made, right?● Manual testing is fun, fast, and enjoyable.

Page 4: Js testing

I don't always test

Page 5: Js testing

Yay Coding!Really, coding?

Page 6: Js testing

Jasmine testing is codingOk, maybe scripting, but almost coding!You get testing, while your developers get to keep coding.

Page 7: Js testing

Enter JasmineNo, not this one

Page 8: Js testing

JasmineJsBDD for your JavaScriptJasmine is a behavior-driven development framework for testing your JavaScript code. It does not depend on any other JavaScript

frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests.

describe("Jasmine", function() {

it("makes testing JavaScript awesome!", function() {

expect(yourCode).toBeLotsBetter();

});

});

Page 9: Js testing

Start Jasmine(function () {

var jasmineEnv = jasmine.getEnv();

jasmineEnv.updateInterval = 250;

var htmlReporter = new jasmine.HtmlReporter();

jasmineEnv.addReporter(htmlReporter);

jasmineEnv.specFilter = function (spec) {

return htmlReporter.specFilter(spec);

};

var currentWindowOnload = window.onload;

window.onload = function() {

if (currentWindowOnload) {

currentWindowOnload();

}

document.querySelector('.version').innerHTML = jasmineEnv.versionString();

execJasmine();

};

function execJasmine() {

console.log("running jasmine");

jasmineEnv.execute();

}

})();

Page 10: Js testing

ChaiAssertion frameworkvar assert = require('chai').assert , foo = 'bar' , beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

assert.typeOf(foo, 'string', 'foo is a string');assert.equal(foo, 'bar', 'foo equal `bar`');assert.lengthOf(foo, 3, 'foo`s value has a length of 3');assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');

Orvar expect = require('chai').expect , foo = 'bar' , beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

expect(foo).to.be.a('string');expect(foo).to.equal('bar');expect(foo).to.have.length(3);expect(beverages).to.have.property('tea').with.length(3);

Orvar should = require('chai').should() //actually call the the function , foo = 'bar' , beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

foo.should.be.a('string');foo.should.equal('bar');foo.should.have.length(3);beverages.should.have.property('tea').with.length(3);

Page 11: Js testing

PhantomJsIs your automated testing not quite fast enough?Automated testing tools not quite extensible enough?Try PhantomJs

Full web stackNo browser required

Page 12: Js testing

Phantom Barebones example

console.log('Loading a web page');var page = require('webpage').create();var url = 'http://www.phantomjs.org/';page.open(url, function (status) { //Page is loaded! phantom.exit();});

Page 13: Js testing

Phantom Sample Post// Example using HTTP POST operation

var page = require('webpage').create(),

server = 'http://posttestserver.com/post.php?dump',

data = 'universe=expanding&answer=42';

page.open(server, 'post', data, function (status) {

if (status !== 'success') {

console.log('Unable to post!');

} else {

console.log(page.content);

}

phantom.exit();

});

Page 14: Js testing

Phantom Sample - Render to imagevar page = require('webpage').create();

page.viewportSize = { width: 400, height : 400 };

page.content = '<html><body><canvas id="surface"></canvas></body></html>';

page.evaluate(function() {

var el = document.getElementById('surface'),

context = el.getContext('2d'),

width = window.innerWidth,

height = window.innerHeight,

cx = width / 2,

cy = height / 2,

radius = width / 2.3,

imageData,

pixels,

hue, sat, value,

i = 0, x, y, rx, ry, d,

f, g, p, u, v, w, rgb;

el.width = width;

el.height = height;

imageData = context.createImageData(width, height);

pixels = imageData.data;

Page 15: Js testing

Phantom Sample - Render to image(cont.) for (y = 0; y < height; y = y + 1) {

for (x = 0; x < width; x = x + 1, i = i + 4) {

rx = x - cx;

ry = y - cy;

d = rx * rx + ry * ry;

if (d < radius * radius) {

hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI);

sat = Math.sqrt(d) / radius;

g = Math.floor(hue);

f = hue - g;

u = 255 * (1 - sat);

v = 255 * (1 - sat * f);

w = 255 * (1 - sat * (1 - f));

pixels[i] = [255, v, u, u, w, 255, 255][g];

pixels[i + 1] = [w, 255, 255, v, u, u, w][g];

pixels[i + 2] = [u, u, w, 255, 255, v, u][g];

pixels[i + 3] = 255;

}

}

}

context.putImageData(imageData, 0, 0);

document.body.style.backgroundColor = 'white';

document.body.style.margin = '0px';

});

page.render('colorwheel.png');

phantom.exit();

Page 16: Js testing

PhantomJs+Chaiphantom.injectJs("chai.js");

var assert = chai.assert;

var expect = chai.expect;

var bAssert = function(delegate, onError, onSuccess) {

success = false;

try {

delegate();

success = true;

} catch (err) {

//chai delegate failed

if (onError) {

onError(err);

} else {

if (bNavigator.config.attemptToLogAssertCaller) {

var callerNameMatch = bAssert.caller.toString().match(/function

([^\(]+)/);

if (callerNameMatch && callerNameMatch[1]) {

console.error('<chai>' + err + '<caller>' + callerNameMatch[1] +

'</caller></chai>');

} else console.error('<chai>' + err + '<callerunknown /></chai>');

//console.log('caller was '+ callerNameMatch[1]);

} else {

console.error('<chai>' + err + '</chai>');

}

}

} //end catch

if (success === true && onSuccess) {

onSuccess();

}

};

Page 17: Js testing
Page 18: Js testing

My Chai (not Mai-Tai)bAssert(function(){ assert.typeOf('test','string','test is a string');});

bAssert(function(){

var currentItemIndex=page.evaluate(function(){

return $('.first-index:first').text();

});

console.log('currentItemIndex='+currentItemIndex);

assert.notEqual(currentItemIndex,'','current item index should never be empty');

});

Page 20: Js testing

Topics Available● Meta-Programming

○ T4○ CoffeeScript

● Javascript Topics○ Knockout

■ Custom bindings■ KoGrid■ jQuery

● ALM○ TFS - Custom Workflow builds○ SonarSource Code quality analysis

● Functional Programming

Page 21: Js testing

More topics● Unit testing● Entity Framework● Dependency Injection● Asp.Net MVC4● MvcOData

○ Knockout -> OdataUrl Generation -> Ajax -> MVC -> WCF Data services -> Entity Framework

Page 22: Js testing

Mehttp://stackoverflow.com/users/57883/maslow

imaginarydevelopment @ gmail