Testing JavaScript Applications

  • View
    377

  • Download
    13

  • Category

    Software

Preview:

DESCRIPTION

Some brief overview of technologies and frameworks that are used for testing front-end and javascript.

Citation preview

TESTING JAVASCRIPT APPLICATIONSby Alexander Gerasimov and Dmitrey Gerasimov

¿POR QUÉ?

¡PORQUE!refactoringorganization, modularization, extensibilitydocumentationdefect preventioncollaboration

"Any feature without a test doesn’t exist"

Steve Loughran HP Laboratories

TDD & BDD

TESTS FIRST

RED/GREEN/REFACTORRed: Write a failing test

RED/GREEN/REFACTORGreen: Make it pass

RED/GREEN/REFACTORRefactor: Eliminate redundancy

STRUCTURESetup: Put the Unit Under Test (UUT) or the overall test system in the state needed

to run the test.

Execution: Trigger/drive the UUT to perform the target behavior and capture all

output, such as return values and output parameters.

Validation: Ensure the results of the test are correct.

Cleanup: Restore the UUT or the overall test system to the pre-test state.http://en.wikipedia.org/wiki/Test-driven_development#Test_structure

TDD ASSERTIONSvar assert = chai.assert;assert.typeOf(foo, 'string');assert.equal(foo, 'bar');assert.lengthOf(foo, 3)assert.property(tea, 'favors');assert.lengthOf(tea.flavors, 3);

BDDBehavior-driven development

GIVEN-WHEN-THENStory: Returns go to stockIn order to keep track of stockAs a store ownerI want to add items back to stock when they're returned

Scenario 1: Refunded items should be returned to stockGiven a customer previously bought a black sweater from meAnd I currently have three black sweaters left in stockWhen he returns the sweater for a refundThen I should have four black sweaters in stock

CUCUMBERFeature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two number

Scenario: Add two numbers Given I have entered 50 into the calculator And I have entered 70 into the calculator When I press add Then the result should be 120 on the screen

CUCUMBER Given /I have entered (.*) into the calculator do calculator = new Calculator(); calculator.push(n); end

EXPECTvar 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);

SHOULDvar should = require("chai").should() , 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);

FUNCTIONAL TESTING

UX/BEHAVIOR VERIFICATIONUnit tests just prove that your code doesn't work

AUTOMATION & CONTROL

METRICS & PROFILINGExecution timeLoading, rendering, paintingCPU & MemoryGoogle Chrome Metrics

HELPS QA TESTERSWhy not let QA guys concentrate on quality rather than

routine?

TOOLS & EXAMPLESgeneratorsframeworks[assertion] librariespluginsstat toolscomplex solutions + Grunt

TECHNIQUES

DUMMIES

STUBS

MOCKS

SPIES

FIXTURES

JASMINE

What is it?..

JASMINESuites & specs

describe("A suite is just a function", function() { var a;

it("and so is a spec", function() { a = true;

expect(a).toBe(true); });});

JASMINEMatchers

expect(x).toEqual(y);expect(x).toBe(y);expect(x).toMatch(pattern);expect(x).toBeDefined();expect(x).toBeUndefined();expect(x).toBeNull();expect(x).toBeTruthy();expect(x).toBeFalsy();expect(x).toContain(y);expect(x).toBeLessThan(y);expect(x).toBeGreaterThan(y);expect(function(){fn();}).toThrow(e);

JASMINESpies

SPIESTracks

Functions callsArgumentsNumber of calls

SPIESAccess

All calls of functionEvery argument of every call

SPIESCan

Track and delegateSubstitute returning valuesCall faked functionsCreate mock objects

JASMINEAny

describe("jasmine.any", function() { it("matches any value", function() { expect({}).toEqual(jasmine.any(Object)); expect(12).toEqual(jasmine.any(Number)); });});

JASMINEClock

beforeEach(function() { timerCallback = jasmine.createSpy("timerCallback"); //create spy jasmine.Clock.useMock(); //use wrepper of system timer});

it("causes a timeout to be called synchronously", function() { setTimeout(function() { timerCallback(); }, 100);

expect(timerCallback).not.toHaveBeenCalled(); jasmine.Clock.tick(101); //make time to go expect(timerCallback).toHaveBeenCalled();});

JASMINEAsync

It exists, but...

JASMINEReporter

describe("Jasmine", function() { it("makes testing JavaScript awesome!", function() { expect (yourCode).toBeLotsBetter(); });});

MOCHA['mɔkə]

MOCHASupports TDD assertions and BDD should/expectReporting & CI integrationJavaScript APIBrowser Test Runner

MOCHAdescribe('Array', function(){ describe('#indexOf()', function(){ it('should return -1 when the value is not present', function(){ [1,2,3].indexOf(5).should.equal(-1); [1,2,3].indexOf(0).should.equal(-1); }) })})

MOCHAdescribe('User', function(){ describe('#save()', function(){ it('should save without error', function(done){ var user = new User('Luna'); user.save(function(err){ if (err) throw err; done(); }); }) })})

MOCHAHooks: before(), after(), beforeEach(), afterEach()

beforeEach(function(done){db.clear(function(err){ if (err) return done(err); db.save([tobi, loki, jane], done); });})

MOCHA

MOCHAConsole reporter

MOCHAHTML reporter

MOCHANyan reporter

CHAI

CHAIAssert, expect/should

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

QUESTION TIME!How would you test an RNG?

CHAIPlugins

here

CASPERJSvar casper = require('casper').create();

casper.start('http://domain.tld/page.html', function() { if (this.exists('h1.page-title')) { this.echo('the heading exists'); }});

casper.run();

QUESTION TIME!What happens if not everyone on the team adopts TDD/BDD?

CODE COVERAGE

INSTRUMENTATION

INSTRUMENTATION

ISTANBULStatement, branch, and function coverageTest running toolsHTML & LCOV reportingesprima-based

TESTING + CI = ❤fail buildsstatistics & reportingGithub is integration paradise

GITHUB IS INTEGRATION PARADISE

IRL, 100% COVERAGE IS A LIElegacy & untestable codepermissive testsnot applicable to functional testing

MUTATION TESTINGWho tests tests?Coverage is paramount! (it isn't)Mutations: remove lines, alter operators, rename identifiersThe Future of Unit Testing

QUESTION TIME!What do you do when you're offerred a project without TDD?

YOU RUN LIKE HELL

THE END