testable javascript

Post on 27-May-2015

1.194 Views

Category:

Business

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Writing testable javascript preso given at YUIConf 2011 (11/3/11) - good times!!!

TRANSCRIPT

Testable Javascript

MARK ETHAN TROSTLER mark@zzo.com@zzoass

http://randomgoo.blogspot.com/

“If today were the last day of my life, would I want to do what I am about to do today?”

KISS

Minimize Your Pain

•Write Small•Write Simple•Test Early•Test Often

Write Small – Write Simple

•Isolate code to test•Loosely couple dependencies•Be obvious•Optimize last

Test Early – Test Often

Test Now

Explicit Dependencies

How things can go wrong…

April 12, 2023

// Call x.flub with twice zfunction foo(z) {

var x = new X(); // Mmmmm tightly coupled…

return x.flub(z*2);}

// We want to test if x.flub was called with 14var back = foo(7);// But only have ‘back’ to test!

April 12, 2023

How can we test only our code?

// Call x.flub with twice zfunction foo(x, z) {

return x.flub(z*2);}

// Test x.flub got called with 14…var x = new MockX(), foo(x, 7);

If (x.called(‘flub’).with(14)) { // a winner!!}

Really see this in constructors…

April 12, 2023

// Ewww – not directly testablefunction MyObject() {

this.x = new X();}

MyObject.Prototpe.foo = function(z) {return this.x.flub(z*2);

}

var test = new MyObject(), back = test.foo(7) // cannot test what foo() did

Inject It - Constructor

April 12, 2023

// Yea! Testable!function MyObject(x) {

this.x = x;}MyObject.Prototpe.foo = function(z) {

return this.x.flub(z*2);}

var x = new MockX(), test = new MyObject(x);

test.foo(7);If (x.called(‘flub’, with(14)) { // We tested only our function!}

Inject It - Setter

April 12, 2023

// Yea! Testable!function MyObject() { }MyObject.prototpe.setX= function(x) { this.x = x;};MyObject.prototpe.foo = function(z) {

return this.x.flub(z*2);};var x = new MockX(), test = new MyObject();test.setX(x);test.foo(7);If (x.called(‘flub’, with(14)) { // We tested only our function!}

YUI

YUI Explicit Dependencies

April 12, 2023

YUI.add(‘myObject’, function(Y) { // Code you want to test Y.MyObject = function() { this.a = new Y.a(); this.b = new Y.b(); this.c = new Y.c(); };}, { requires: [ ‘a’, ‘b’, ‘c’ ] });

YUI.use(‘myObject’, function(Y) { new Y.MyObject();});

Injecting YUI3 Dependencies??

April 12, 2023

YUI.add(‘myObject’, function(Y) { //// Code you want to test Y.MyObject = function(a, b, c) { this.a = a; this.b = b; this.c = c; };});YUI.use(‘myObject’, ‘a’, ‘b’, ‘c’, function(Y) { // Prod new Y.MyObject(new Y.a(), new Y.b(), new Y.c());});YUI.use(‘myObject’, ‘test’, function(Y) { // Test new Y.MyObject(Y.Mock(), Y.Mock(), Y.Mock());});

Isolating Dependencies

April 12, 2023

<script src =“yui3.js”></script><script src =“a.mock.js”></script><script src =“b.mock.js”></script><script src =“c.mock.js”></script><script src =“myObject.js”></script>

<script>YUI.use(‘myObject’, function(Y) { new Y.MyObject();</script>

Injecting YUI3 Dependencies

April 12, 2023

YUI.add(‘myObject’, function(Y) { //// Code you want to test Y.MyObject = function(a, b, c) { this.a = a || new Y.a(); this.b = b || new Y.b(); this.c = c || new Y.c(); };}, { requires: [‘a’, ‘b’, ‘c’ ] });YUI.use(‘myObject’, function(Y) { // Prod new Y.MyObject();});YUI.use(‘myObject’, ‘test’, function(Y) { // Test new Y.MyObject(Y.Mock(), Y.Mock(), Y.Mock());});

Injecting YUI3 Dependencies

April 12, 2023

YUI.add(‘myObject’, function(Y) { //// Code you want to test Y.MyObject = function() { } Y.MyObject.prototype.setX = function(x) { this.x = x; };}, { requires: [‘a’, ‘b’, ‘c’ ] });YUI.use(‘myObject’, function(Y) { // Prod new Y.MyObject();});YUI.use(‘myObject’, ‘test’, function(Y) { // Test new Y.MyObject().setX(Y.Mock());});

Isolating Dependencies

YUI({ modules: { a: { fullpath: ’/a-mock.js'

} }}).use('test', ’myObject', 'console',

function(Y) { var obj = new Y.MyObject();});

April 12, 2023

Isolating Dependencies

YUI({ filter: mock:

{ 'searchExp': “\\.js", 'replaceStr': "-mock.js" }}).use('test', ’myObject', 'console',

function(Y) { var obj = new Y.MyObject();});

April 12, 2023

Mock Objects

Mock Object

YUI().add(’a', function(Y) { Y.A= function() { var me = Y.Mock(); Y.Mock.expect(me, { method: ”render",

args: [‘#toolbar’] }); return me; }}, '1.0.0' ,{requires:['test']});

April 12, 2023

Testing with Mocked Dependencies

YUI().add(’a', function(Y) { Y.A= function() { return Y.Mock(); };}, '1.0.0' ,{requires:['test']});YUI().use(‘a’, ‘test’, ‘myObject’, function(Y) { var a = new Y.A(); Y.Mock.expect(a, { method: ”render",

args: [‘#toolbar’] }); new MyObject(a).render(); //// verify a.render(‘#toolbar’) was called});

April 12, 2023

Implicit Dependencies

‘Hidden’ Dependencies

Private functions are ‘hidden’ dependencies

Cannot test by definition! Make public? Are they part of the public

API?? Mock them out?? How??

Refactor private function to be explicit dependencies

Minimize their use – they cannot be tested directly

Treated exactly like any other dependency

April 12, 2023

Private functions

April 12, 2023

YOU CANNOT TEST THEM!

Don’t forget browser dependencies!

YUI.add(‘myObject’, function(Y) { //// Code you want to test Y.MyObject = function(window) { this.window = window; }; myObject.prototype.fiddle = function(str) { return

window.escape(str + ‘ FOOBIE’); }; });

YUI.use(‘myObject’, function(Y) { var winMock = new WindowMock(), myObj = new myObject(winMock); myObj.fiddle(‘foobie’); // Check WindowMock!!}

April 12, 2023

Recap

Explicit Deps

Problem: Public dependenciesSymptom: Explicitly declared

dependenciesCure: • Eliminate tightly coupled code/use

injection• Pre-load mock’ed versions of public

dependencies

April 12, 2023

Private Deps

Problem: Private dependenciesSymptom: Private methods and

functionsCure: • Minimize private dependencies• Make public dependency• Use composition to pull in private stuff

April 12, 2023

Browser Deps

Problem: Browser dependenciesSymptom: ‘window’ or global scope

usageCure: • Eliminate tightly coupled code/use

injection• Pre-load mock’ed versions of public

dependencies

April 12, 2023

Unit Testing Principles & Practices

All about dependency management

Identify dependencies and mock them out

Do not take your environment for granted

April 12, 2023

“Don’t Be Foolish”

Resources

• https://github.com/zzo/JUTE• trostler@yahoo-inc.com• @zzoass• http://randomgoo.blogspot.com/

April 12, 2023

top related