View
968
Download
0
Category
Tags:
Preview:
Citation preview
Javascript TestingJasmine, Chai, and Phantomby Brandon D'Imperio
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
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.
I don't always test
Yay Coding!Really, coding?
Jasmine testing is codingOk, maybe scripting, but almost coding!You get testing, while your developers get to keep coding.
Enter JasmineNo, not this one
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();
});
});
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();
}
})();
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);
PhantomJsIs your automated testing not quite fast enough?Automated testing tools not quite extensible enough?Try PhantomJs
Full web stackNo browser required
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();});
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();
});
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;
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();
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();
}
};
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');
});
Referenceshttp://pivotal.github.io/jasmine/http://chaijs.com/http://phantomjs.org/
Mine:http://jsfiddle.net/Maslow/V8ryc/showhttp://jsfiddle.net/Maslow/66MJU/show/https://github.com/ImaginaryDevelopment/javascript/tree/master/phantom
These slideshttp://j.mp/13spNkW
Topics Available● Meta-Programming
○ T4○ CoffeeScript
● Javascript Topics○ Knockout
■ Custom bindings■ KoGrid■ jQuery
● ALM○ TFS - Custom Workflow builds○ SonarSource Code quality analysis
● Functional Programming
More topics● Unit testing● Entity Framework● Dependency Injection● Asp.Net MVC4● MvcOData
○ Knockout -> OdataUrl Generation -> Ajax -> MVC -> WCF Data services -> Entity Framework
Mehttp://stackoverflow.com/users/57883/maslow
imaginarydevelopment @ gmail
Recommended