node.js moduly a testovanie

31
Node.js Moduly @sotosof @danielharcek

Upload: harcek

Post on 20-Aug-2015

776 views

Category:

Technology


6 download

TRANSCRIPT

Node.js Moduly

@sotosof @danielharcek

Obsah

Kto smeModulyNPMPackage.jsonStrukturaExports / RequireProcess.NextTick

Vela o testovani :)

Kto sme

Online marketing

Robili sme:● M 2 N affiliate platformu● campaign management and reporting ● tag management● campaign attribution / selective cookie call● ad server with different targeting models including behavioral targeting

Teraz robime @novosense:● Persistent user tracking platformu● Cloud cookie● Realtime activity maps & user engagement

Technologicky stack

Server:● Node.js (predtym nativne Apache moduly)● Python

Data:● Cassandra● Redis● Couchbase

Komunikacia:● RabbitMQ

a samozrejme aj PHP a MySQL ;)

Moduly

Jasna vec deporkifikacia kodu / DRY, znovupouzitelnost, izolacia kodu a decoupling, vyssia kombinovatelnost

Druhy modulov v Node.js*:● c/c++ binding● kniznica● command line program● server / website (nie framework - uz kompletna implementacia)

Nevynaliezajte "koleso":● https://github.com/joyent/node/wiki/Modules kategorizovany zoznam● http://search.npmjs.org/ a http://toolbox.no.de/ vyhladavace

* Podla http://howtonode.org/how-to-module

Balicky (CommonJS 1.0)

npm [http://npmjs.org/doc/]● kto "Noduje" tak sa s nim stretol● od Node.js v0.6+ bundlovany s Node● CLI sprava a distribucia balickov● popisuje interface k balickom prostrednictvom package.json suboru v

roote projektu

Co je balicek (a formy distribucie pre npm install)● adresar obsahujuci program popisany package.json● tar.gz obsahujuci package.json alebo URL na tar.gz● meno / meno@verzia / meno@tag publishnuty v NPM registri● GIT repository obsahujuce package.json

Privatny NPM register? Da sa http://npmjs.org/doc/registry.html

Struktura balicku (layout podla CommonJS)

/bin spustitelne subory

/doc/example/lib tu prebyva nas modul / javascript kod

/test.npmignore funguje ako .gitignore

index.js automaticky berie ako main include pre adresar

package.jsonREADME.md slusnost kaze zvlast ak chceme npm publish

package.json [http://npmjs.org/doc/json.html]

npm init je carovny :) a interaktivny

About to write to /Users/daniel/Desktop/todo/rubyslava/package.json

{

"author": "kolektiv autorov :)",

"name": "simple_remote_logger",

"description": "Intended to be used as remote javascript console.",

"version": "0.0.1",

"main": "./index",

"scripts": {

"test": "mocha test/*.js"

},

"engines": {

"node": "~0.6.7"

},

...

package.json rucne upravy

Semantic version ranges http://npmjs.org/doc/json.html#dependencies

podla potreby doplnime zavislosti"dependencies" : {

"commander" : "=0.6.x" // doporucuje sa }

vyvojove zavislosti test fw, docu fw..."devDependencies" : {

"mocha" : "" // matches any version}

ak ideme npm publish pridame keywords"keywords" : ["remote", "console"]

package.json goodies

● "files" pole definijuce subory / adresare ktore ma projekt obsahovat, toto je lepsie riesit asi cez .npmignore

● "bin" kolekcia spustitelnych suborov ktore sa maju nainstalovat do PATH

● "scripts" script commandy spustitelne v roznych fazach zivotneho cyklu balicka

● "config" konfiguracne parametre pre scripty

● "publishConfig": {"registry": URL } prikaze publikovat do definovaneho registra

● "private" true / false povoluje alebo zamedzuje publikovanie balicka vo vseobecnosti

module.exports

Lokalne premenne modulu su privatne. Nedeklarujeme NIC bez var lebo zmrsime global scope. Ako rozhranie modulu sluzi module.exports. Je to objekt (kolekcia) zdielany medzi vsetkymi "instanciami" modulu.

var default_name = 'John';var say_hello = function(name) { console.log('Hello ' + (name ? name : default_name) + '!'); };module.exports.def_name = default_name;module.exports.say = say_hello;

Priradit mu ale mozeme aj akykolvek platny Javascript typ (boolean, number, date, string, function, array, object etc.)

var Server = function(resource_path) { ... }module.exports = Server;

exports vs. module.exports

exports nepouzivat !!!, je to vlastne "alias" vytvoreny k module.exports. Module system za nas urobi

var exports = module.exports;

Pokial pridavame properties tak je to ok. Akonahle ale chceme priradit nieco "by assignment" tak vlastne len prepiseme referenciu na module.exports a modul exportuje prazdny objekt.

exports = 'jezisko'; // jezisko von nepride

zauzivane je exports = module.exports = ...

require()

Nacita modul a vrati jeho exports. Moduly su cachovane po prvom nacitani, takze kazdy call require('moj_modul') vrati ten isty objekt (vynimka moze byt ak exportujeme "by assignment" - tam zalezi od toho co priradime priamo do module.exports).

var greeting = require('./say_hello');var def_name = require('./say_hello').def_name; // priame require konkretnej property exportu modulu je moznegreeting.say();

$ node main.jsHello John!

require()

Tri sposoby pouzivania require● var foo = require('./lib/foo') relativna cesta● var foo = require('/home/foo/lib/foo') absolutna cesta● var foo = require('foo') search

Pri loadovani modulov idealne pouzivat search - drzat sa pravidla ze vsetky dependencies by mali byt instalovane lokalne (voci danemu modulu).

Require cohokolvek v ramci modulu (okrem modulov) relativne.http://npmjs.org/doc/faq.html#Why-can-t-npm-just-put-everything-in-one-place-like-other-package-managers

Process.NextTick

Sluzi na odlozenie vykonania ulohy, callbacku do dalsieho cyklu event loopu (narocne CPU tasky je ale idealne oddelit do zvlast procesu - s nimi mozeme komunikovat tiez cez eventy, eventualne pouzit WebWorkers). Tak neblokuje vykonavany kod a je vykonany skutocne asynchronne.

var net = require('net');var client = net.connect(8124, function() { //'connect' listener console.log('client connected'); client.write('world!\r\n');});

npm workflow

npm adduser

npm init

npm publish // v roote modulu

npm unpublish name

npm finticky

npm link / npm unlink (alebo vymazat symlink)Ak mame modul ktory je vyvoji a nie je publishnuty tak jednoduchsie ako ho stale instalovat je pouzit npm link. To vytvori symlink v global mode. Potom ho mozeme linkovat kde potrebujeme / odkazovat nan v dependencies.

npm root podla adresara v ktorom sa nachadzame nam vypise kde idu moduly

npm pack z hocicoho instalovatelneho vytvori tarball

npm prune vycisti node_modules od balikov ktore nie su v dependencies

Testovanie

Znova jasna vec● odhalovanie chyb● chyby po update● opatovne zanesenie chyb● test funkcionality robi to to co ma?

● automatizacia nech na to mysli stroj a nie ja

Najbeznejsie sa stretavame s● unit testmi funkcie, subrutiny, metody

● funkcnymi testmi cely program s roznymi vstupmi

Testy? Bitch please...

"Test je prvy pouzivatel tvojho kodu."

Zakladne pravidla testov● F ako Fast Preco hrate CS? Lebo bezia testy :).

● I ako Isolated Test ma testovat iba jedno spravanie a ma byt izolovany.

● R ako Repeatable Musi vratit vzdy rovnake vysledky.

● S ako Self-Verifying Ma zlyhat koli jednoznacnemu dovodu.

● T ako Timely Testy sa pisu predtym ako je hotovy produkcny kod.

pisanie Test-After Development je evil

Ako ich pisat v Javascripte

Netestovat privatne metodyassertEqual(val, component._pseudoPrivateFunc());

Netestovat privatny statusassertEqual(val, component._pseudoPrivateAttribute);

Netestovat privatne zavislostivar obj = new FooComponent();var spy = sinon.spy(obj.dependency._pseudoPrivateFunc);obj.doSomething();assertTrue(spy.called);

Ako ich pisat v Javascripte contd.

Netestovat viacere operacie v jednom testeobj.doSomething();this.assertEqual(expected, obj.attr);obj.doSomethingElse();this.assertEqual(different, obj.attr);

Mocknut vsetky zavislostivar dep = sinon.mock({mockedFunc: function() {return true;}});objToTest.setDep(dep);

Testovat spravanie public interface objektu

Test styles TDD (xUnit)

buster.testCase("My thing", { "foo": function () { assert.equals(foo, "bar"); },

"state": function () { assert(true); }})

my sme zvyknuti na xUnit

Test styles BDD

describe("My thing", function () { it("equals of foo and bar failes", function () { expect("foo").toEqual("bar"); });

it("states the obvious", function () { expect(true).toBe(true); });});

Test styles qUnit

test("a basic test example", function() { ok(true, "this test is fine"); var value = "hello"; equals("hello", value, "We expect value to be hello");});

module("Module A");

test("first test within module", 1, function() { ok(true, "all pass");});

Test runners

Je ich vela, "uceleny" framework existuje v beta verzii.

Najznamejsie● mocha● buster● vows● zombie.js● jsTestDriver

Zacali sme s mocha lebo ma runner pre kazdy styl, vela reporterov (pristavanie lietadla), code coverage report, nezavislost od assertovacej libky. Nema assertation count :(

Assertations

O tomto je testovanie.

Najznamejsie● chai.js● should.js

Idealny stav je jeden assert v teste (I ako Isolated). Nie vzdy to musi byt pravidlo.

Message ma pomoct pri pochopeni assertu.

Spy, Stub and Mock

● simulovanie zavislosti● overovanie volani● predprogramovane ocakavania

Ale nie privatnych!

Ak to test vyzaduje moze to znamenat ze objekt je moc zlozity. Treba porozmyslat nad rozdelenim logiky do viacerych objektov (zavislosti), ktore uz ide mocknut lahko.

Buster

"Uceleny" framework v pouzitelnej verzii.

Spaja vsetky skvele funkcie ostatnych runnerov do jedneho.

● testovanie v node aj v browseroch (aj vo viacerych naraz)

● assertations and refutes (minitest v ruby)● obsahuje sinon.js a podporuje definiciu vlastnych

asertacii● moznost automatizacie● ...● bude aj podpora BrowserStack

Testy modulu

Nejake zdrojaky.

Makefile

Kamarat automatizacie

make test

make test-xml

a npm

npm test