testacular

27
Testacular Javascript Testing with Node.js, Testacular & Jasmine

Upload: james-ford

Post on 10-May-2015

419 views

Category:

Technology


0 download

DESCRIPTION

Javascript Testing with Node.js, Testacular & Jasmine

TRANSCRIPT

Page 1: Testacular

TestacularJavascript Testing with

Node.js, Testacular & Jasmine

Page 2: Testacular

"Man, I just love unit tests, I've just been able to make a bunch of changes to the way something works, and then was able to confirm I hadn't broken anything by

running the test over it again..."

Page 3: Testacular

1. Unit Tests allow you to make big changes to code quickly. You know it works now because you've run the tests, when you make the changes you need to make, you need to get the tests working again. This saves hours.

2. TDD helps you to realise when to stop coding. Your tests give you confidence that you've done enough for now and can stop tweaking and move on to the next thing.

3. The tests and the code work together to achieve better code. Your code could be bad / buggy. Your TEST could be bad / buggy. In TDD you are banking on the chances of BOTH being bad / buggy being low. Often it's the test that needs fixing but that's still a good outcome.

4. TDD helps with coding constipation. When faced with a large and daunting piece of work ahead writing the tests will get you moving quickly.

5. Unit Tests help you really understand the design of the code you are working on. Instead of writing code to do something, you are starting by outlining all the conditions you are subjecting the code to and what outputs you'd expect from that.

Why Unit Test Javascript? part 1

Page 4: Testacular

6. Unit Tests give you instant visual feedback, we all like the feeling of all those green lights when we've done. It's very satisfying. It's also much easier to pick up where you left off after an interruption because you can see where you got to - that next red light that needs fixing.

7. Contrary to popular belief unit testing does not mean writing twice as much code, or coding slower. It's faster and more robust than coding without tests once you've got the hang of it. Test code itself is usually relatively trivial and doesn't add a big overhead to what you're doing. This is one you'll only believe when you're doing it :)

8. I think it was Fowler who said: "Imperfect tests, run frequently, are much better than perfect tests that are never written at all".

9. Good unit tests can help document and define what something is supposed to do

10. Unit tests help with code re-use. Migrate both your code AND your tests to your new project. Tweak the code till the tests run again.

Why Unit Test Javascript? part 2

Page 5: Testacular

● Sanity testing - Are the expected functions and classes available?

● Regression testing - Is that bug squashed, and will never appear again?

● Functional testing - Given x, do y.● Specification tests - I don't have real world data,

but assuming I get data in this format...● Edge-case testing - This expects a Number, but if

someone gives it a String...

Why do we use Unit Testing?

Page 6: Testacular

Running Tests

Page 7: Testacular

● Developed + Open Sourced by Google.● Node.js === Native Javascript, using the V8 framework.● Works with any* browser.● Works without any IDE.● Integration with CI servers.● Stable.● Fast. ● Line, branch, statement & function coverage test

data.● Jasmine, Mocha & AngularJS testing frameworks.

Why Testacular?

Page 8: Testacular

● It can't evaluate code coverage in any more depth than line coverage.

● It's Java based.● Slower than Testacular.

Why not JSTestDriver?

Page 9: Testacular

● Configuration file specifies:○ Input files (source code and test files)○ Browsers to test with○ Excluded files, coverage tests, ports, run mode, output format, base path, etc...

● Command line execution:> testacular start

How does it work?

Page 10: Testacular
Page 11: Testacular

Let's see that in action...

Page 12: Testacular

Writing Tests

Page 13: Testacular

Sanity testing/js/rio.js

var RIO = {

init: initialise,

model: new RIOModel(),

data: new RIOData(),

controller: new RIOController()

};

/tests/rio.tests.js

describe("RIO Object", function() { it("has the expected API", function() { expect(RIO).toBeDefined();

expect(typeof(RIO)).toBe("object");

expect(typeof(RIO.init)).toBe("function");

expect(typeof(RIO.model)).toBe("object");

expect(typeof(RIO.data)).toBe("object");

expect(typeof(RIO.controller)).toBe("object"); });});

Page 14: Testacular

Regression testing/tests/regression.test.js

describe("Defect DE248 Regression test", function() {

beforeEach(function() {

readFixtures('simple-fixture.html');

var options = {

containerElement: $('div.sample-1'),

dataProvider: Standalone.DataProvider,

pathToAssets: "base/mockdata/mfl/"

};

var activeTextInstance = new ActiveText(options);

});

it("stops the iframes overlapping", function() {

var iframeWidth = $('div.sample-1').find('div.iframe').width();

var dpsWidth = $('div.sample-1').find('div.reader').width();

expect(iframeWidth < dpsWidth).toBeTruthy();

expect(iframeWidth).toBeCloseTo(dpsWidth / 2);

});

});

Page 15: Testacular

Functional testing/tests/utils.tests.js

describe("Functional tests for the utils class", function() {

it('checks the output of getCorrectPathToAssetsFromHTMLPageAt', function() {

var instance = new ActiveText.Loader({

pathToAssets: "mockdata/exploringscience/"

});

var output = instance.test.getCorrectPathToAssetsFromHTMLPageAt( "images/page0001Exploring_Science_AT_v1.pdf.png");

expect(output).toBe("mockdata/exploringscience/images/");

...

});

});

Page 16: Testacular

Specification testing/tests/specification.test.js

$.ajaxSetup({

async: false

});

$.mockjax({

url: 'mockdata/sockosaurus/META-INF/container.xml',

responseType: "xml",

responseText: '<?xml version="1.0" encoding="UTF-8"?><container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"><rootfiles><rootfile full-path="OPS/book.opf" media-type="application/oebps-package+xml"/></rootfiles></container>'

});

describe("Data Loader test", function() { it("loads data", function() {

activeTextInstance.loader.loadData(); expect(activeTextInstance.data.getPath()).toBe("OPS/book.opf"); });});

Page 17: Testacular

Edge-case testing/tests/edgecase.tests.js

describe("Navigation tests", function() { it("tests the edge cases", function() { activeTextInstance.navigation.gotoPage(5);

expect(activeTextInstance.model.getCurrentPageNumber()).toBe(5);

activeTextInstance.navigation.gotoPage(12);

expect(activeTextInstance.model.getCurrentPageNumber()).toBe(12);

activeTextInstance.navigation.gotoPage(-500);

expect(activeTextInstance.model.getCurrentPageNumber()).toBe(0);

activeTextInstance.navigation.gotoPage(500);

expect(activeTextInstance.model.getCurrentPageNumber()).toBe(26);

});});

Page 18: Testacular

● describe(name, function)● it(name, function)● beforeEach(function) / afterEach(function)● expect(condition).toBe(value);● expect(condition).not.toBe(value);● .toEqual() / .toBeTruthy() / .toBeFalsy()● waitsFor(function) / runs(function)

describe("A suite", function() { it("contains spec with an expectation", function() { expect(true).toBe(true);

expect(true).not.toBe(false); });});

Writing tests in Jasmine

Page 19: Testacular

Setup time

Page 20: Testacular

Python 2.7node.js + npmtestacular

Growl NotificationsPhantomJS

http://www.python.org/download/releases/

http://nodejs.org/

http://testacular.github.com/0.6.0/intro/ installation.html

http://www.growlforwindows.com/gfw/

http://phantomjs.org/

Installing Testacular + Jasmine

Optional Extras

Page 21: Testacular

> testacular init

Page 22: Testacular

Time to write some tests...

Page 23: Testacular

Time to write some code...

Page 24: Testacular

How many tests do you need?

Page 25: Testacular
Page 26: Testacular

// Testacular configuration

// base path, that will be used to resolve files and excludebasePath = '';

// list of files / patterns to load in the browserfiles = [ JASMINE, JASMINE_ADAPTER, 'js/**/*.js', 'js-tests/**/*.js'];

// list of files to excludeexclude = [];

preprocessors = { 'js/**/*.js' : 'coverage'};

coverageReporter = { type: 'lcov', dir: 'coverage/'};

// test results reporter to use// possible values: 'dots', 'progress', 'junit'reporters = ['progress', 'coverage'];

// web server portport = 7654;

Testacular configuration file + coverage// cli runner portrunnerPort = 9100;

// enable / disable colors in the output (reporters and logs)colors = true;

// level of logging// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUGlogLevel = LOG_INFO;

// enable / disable watching file and executing tests whenever any file changesautoWatch = true;

// Start these browsers, currently available:// - Chrome// - ChromeCanary// - Firefox// - Opera// - Safari (only Mac)// - PhantomJS// - IE (only Windows)browsers = ['PhantomJS'];

// If browser does not capture in given timeout [ms], kill itcaptureTimeout = 60000;

// Continuous Integration mode// if true, it capture browsers, run tests and exitsingleRun = false;

Page 27: Testacular

That's all folks@psyked_james / aka James Ford