js fwdays unit tesing javascript(by anna khabibullina)

Post on 11-May-2015

564 Views

Category:

Engineering

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

See video from JS Frameworks Day, April 2014 https://www.youtube.com/watch?v=edOIMiQFZ2w&list=UU3NDbeN0Jq_InNAhiJtvHcQ

TRANSCRIPT

В поисках качества JavaScript:модульное тестирование

Анна ХабибуллинаDA-14 / da-14.com

anna.khabibullina@da-14.com

akhabibullina

_khabibullina

SAY HI

ZE QUALITYS?

“Any feature without a test doesn’t exist”

Steve Loughran HP Laboratories

AGENDA

Unit Testing Concept

Pros & Cons

Basic Terms & Structure

TDD &/vs. BDD

Tools & Libraries

Unit Testing Specifics

in JavaScript

Best Practices

UNIT TESTING CONCEPT

Unit testing is a method by which individual

units of source code are tested to determine

if they are fit for use.

WHY UNIT TESTING?

Unit tests find problems early in the

development cycle (TDD & BDD)

Refactoring

Integration

Documentation

Better design

IS UNIT TESTING A GOOD INVESTMENT?

slow down the development process

share the same blind spots with the code

doesn’t prove that they’re compatible with

one another or configured correctly

BASIC TERMS

In simple words, the goal of assertion is to

forcefully define if the test fails or passes.

STATEMENT PASSES FAILS

x = 1 assert(x > 0) assert(x < 0)

expect(4+5).to.equal(9);

ASSERTION

function initialize() {

// The initialization was successful.

return true;

}

Given the function initialize():

ASSERTION: EXAMPLE

ASSERTION: EXAMPLE

var isInitialized = initialize();

TDD assert.isTrue(isInitialized)

BDD expect(isInitialized).to.be.true

Check that function initialize() returns true

when called.

FIXTURE

A test fixture is a fixed state of the software

under test used as a baseline for running

tests.

In JavaScript for client side:

simulate AJAX responses;

loading known set of data such as html

objects.

FIXTURE: EXAMPLE

Require the piece of markup stored in

myfixturemarkup.html file before each test:

beforeEach(function() {

loadFixtures('myfixturemarkup.html');

});

STUB

Method stubs

are functions

with pre-

programmed

behavior.

STUB: EXAMPLE

Forcing a method to throw an error in order

to test error handling.

var fn = foo.stub().throws(Error);

expect(fn).to.throw(Error);

SPY

A test spy is a

function that

records

arguments,

return value, the

value of this and

exception thrown

(if any) for all its

calls.

SPY: EXAMPLE

Test that a function cursor.hide() has been

only called once, and only once.

sinon.spy(cursor, "hide");

TDD sinon.assert.calledOnce(cursor.hide)

BDD expect(cursor.hide.calledOnce).to.be.true

MOCK

Mocks are fake objects with pre-

programmed behavior (like stubs) and

pre-programmed expectations.

They are like both stubs and spies – in

one.

MOCK: EXAMPLE

Create an expectation that jQuery.each is

called once, and only once, and also

instructs the mock to behave as we pre-

define.

var mock = sinon.mock(jQuery);

MOCK: EXAMPLE

#1 – which method?

#2 – how many times it is called?

#3 – what are the arguments when the

method called?

#4 – what the method returns?

TEST DRIVEN DEVELOPMENT(TDD)

TDD is a software

development

process that…

I’ll tell you the rest

WHAT ARE THESE BDD?

ALRIGHT, WHAT IS BDD YOU ASK?

Terminology:

TDD BDD

Test Example

Assertion Expectation

Unit Behavior

BASIC STRUCTURE

#1. Setup/BeforeEach/Before

#2. Prepare an input

#3. Call a method

#4. Check an output

#5. Tear down/AfterEach/After

#1. Setup / Before

before(function(done) {

// Create a basic document.

document = jsdom.jsdom();

window = document.parentWindow;

done();

});

BASIC STRUCTURE: EXPLAINED

Before / BeforeEach

before(function() { console.log(‘before test’); });

test(‘first test’, function() { console.log(‘first test’); });

test(‘second test’, function() { console.log(‘second test’);});

afterEach(function() { console.log(‘after each test’); });

Result

before test

first test

after each test

second test

after each test

BASIC STRUCTURE: EXPLAINED

BASIC STRUCTURE: EXPLAINED

it('should initialize cursor if zoom level >= minimum zoom

level.',

#2. Prepare an input and predicted result.

var minZoomLevel = 1;

var zoomLevel = minZoomLevel + 0.1;

var expectedCursor = {‘color’: ‘white’, ‘height’: … };

#3. Call a method.

var actualCursor = cursor.init(zoomLevel);

#4. Check an output.

expect(actualCursor).to.deep.equal(expectedCursor);

done();

});

function(done) {

BASIC STRUCTURE: EXPLAINED

it('should initialize cursor if zoom level >= minimum zoom

level.',

#2. Prepare an input and predicted result.

var minZoomLevel = 1;

var zoomLevel = minZoomLevel + 0.1;

var expectedCursor = {‘color’: ‘white’, ‘height’: … };

#3. Call a method.

var actualCursor = cursor.init(zoomLevel);

#4. Check an output.

expect(actualCursor).to.deep.equal(expectedCursor);

done();

});

function(done) {

BASIC STRUCTURE: EXPLAINED

it('should initialize cursor if zoom level >= minimum zoom

level.',

#2. Prepare an input and predicted result.

var minZoomLevel = 1;

var zoomLevel = minZoomLevel + 0.1;

var expectedCursor = {‘color’: ‘white’, ‘height’: … };

#3. Call a method.

var actualCursor = cursor.init(zoomLevel);

#4. Check an output.

expect(actualCursor).to.deep.equal(expectedCursor);

done();

});

function(done) {

BASIC STRUCTURE: EXPLAINED

it('should initialize cursor if zoom level >= minimum zoom

level.',

#2. Prepare an input and predicted result.

var minZoomLevel = 1;

var zoomLevel = minZoomLevel + 0.1;

var expectedCursor = {‘color’: ‘white’, ‘height’: … };

#3. Call a method.

var actualCursor = cursor.init(zoomLevel);

#4. Check an output.

expect(actualCursor).to.deep.equal(expectedCursor);

done();

});

function(done) {

#5. TearDown / After

after(function(done) {

// Remove global objects document.

document = null;

window = null;

done();

});

BASIC STRUCTURE: EXPLAINED

OUTPUT

<testsuite name="Macchiato Tests" tests="13"

failures="0" errors="0" skipped="0"

timestamp="Mon, 02 Dec 2013 11:08:09 GMT"

time="0.114">

<testcase classname = "cursor #init ()"

name = "should initialize cursor if

zoom level &gt; minimum zoom level."

time="0.004"/>

</testsuite>

OUTPUT: SUCCESS

<failure classname="cursor #init()"

name="should initialize cursor if zoom level

&gt; minimum zoom level." time="0"

message="Cannot read property 'show' of

undefined"><![CDATA[TypeError: Cannot read

property 'show' of undefined

// ..... Exception Stack Trace .....

</failure>

OUTPUT: FAILURE

TOOLS

TOOLS

> 40 frameworks & libraries

qUnit(TDD) light-weight TDD framework

Jasmine(BDD) flexible BDD framework

Mocha / Karma test runner for async code

+ Chai TDD / BDD assertion library

+ Sinon test spies, stubs & mocks

ENTIRE SPACE OF FRAMEWORKS…

HOW DO I UNIT TEST Known Frameworks / Libraries?

What to test? What to use?

Angular, React, Flight Karma + Jasmine

Backbone qUnit

Ember Karma + qUnit (ember-app-kit)

ExtJs Jasmine, Siesta (UI)

TypeScript tsUnit

CoffeeScript qUnit

Dart Unittest, Hop and Drone.io

NodeJs expresso and vows, Nodeunit

TOOLS: WHAT WE USE

Run UT: Mocha

Run UT in parallel: Macchiato

Assert/Expect: Chai

W3C DOM in JavaScript: Jsdom

Mock, spy, stub: Sinon

Code coverage tool: None

Routine automation: make/Grunt

TOOLS: WHAT WE USE

TOOLS: WHAT WE USE

Project unit tested like a dream ♥

UNIT TESTING SPECIFICS IN JAVASCRIPT

UI

Load fake data via “fixtures”

Jsdom(W3C JavaScript implementation)

UNIT TESTING SPECIFICS IN JAVASCRIPT

AJAX

Stub jQuery.ajax

Fake XMLHttpRequest(XMLHTTP ActiveXObject)

Fake server

UNIT TESTING SPECIFICS IN JAVASCRIPT

3rd-party scripts

Stubbing jQuery plugin functions

(mock jQuery.fn)

UNIT TESTING SPECIFICS IN JAVASCRIPT

Dependency Injection

Mocking deps in RequireJs sucks hard!

Squire.js lib / testr.js

UNIT TESTING SPECIFICS IN JAVASCRIPT

NodeJs

Server-side specifics

rewire: node.js dependency injection

BEST PRACTISES

Fast

Isolated

Consistent

Responsibility

Self-descriptive

No exception Handling

Use assertions when needed

WRAPPING UP

Each test verifies a small chunk of code

Unit tests work best in isolation

Mocks, stubs and spies help to isolate test

Don’t test everything but write many tests

> 40 tools are available to ease unit testing

experience, so CHOOSE YOUR OWN!

SHWEEET

ありがとう

top related