iii - better angularjs

128
<web/F> Better Angular.js Misnomer, myth and Angular.js goliath

Upload: webf

Post on 19-Aug-2015

58 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: III - Better angularjs

<web/F>

Better Angular.js Misnomer, myth and Angular.js goliath

Page 2: III - Better angularjs

<web/F> <web/F>

TDD Test driven development

Page 3: III - Better angularjs

<web/F> <web/F>

Test driven development

TDD is a game of chess

A best practice could be:

“Never lose a piece without winning a piece of equal or

greater value.”

Page 4: III - Better angularjs

<web/F> <web/F>

Test driven development

• In reality, there are no rules/best practices

• There are always situations, responses to those situations and

observations recorded for future reference.

Page 5: III - Better angularjs

<web/F> <web/F>

TDD

Does Test Driven Development means – write tests first and then code

later to pass those tests?

Probably not…

Page 6: III - Better angularjs

<web/F> <web/F>

Idea of TDD

• TDD is about testability.

• TDD is about writing testable code.

• It is not about writing unit test first.

Page 7: III - Better angularjs

<web/F> <web/F>

Testable code

• Probably the most important aspect of TDD is readability.

• We spend more time on reading a code than writing it. And the goal

of TDD is to generate a testable code that is easy to read while not

sacrificing its performance.

• Can we call readable code as maintainable code?

Page 8: III - Better angularjs

<web/F> <web/F>

Testable code

• On the surface, testable code is

• Efficient

• As simple as possible

• DRY – Doesn’t repeat

• Modular

Page 9: III - Better angularjs

<web/F> <web/F>

Testable code

• Inside, testable code has

• Encapsulation

• Loose coupling

• Separation of concern

• Zero to fewer global objects

• Optimized design patterns

Page 10: III - Better angularjs

<web/F> <web/F>

TDD on front-end Does TDD ideology holds true for front-end

Page 11: III - Better angularjs

<web/F> <web/F>

What happens when we move to front-end?

Page 12: III - Better angularjs

<web/F> <web/F>

But on front-end

• Testability is problematic,

• Because, though HTML, CSS and JS are three pieces of same stack,

each of them is a stack in itself.

Page 13: III - Better angularjs

<web/F> <web/F>

On front-end

• The problem is

• We mix HTML, CSS and JS at will

• Concept of encapsulation is very vague

Page 14: III - Better angularjs

<web/F> <web/F>

function implementSomeBusinessLogic() {

// Some business logic

var data = getLatestData();

var $div = $("<div></div>");

// Mixing HTML with JavaScript

$div.text("Data: " + data);

// Mixing CSS with JavaScript

$div.css("color", "red");

// DOM Manipulation mixed with Business Logic

$(body).append($div);

}

Mixing Presentation, DOM & Business logic at

will.

Page 15: III - Better angularjs

<web/F> <web/F>

function UserList(items) {

this._items = items;

}

UserList.prototype.render = function () {

var $list = $("#userList");

this._items.forEach(function (item) {

$("<li>").text(item.name).appendTo(list);

});

}

UserList.prototype.search = function () { }

Is this a good encapsulation?

Page 16: III - Better angularjs

<web/F> <web/F>

Angular to rescue Core design and philosophy of Angular.js

Page 17: III - Better angularjs

<web/F> <web/F>

Here comes the Angular

• That is exactly where Angular ratifies & embraces these problems

• Three pillars of Angular

Page 18: III - Better angularjs

<web/F> <web/F>

Three Pillars of Angular

• Updating view (HTML/DOM)

should be very trivial

• And that is the first pillar of

Angular.js – Data Binding

DRY – Do not Repeat Yourself

DB – Two way Data Binding

Page 19: III - Better angularjs

<web/F> <web/F>

Three Pillars of Angular

• There should be proper separation

of concern and for that you need

structure.

• That is the second pillar of

Angular.js – Directives

• Then there are controllers, services,

routers, etc.

Structure

Directives

Page 20: III - Better angularjs

<web/F> <web/F>

Three Pillars of Angular

• It is not enough to use

framework which is thoroughly

tested. Code on top of it should

also be readily testable.

• That is the third pillar –

Dependency Injection

Page 21: III - Better angularjs

<web/F> <web/F>

TDD & Angular How does Angular helps write testable code?

Page 22: III - Better angularjs

<web/F> <web/F>

Angular is solving many trivial front-end

problems.

Page 23: III - Better angularjs

<web/F> <web/F>

Problem 1

Modules

Testable design is always modular. There is no exception.

Page 24: III - Better angularjs

<web/F> <web/F>

Code organization - Modules

• Any large scale apps needs modules to organize and group related

components.

• Modules help create logical boundaries within system.

• Angular.js modules existed long before ES6 or Common.js modules

Page 25: III - Better angularjs

<web/F> <web/F>

Organizing angular app into modules

Page 26: III - Better angularjs

<web/F> <web/F>

But angular modules are yin and yang

There is beast and then there is beauty.

Page 27: III - Better angularjs

<web/F> <web/F>

Angular.js Modules – beasts

• No support for namespace

• Probably most criticized aspect of Angular.js modules

• No support for lazy loading

• Practically useless for any other libraries

• Not very intuitive to encapsulate CSS

Page 28: III - Better angularjs

<web/F> <web/F>

The idea is to use modules for what they are

supposed to be used for.

Angular.js module is like a bag that holds one or more recipes.

Page 29: III - Better angularjs

<web/F> <web/F>

Angular.js Modules – Beauty

• Logical separation

• Provide better abstractions

• Lazy instantiation

• Module is not instantiated until required

• Dependency organization

• Small modules makes for a bigger modules

Page 30: III - Better angularjs

<web/F> <web/F>

Angular.js Modules – Why

• Code reuse

• Module can be replaced and developed in parallel.

• Better separation of concern

• Config and Run blocks

• Config and run blocks respect dependency tree.

• Code decoration

Page 31: III - Better angularjs

<web/F> <web/F>

Two controllers with same name

(function () {

var app = angular.module("HigherModule", []);

app.controller("ControllerSameName", function () {

this.title = "Defined once (1)";

});

app.controller("ControllerSameName", function () {

this.title = "Defined twice (2)";

});

})();

Page 32: III - Better angularjs

<web/F> <web/F>

Two controllers with same name in different modules

(function () {

var lowerModule = angular.module("LowerModule", []);

var app = angular.module("HigherModule", ["LowerModule"]);

app.controller("ControllerSameName", function () {

this.title = "Defined at Higher Module (2)";

});

lowerModule.controller("ControllerSameName", function () {

this.title = "Defined at Lower Module (1)";

});

})();

Page 33: III - Better angularjs

<web/F> <web/F>

Modules – name spacing

• Often misused approach

• Dot notation approach

• Typically observed when backend programmer do Angular without JavaScript

understanding

Page 34: III - Better angularjs

<web/F> <web/F>

Two controllers with same name in different modules

var lowerModule = angular.module("LowerModule", []);

var app = angular.module("HigherModule", ["LowerModule"]);

app.controller("HM.ControllerSameName", function () {});

lowerModule.filter("LM.customFilter", function () {});

Page 35: III - Better angularjs

<web/F> <web/F>

Ideal name spacing technique for handling collisions

var lowerModule = angular.module("LowerModule", []);

var app = angular.module("HigherModule", ["LowerModule"]);

app.controller("hmControllerSameName", function () { });

lowerModule.filter("lmCustomFilter", function () { });

Page 36: III - Better angularjs

<web/F> <web/F>

Problem 2

Separation of Concern

(Directives, controllers and services)

Testable design adheres to high cohesion along with well defined separation of concern.

Page 37: III - Better angularjs

<web/F> <web/F>

Separation of concern – Directives

• Directive are heart of Angular.js

• Separation of concern

• DOM manipulations are abstracted away inside directives.

• Services abstract away server side communication.

• Promoting ideal component encapsulation

Page 38: III - Better angularjs

<web/F> <web/F>

What is directive in Angular.js?

Directive is something that extends the meaning

of HTML.

Page 39: III - Better angularjs

<web/F> <web/F>

More than one directive with same name?

(function () {

var app = angular.module("HigherModule", []);

app.directive("mySimpleDir", function () {

return { /* DDO */};

});

app.directive("mySimpleDir", function () {

return { /* DDO */};

});

})();

Page 40: III - Better angularjs

<web/F> <web/F>

Idea of extending HTML

• Extension in software programming roughly translates to

• Inheritance

• New meaning

• Overriding existing meaning

• Polymorphism

• Extending the meaning of existing items

Page 41: III - Better angularjs

<web/F> <web/F>

Directives – Idea of extension

Thus directives are allowed to extend the meaning… Period.

Page 42: III - Better angularjs

<web/F> <web/F>

Overriding default browser behavior

(function () {

var app = angular.module("HigherModule", []);

// Extending browser autofocus attribute

app.directive("autofocus", function () {

return { /* DDO */};

});

})();

Page 43: III - Better angularjs

<web/F> <web/F>

Problem 3

Loose Coupling

(Dependency Injection and Angular Bootstrapping)

Software design without loose coupling is never testable.

Page 44: III - Better angularjs

<web/F> <web/F>

Loose coupling

• Loose coupling – IoC (Inversion of Control)

• Don’t call me; I will call you

• It is always Angular that initiates the call

• Example,

• Angular decides when to instantiate controller

• Angular is responsible for loading templates

Page 45: III - Better angularjs

<web/F> <web/F>

Idea of IoC – Inversion of Control

Main Traditional jQuery style

Page 46: III - Better angularjs

<web/F> <web/F>

Idea of IoC – Inversion of Control

Main Main Dependency Injector

Traditional jQuery style

This is how Angular does it

Page 47: III - Better angularjs

<web/F> <web/F>

Dependency injection

• Angular implements IoC using DI

• DI internally uses Service Locator pattern

• To understand DI, we have to understand Angular bootstrapping

Page 48: III - Better angularjs

<web/F> <web/F>

Angular bootstrap process

Diagram does not illustrate the broader picture. So let’s try to drill down further…

Page 49: III - Better angularjs

<web/F> <web/F>

Angular composition

This is what Angular is made up of

Page 50: III - Better angularjs

<web/F> <web/F>

Angular composition

These boxes are objects communicating with each other. That’s the need for DI.

Page 51: III - Better angularjs

<web/F> <web/F>

Angular composition

These objects are angular components

Filters

Controllers

Services

Constants

Providers Directives

Factories

Values

Page 52: III - Better angularjs

<web/F> <web/F>

Angular composition

Special Objects

Controllers

Directives

Filters

Animations

Custom objects

Services

The world of Angular can be categorized into

The only catch is they should be singleton.

Angular calls these customer objects as services.

Page 53: III - Better angularjs

<web/F> <web/F>

Creating various angular objects

• To create Angular.js objects (custom objects or special objects),

use providers:

• $controllerProvider

• $compileProvider

• $filterProvider

• $provide (service Provider)

• Beware of Internet/Google/Angular.js docs

https://docs.angularjs.org/api/auto/service/$provide

Page 54: III - Better angularjs

<web/F> <web/F>

Angular bootstrap process

ANGULAR TWO DISTINCT PHASES

C o n f i g u ra t i o n P h a s e R u n P h a s e

Page 55: III - Better angularjs

<web/F> <web/F>

Angular bootstrap process

Use different providers to register your

components/classes/objects with Angular

modules. Angular calls it recipes for

object creation; C o n f i g u ra t i o n P h a s e

module.config();

Page 56: III - Better angularjs

<web/F> <web/F>

Angular bootstrap process

Instantiate objects from the

components/classes registered during

configuration phase. R u n P h a s e

module.run();

Page 57: III - Better angularjs

<web/F> <web/F>

Angular bootstrap process

Browser HTML page

Wait for DOM ready

Search ng-app=“module”

Initialize $injector

.config()

.run() Start playing with DOM

IoC – Inversion of Control

Page 58: III - Better angularjs

<web/F> <web/F>

Code sample with config block

(function () {

var app = angular.module("HigherModule", []);

app.config(function ($controllerProvider) {

$controllerProvider.register("MyCtrl", function () {

var vm = this;

vm.title = "My Title";

});

});

})();

Page 59: III - Better angularjs

<web/F> <web/F>

Reduced boilerplate code

app.controller("MyCtrl", function () {

var vm = this;

vm.title = "My Title";

});

Page 60: III - Better angularjs

<web/F> <web/F>

Creating a directive

app.config(function ($compileProvider) {

$compileProvider.directive("mySimpleDir", function () {

// DDO - Directive Definition Object

});

});

app.directive("mySimpleDir", function () {

// DDO - Directive Definition Object

});

Page 61: III - Better angularjs

<web/F> <web/F>

Built in objects in Angular

• Angular understands:

• Controllers

• Filters

• Directives

• Animation

Built in object Corresponding providers

Controller $controllerProvider

Filter $filterProvider

Directive $compileProvider

Animation $animationProvider

Page 62: III - Better angularjs

<web/F> <web/F>

Can we call providers as Classes in plain old

JavaScript?

Page 63: III - Better angularjs

<web/F> <web/F>

Creating custom objects

• Remember, Customer objects are called services in Angular

• To create any object in Angular you need provider

• To create custom object, custom provider is necessary

• For that purpose, we need a provider that can create new provider

which is sort of meta provider

Page 64: III - Better angularjs

<web/F> <web/F>

About custom objects

• One condition by Angular.js

• Custom Objects (services) should be Singletons

• It is enforced at Framework level by Angular

• One assumption by Angular.js

• Custom Objects should hold your data

Page 65: III - Better angularjs

<web/F> <web/F>

Comes $provide app.config(function ($provide) {

$provide.provider("calculator", function () {

this.$get = function () {

return {

add: function () { },

subtract: function () { }

};

};

});

});

Page 66: III - Better angularjs

<web/F> <web/F>

Using custom object

app.controller("MyCtrl", function (calculator) {

calculator.add();

calculator.subtract();

});

Page 67: III - Better angularjs

<web/F> <web/F>

Reducing boilerplate – Why so verbose?

app.provider("calculator", function () {

this.$get = function () {

return {

add: function () { },

subtract: function () { }

};

};

});

Page 68: III - Better angularjs

<web/F> <web/F>

Providers are still verbose

&

weird way to create objects

Page 69: III - Better angularjs

<web/F> <web/F>

How we do it in plain old JavaScript?

(function () {

function Calculator() {

this.add = function () { };

this.substract = function () { };

}

var calculator = new Calculator();

})();

Page 70: III - Better angularjs

<web/F> <web/F>

Comparing plain JS and Angular

(function () {

function Calculator() {

this.add = function () { };

this.substract = function () { };

}

var calculator = new Calculator();

})();

app.provider("calculator", function

() {

this.$get = function () {

return {

add: function () { },

subtract: function () { }

};

};

});

Page 71: III - Better angularjs

<web/F> <web/F>

So Angular is creating syntactic sugar

app.service("calculator", function () {

this.add = function () { };

this.substract = function () { };

});

Page 72: III - Better angularjs

<web/F> <web/F>

Comparing two syntax

app.service("calculator", function () {

this.add = function () { };

this.substract = function () { };

});

app.provider("calculator", function

() {

this.$get = function () {

return {

add: function () { },

subtract: function () { }

};

};

});

Page 73: III - Better angularjs

<web/F> <web/F>

What angular is doing internally

app.service("calculator", function () {

this.add = function () { };

this.substract = function () { };

});

app.service = function (name, Class) {

app.provider(name, function () {

this.$get = function ($injector) {

return

$injector.instantiate(Class);

};

});

}

Page 74: III - Better angularjs

<web/F> <web/F>

Some are not comfortable with new

function calculatorFactory() {

var obj = {};

obj.add = function () { };

obj.substract = function () { };

return obj;

}

var calculator = calculatorFactory();

Enter the factory pattern

Page 75: III - Better angularjs

<web/F> <web/F>

Angular has solution for that

function calculatorFactory() {

var obj = {};

obj.add = function () { };

obj.substract = function () { };

return obj;

}

var calculator = calculatorFactory();

app.factory("calculator", function ()

{

return {

add: function () { },

substract: function () { }

};

});

Page 76: III - Better angularjs

<web/F> <web/F>

Angular factory pattern

app.factory("calculator", function ()

{

return {

add: function () { },

substract: function () { }

};

});

app.factory = function (name, factory) {

app.provide(name, function () {

this.$get = function ($injector) {

return $injector.invoke(factory);

};

});

}

Page 77: III - Better angularjs

<web/F> <web/F>

Then there are other recipes

app.constant("STATES", {

DASHBOARD: "dashboard",

LIST: "projectList"

});

app.value("calculator", function

() { });

app.value("PI", 3.1422);

app.value("welcome", "Hi,

Harsh");

Page 78: III - Better angularjs

<web/F> <web/F>

But, yes providers are powerful

app.provider("greeting", function () {

var text = "Hello, ";

this.setText = function (value) {

text = value;

};

this.$get = function () {

return function (name) {

alert(text + name);

};

}; });

app.config(function (greetingProvider) {

greetingProvider

.setText("Howdy there, ");

});

app.run(function (greeting) {

greeting("Harsh Patil");

});

Page 79: III - Better angularjs

<web/F> <web/F>

Angular core - $injector

• So far, we have just seen how to bootstrap angular. But how does

Angular executes in run phase?

Page 80: III - Better angularjs

<web/F> <web/F>

$injector internals

app.value("val", "");

app.constant("CON", 123);

app.controller("MyCtrl", function () { });

app.factory(“myFactory",

function () { });

Instance Factory

Instance Cache

Service Locator

$injector

$injector.get("myFactory");

Page 81: III - Better angularjs

<web/F> <web/F>

Problem 4

Using optimized design patterns

Testable software design implements well thought design patterns

Page 82: III - Better angularjs

<web/F> <web/F>

Typical Ajax Request example

var http = new XMLHttpRequest(),

url = "/example/new",

params = encodeURIComponent(data);

http.open("POST", url, true);

Page 83: III - Better angularjs

<web/F> <web/F>

Typical Ajax Request example

http.setRequestHeader("Content-type",

"application/x-www-form-urlencoded");

http.setRequestHeader("Content-length", params.length);

http.setRequestHeader("Connection", "close");

Page 84: III - Better angularjs

<web/F> <web/F>

Typical Ajax Request example

http.onreadystatechange = function () {

if (http.readyState == 4 && http.status == 200) {

alert(http.responseText);

}

}

http.send(params);

Page 85: III - Better angularjs

<web/F> <web/F>

Same thing with Angular

$http({

method: "POST",

url: "/example/new",

data: data

})

.then(function (response) { alert(response); });

Page 86: III - Better angularjs

<web/F> <web/F>

Problem 5

Data Binding

DOM updates should be very trivial. This is the magic of angular.

Page 87: III - Better angularjs

<web/F> <web/F>

Plain JS code

// HTML

<button id="myButton"></button>

// JavaScript

var button = document.getElementById("myButton");

button.addEventListener("click", function () {

// Do something

}, false);

Page 88: III - Better angularjs

<web/F> <web/F>

How we do it in Angular

// HTML

<button ng-click="doSomething()"></button>

// JavaScript

app.controller("MyCtrl", function ($scope) {

$scope.doSomething = function () {

// Do something

};

});

Page 89: III - Better angularjs

<web/F> <web/F>

Creating function in JavaScript

// Technique 1

function test() {

// Do something

}

// Technique 2

var test = function () { };

Page 90: III - Better angularjs

<web/F> <web/F>

There is something more to JS

// Technique 3

var test = new Function(arguments, body);

Functions in JavaScript are objects. They can be created just like any other objects.

Page 91: III - Better angularjs

<web/F> <web/F>

What angular is doing internally

// HTML

<button ng-click="doSomething()"></button>

This is a directive

Page 92: III - Better angularjs

<web/F> <web/F>

What angular is doing internally

link: function ($scope, iElement, iAttr) {

iElement.addEventListener("click", function () {

var ngClick = iAttr.ngClick;

var func = new Function([], ngClick);

// Setup Angular watcher ...

func();

// Execute watchers & bindings ...

// Run $scope.digest();

}, false);

}

Page 93: III - Better angularjs

<web/F> <web/F>

Angular digest function

$scope.prototype.$digest = function () {

var self = this;

_.forEach(this.$$watchers, function (watch) {

var newValue = watch.watchFn(self);

var oldValue = watch.last;

if (newValue !== oldValue) {

watch.listenerFn(newValue, oldValue, self);

watch.last = newValue;

}

});

};

Page 94: III - Better angularjs

<web/F> <web/F>

Modern Enterprise Web Apps

Page 95: III - Better angularjs

<web/F> <web/F>

Modern enterprise web application

Page 96: III - Better angularjs

<web/F> <web/F>

Then they evolve

Page 97: III - Better angularjs

<web/F> <web/F>

• There is nothing permanent except change.

Page 98: III - Better angularjs

<web/F> <web/F>

Then it becomes all together different

Page 99: III - Better angularjs

<web/F> <web/F>

Modern enterprise applications

• API

• Third party integrations

• Packages

• Libraries

• Modules

• Legacies

• Versioning

• Limited eye site for individual

developer & tester

• Nearly impossible to test everything

through leaky abstractions

Abstractions leak when you have to understand the lower level concept

to use the higher level concept.

Page 100: III - Better angularjs

<web/F> <web/F>

So how do you write testable code?

• One sure shot way is to write Unit Tests.

Page 101: III - Better angularjs

<web/F> <web/F>

When you write unit tests

• When you start for unit testing, you disintegrate or more accurately

isolate different components of the system.

• That is where you can see system as a set of interconnected

components.

• And so goes for the couplings between components.

Page 102: III - Better angularjs

<web/F> <web/F>

But most unit testing is not proper

• If you do any of this

• Database

• Any kind of server

• File/network I/O or file system

• Another application

• Console

• Logging

• Other classes

Page 103: III - Better angularjs

<web/F> <web/F>

So when do you write unit tests?

• Never do it. Let QA do it

• After some amount of code

• After writing all the code

• Before any code* (Test first)

• At the same time as I write the code

Page 104: III - Better angularjs

<web/F> <web/F>

Unit testing in day to day life

1. Describe the behavior of function in plain English in some readme file.

2. Create a test that is mostly just a copy/paste from the readme code.

3. Write the actual function until it passes the first test.

4. Write a few more tests for any edge cases I can think of.

5. Get the function to pass again

6. Encounter another edge case, go to 4.

Page 105: III - Better angularjs

<web/F> <web/F>

But I find writing unit tests hard

• Because the reality check says unit testing is hard

Page 106: III - Better angularjs

<web/F> <web/F>

To simplify

Categorize unit tests as:

• Level 1 – Isolated classes

• Level 2 – State management

• Level 3 – Internal dependency

• Level 4 – State management, internal dependency & DOM

Page 107: III - Better angularjs

<web/F> <web/F>

Level 1

Isolated Classes/Components

Page 108: III - Better angularjs

<web/F> <web/F>

app.factory("utilsFactory", function () {

return {

constructUrl: function (url, urlParams) {

urlParams = urlParams || {};

Object.keys(urlParams).forEach(function (param) {

url = url.replace(":" + param, urlParams[param]);

});

return url;

}

};

});

No Dependency No state management

Page 109: III - Better angularjs

<web/F> <web/F>

it("utilsFactory should construct url correctly", function () {

var url, params, url;

// Setup data

url = "/api/projects/:projectId"; params = { projectId: 1 };

// Exercise SUT

url = utilsFactory.constructUrl(url, params);

// Verify result (behavior)

expect(url).to.equal("/api/projects/1");

});

Page 110: III - Better angularjs

<web/F> <web/F>

We need supporting code as well

beforeEach(function () {

module("myModule");

inject(function (_utilsFactory_) {

utilsFactory = _utilsFactory_;

});

});

Page 111: III - Better angularjs

<web/F> <web/F>

Level 2

State Management

Page 112: III - Better angularjs

<web/F> <web/F>

app.factory("utilsFactory", function () {

return {

_count: 0,

constructUrl: function (url, urlParams) {

urlParams = urlParams || {};

// ...

this._count++;

return url;

},

};

});

Page 113: III - Better angularjs

<web/F> <web/F>

it("utilsFactory should update _count", function () {

var url, params, url;

// Setup data

url = "/api/projects/:projectId";

params = { projectId: 1 };

// Exercise SUT

url = utilsFactory.constructUrl(url, params);

url = utilsFactory.constructUrl(url, params);

// Verify result (state)

expect(utilsFactory._count).to.equal(2);

});

Page 114: III - Better angularjs

<web/F> <web/F>

Level 3

Internal dependency

Page 115: III - Better angularjs

<web/F> <web/F>

app.factory("projectFactory", function projectFactory($http, urlFactory) {

function _getProjects() {

var request = angular.copy({

method: "GET",

url: urlFactory.get("projects")

});

return $http(request).then(function (response) {

return response.data;

});

}

return { getProjects: _getProjects };

});

Page 116: III - Better angularjs

<web/F> <web/F>

it("projectFactory should return promise", function () {

var promise;

// Setup data

// Exercise SUT

promise = projectFactory.getProject();

// Verify result (state)

expect(promise).to.have.key("then");

});

Page 117: III - Better angularjs

<web/F> <web/F>

it("projectFactory should make call to urlFactory", function () {

var promise;

// Setup data

// Exercise SUT

promise = projectFactory.getProjects();

// Verify result (state)

expect(urlFactory.get).to.have.been.called.once();

});

Page 118: III - Better angularjs

<web/F> <web/F>

it("projectFactory should make call to $http", function () {

var url, promise;

// Setup data

// Setup expectation

$httpBackend.expectGET("/api/users/").respond(200, {});

// Exercise SUT

promise = projectFactory.getProjects();

// Verify result (behavior)

$httpBackend.verifyNoOutstandingExpectation();

$httpBackend.verifyNoOutstandingRequest();

});

Page 119: III - Better angularjs

<web/F> <web/F>

beforeEach(function () {

module("myModule");

inject(function (_projectFactory_, _$httpBackend_, _urlFactory_) {

projectFactory = _projectFactory_;

$httpBackend = _$httpBackend_;

urlFactory = _urlFactory_;

// Mocking

urlMock = sinon.mock(urlFactory);

urlMock.stub("get").when("/api/project").returns("/api/projects");

});

});

Page 120: III - Better angularjs

<web/F> <web/F>

it(“description", function () {

// Setup data

// Setup expectation

// Exercise SUT

// Verify result (behavior)

// Teardown

});

Page 121: III - Better angularjs

<web/F> <web/F>

What do I need to write unit tests?

• Test runner

• Runtime

• Testing suite

• Assertion library

• Mocking library

Page 122: III - Better angularjs

<web/F> <web/F>

Quality of unit tests

A management stake (code coverage)

“I expect a high level of coverage. Sometimes managers

require one. There's a subtle difference.”

“you can't go into production with less than 80% coverage.”

Page 123: III - Better angularjs

<web/F> <web/F>

True use of code coverage

Just like this

Page 124: III - Better angularjs

<web/F> <web/F>

True use of code coverage

Page 125: III - Better angularjs

<web/F> <web/F>

True use of code coverage

80%, 90% is good but 100%

“It would smell of someone writing tests to make the coverage

numbers happy, but not thinking about what they are doing.”

Page 126: III - Better angularjs

<web/F> <web/F>

There are lot many things

• URL design

• Quality matrix

• Verification strategies

• Test doubles

Page 127: III - Better angularjs

<web/F> <web/F>

Thank You Any more questions

Page 128: III - Better angularjs

<web/F> <web/F>

By

Harshal Patil

@mistyharsh