Wednesday, February 15, 2012

An Implementation

Get caught up:
Part 1: http://randomgoo.blogspot.com/2012/02/release-event-hub-web-30-introduction.html
Part 2: http://randomgoo.blogspot.com/2012/02/events.html
Part 3: http://randomgoo.blogspot.com/2012/02/event-listeners-get-up-to-speed-first.html
Part 4: http://randomgoo.blogspot.com/2012/02/event-hub.html
Part 5: http://randomgoo.blogspot.com/2012/02/deploying-event-hub-application.html

Quick recap - Web 3.0 is two-way asynchronous programming - events on the way out and another event or a callback on the way back.

I have cobbled together an Event Hub implementation here: https://github.com/zzo/EventHub.
This implementation happens to be in Javascript and it built upon socket.io.  Which means besides being very easy to add to client-side modules, there is support for many languages on the server side including Erlang, Lua, Java, Perl, Go, Python, Ruby, Flash, and of course Javascript.  See the socket.io wiki for details.  The Event Hub itself is also available as an npm package.

The actual Event Hub code is very small.  It actually uses the connect frame work for transport and serves the static socket.io and Event Hub client libraries itself (there are currently 2, one for YUI and another for jQuery - feel free to add more!).  There is also a NodeJS client-library for NodeJS client to connect to the hub.  Check out the examples/ directory for how to use all of this stuff.

You have a couple choices when starting server-side event hub modules.  They can either all be completely separate processes, which is cleanest.  Each server-side module would sit on its own port connected to the event hub completely independent of each other.  They can all be on separate hosts, however you want to do it - they are all completely separate from each other.
You can also start them all up in one shot and multiplex their port amongst them.  While this is perhaps easier to do initially, if you need to restart any one of them you will need to restart all of them.

Let's look at some examples!

Here is a NodeJS EventHub client:

var eventHub = require('eventClient.js')
                     .getClientHub('http://localhost:5883?token=SECRET');

eventHub.on('eventHubReady', 
    function() {
        eventHub.on('HelloWorld', 
            function(data, callback) {
                // SESSION key is in data['eventHub:session']
                callback(null, { mark: 'trostler' });
             }
            , { type: 'unicast' }
        );

        eventHub.on('eventClient:done', 
            function(event) {
                console.log('DONE LISTENING FOR ' + event);
                // wait for us to finish processing any current
                //    event and then....
                process.exit(0);
            }
        );
    }
);

So we connect to the hub using the secret key ('SECRET' in this case). If we successfully connect (because the token is correct) we become a 'trusted' module and can listen for 'unicast' events.
If the connection is established we listen for a 'HelloWorld' event, telling the EventHub this is a 'unicast' event - so only send these events to us. That also means the Hub will sent us an 'eventClient:done' event if someone else comes along and starts listening for this event too - so we also listen for that event. If we get that event we shut ourselves down gracefully. And finally 'trusted' modules will also receive the session key of the client who emitted this event - and will be available to this modules in data['eventHub:session'] in the event data.
Upon receiving a 'HelloWorld' event, we do some processing and call back to the emitted using the supplied callback. We follow the convention that the first argument of the callback is an error object or string if there was an error, and whatever data in the second callback argument.

Now let's look at something that might emit this event:

<html>
<head>
</head>
<body>
 <script src="http://yui.yahooapis.com/3.4.1/build/yui/yui-min.js"></script>
 <script src="http://dashr.net:5883/socket.io/socket.io.js"></script>
 <script src="http://dashr.net:5883/yui3.js"></script>
 <button id="button">Press Me</button>
<script>
    YUI().use('node', 'EventHub', function(Y) {

        var hub = new Y.EventHub(io, 'http://dashr.net:5883');
        hub.on('eventHubReady', function() {
            var helloWorld = hub.addEvent('HelloWorld');
            Y.one('#button').on('click',
                function(event) {
                    helloWorld.fire({ button: 'clicked' },
                        function(error, data) { 
                            Y.log("callback from event listener!");
                        }
                    );
                }
            );
            hub.on('someOtherEvent', function(data, callback) {
                Y.log("Got some other event!");
                callback(null, { hello: "stranger" });
            });
        });
    });
</script>
</body>
</html>

Ok so check it out - first we load the YUI seed (we'll use the YUI EventHub client), socket.io and the YUI event hub library. Note we can load those last two scripts directly from the EventHub itself.
We then connect to the hub and when ready we use a convenience function in the client YUI library to create a 'shortcut' for the HelloWorld event we are going to fire.
So when someone clicks our button we fire the HelloWorld event and set up the callback for the response. At some point the callback comes back and Bob is your uncle.

Listening for events is just as easy, here I'm not using the convenience 'addEvent' method and just listening for 'someOtherEvent' and calling its callback function back when I get it.

The jQuery example is remarkably similar!

<html>
<head>
</head>
<body>
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
 <script src="http://dashr.net:5883/socket.io/socket.io.js"></script>
 <script src="http://dashr.net:5883/jquery.js"></script>
 <button id="button">Press Me</button>
<script>
    var hub = new $.fn.eventHub(io, 'http://dashr.net:5883');
    hub.bind('eventHubReady', function() {
        var helloWorldEvent = hub.addEvent('HelloWorld');
        $('#button').bind('click',
            function(event) {
                console.log('clicked on button - making new event for hub');
                console.log(clickEvent);
                helloWorldEvent.trigger({ button: 'clicked' },
                    function(error, data) { 
                        console.log("callback from event listener!");
                    }
                );
            }
        );
     
        // listen for some other event
        hub.bind('someOtherEvent',
            function(data, callback) {
                console.log('got someOtherEvent');
                console.log(data);
                callback(null, { mark: 'rox' });
            }
        );
    }); 
</script>
</body>
</html>

For jQuery we use the jQuery syntax of 'trigger' and 'bind' instead of 'fire' and 'on' but everything else is pretty much the same. We use the client utility method 'addEvent' for the HelloWorld event but don't for the 'someOtherEvent', totally optional to use the syntactic sugar 'addEvent' provides for you.

It's equally easy to add clients in other languages that socket.io supports - or any language with a Web Sockets library.

Finally starting the event hub is easy:

% node eventHub.js

For now you need to edit 'eventHub.js' itself if you want to change the port (5883) or the secret used to determine trusted clients.

If you installed EventHub using npm try:

% npm start EventHub

Have fun out there and stay tuned for even more!!

Deploying an Event Hub application

Get caught up:
Part 1: http://randomgoo.blogspot.com/2012/02/release-event-hub-web-30-introduction.html
Part 2: http://randomgoo.blogspot.com/2012/02/events.html
Part 3: http://randomgoo.blogspot.com/2012/02/event-listeners-get-up-to-speed-first.html
Part 4: http://randomgoo.blogspot.com/2012/02/event-hub.html

Quick recap - Web 3.0 is two-way asynchronous programming - events on the way out and another event or a callback on the way back.


An oft overlooked key piece to any application is its deployment.  Deploying a 'traditional' HTTP-server based application is a one-shot all-or-nothing affair.  Typically even the smallest server-side change requires a full-blown deploy and restart of all of your HTTP servers.  Well that blows.


Compare with an event-based application consisting of a federation of independent processes that comprise the application.  You only need to deploy and restart small, independent pieces of the application for updates, not the entire thing.


Now it's not all wine and roses (or beer and dandelions).  There is more complexity because there are more pieces.  But small and independent beats large and monolithic even with the extra complexity, of which there isn't that much.


But the biggest issue is dropping events.  HTTP servers have 'graceful' shutdowns, ensuring all current requests are satisfied before shutting down, ensuring remote clients aren't left in the lurch during a restart, what about Event Hubs?


Glad you asked, let's look at the scenarios:


Server Side


1. Broadcast events


Broadcasted events are sent to every connected module.  Each broadcast event listener should listen for a signal or other outside data that tells it to shutdown.  So to shut down and restart a broadcast event listener, simply bring up the newer version of the listener and tell the old one(s) to shutdown.
Like a 'graceful' shutdown the current about-to-be-shutdown listeners should immediately stop listening for the given event, wait until they are done servicing any existing events, and then shut down if that is the only event that module is listening for.


Here is where putting a version number in the event name is also useful.  If using this method bring up the new listener that listens for the new event name with the updated version number and update the clients to use this new event name.  As clients start calling the new event name (with an updated version number in it) the old listeners duties trickle away until it can be safely killed.


2. Unicast Events


This is even easier as the event hub notifies the old listener (via an event) when a new one takes over that it has been replaced and can stop listening for the unicast event.  At that point the listener will finish with any current events its dealing with and then shut down.


So you need only the bring up the newer version of the unicast listener, it will connect to the hub, telling the hub it is the new listener for the given unicast event.  All subsequent unicast events will get passed to the new listener and the old listener will receive a event from the hub telling the old listener that its work is done.


Client-Side


The above two scenarios detail how to shutdown old server-side listeners, what about updating clients?  Welp that is no different than what we currently do when we roll out new client-side web application code: push the code out the the CDN.  Your HTTP server is still around to server the static client-side code.  Subsequent browser refreshes will now get served this new code.  Same deal.
What is more interesting is the client-side code is split into many smaller individual files which can be changed independent of all the other files.  It's not quite as clean as that because for efficiency the small Javascript files would be mashed into one large one and then minified for performance, regardless the process is the same as for current web applications.
Deploying small changes in client-side code is a very interesting topic and I hope someday to learn how to do it better...


The Hub


What about the hub itself?  The time will come when it needs to be restarted for whatever reason.  The best way is to bring up a new hub and bring up another set of listeners that connect to it.  Update client-side code to point to the new hub and push it out.  Wait.  Wait some more.  Eventually traffic to your old hub will cease, then you can shut it down and shut down all the listeners connected to it.
When is safe to shut down the old hub?  Where there is no more client traffic!  We'll look at that in the 'Logging' post coming up soon!


I hope you can see deployment of event-based asynchronous application is more complex because there are more pieces but much more fine-grained and much safer overall.


Stay tuned for Logging, languages, and an implementation!

Tuesday, February 14, 2012

Event Hub

Event Hub


Get caught up:
Part 1: http://randomgoo.blogspot.com/2012/02/release-event-hub-web-30-introduction.html
Part 2: http://randomgoo.blogspot.com/2012/02/events.html
Part 3: http://randomgoo.blogspot.com/2012/02/event-listeners-get-up-to-speed-first.html

Quick recap - Web 3.0 is two-way asynchronous programming - events on the way out and another event or a callback on the way back.


The hub (maybe more like a switch) is pretty dumb with some minimal smarts.


The Dumb


The hub listens on a port for connections from interested modules.  Once connected the hub relays events to all connected modules (yes even back to the module that fired the event - the handler may be there too!).  Nice and dumb.


The Smart


Cry not for our poor hub.  It also has some basic smarts.  The smarts are necessary for 2 separate reasons:


1. sessions
2. trust


Sessions


Each connection to the hub is associated with a session, not an entire session, just a unique identifier.  This identifier, hmmm... identifies a session uniquely.  Didn't I just say that?  Anyway the hub itself does not use the session key, but merely passes it along to 'trusted' modules.  'Trusted' modules can use this identifier to store data associated with this session if they so choose. 
The hub injects the session key into any event arguments before passing the event on to any 'trusted' connected modules.


Trust


Some connected modules are more special than others.  These are typically server-side listeners that do actual work, like updating a database or flipping switches in a nuclear reactor.  Not all modules are created equally.  We wouldn't want just anyone connecting to our hub and responding to the 'reactor:TurnOn' event now would we?  
So a module is 'trusted' by the hub if, upon connection, it provides a secret key shared only by trusted modules and the event hub.  
So what does a 'trusted' module get that a plain old untrusted one doesn't?
It gets 2 things, the session key and responder status.
The session key is mentioned above, it's just a unique key that identifies the event emitter.
'Responder status' means a trusted module gets to listen for certain events, and ONLY that ONE trusted module will be delivered that event.
FOR INSTANCE the 'user:add' event.
Without a trusted listener for that event the 'user:add' event will be broadcast to all modules.  So a 'bad guy' can connect to your event hub and listen for that event and when a good guy tries to create a user (including username and password in the event data) the bad guy will get it.
Even without a bad guy some events only want one listener.  What if I had three modules, trusted ones event, listening for the 'user:add' event?  They would all get the event, the first one would succeed (say by adding the user to the database) while the other 2 would fail, as the user now already exists.  Even worse what about events with callbacks?  The first callback would work and the next 2 callbacks would fail as the callback already happened.


SO events with callbacks can only have ONE listener.  Events that change stuff should only have ONE listener.  That ONE listener should be 'trusted'.


SO the event hub must support trusted modules AND the ability to have only ONE listener for an event.  And as an extra added bonus IF the module is trusted it gets the session key to boot.


Ok stay with me here just about done!  Here's how it all comes together:


Module <-> Event Hub Initialization


Clients, typically browsers or command line clients, connect to the event hub with no special privileges.  They can emit all the events they want, not knowing or caring about all of this 'trust' or 'session' stuff.
Server-side modules can connect to the event hub with a shared key giving them 'trusted' status.  These trusted modules can request to listen for events which they deem 'unicast' using event-listening syntax sugar.


Unicast Event to Trusted Listener


Ok everyone is connected to the hub now, now the user creates a new user and the client fires the 'user:add' event with the username and password.  This unbeknownst-to-the-client is a unicast event that ONLY gets sent to the one trusted server-side module that is listening for it.  This handler adds the user to the database and can either fire another event upon successful completion or use a callback to respond with the operation's status.


Event with Session Key


Great so we have created a new user, now that user wants to log in.  User fills in their username and password and a 'user:login' event is emitted.  The trusted unicast listener (doesn't have to be unicast in this case) gets the username & password & session key from the event hub and verifies the credentials against the database.  A match!  Now the listener would use the unique session key to create a session object in the database with the username of the authenticated user and again uses the callback or emits a 'user:loggedIn' event of its own to report status.


Great, now that user wants to change their password.  So the client fires a 'user:changePassword' (or 'user:updateUser' or whatever) event with the username, new password and the event hub adds in the session key before handing re-firing the event to the trusted listener (perhaps unicast).  The listener verifies the username in the event matches the username associate with the session key and if they match updates the password.  Finally it can either fire an event 'user:passwordUpdated' (or whatever) or use a callback to report back status.


Doesn't that all just make perfect sense??


So our event hub has sessions and trusted modules and unicast, everything else is just dumb event and callback passthru.


SSL


An event hub can operate just fine over SSL.  You will not get the pretty 'lock' or 'green' URL bar but all of your data can very easily be sent encrypted.




Coming up next: languages, implementations, and deployment - stay tuned!!

Event Listeners

Event Listeners

Get up to speed first:
Part 1: http://randomgoo.blogspot.com/2012/02/release-event-hub-web-30-introduction.html
Part 2: http://randomgoo.blogspot.com/2012/02/events.html

Quick recap - Web 3.0 is two-way asynchronous programming - events on the way out and another event or a callback on the way back.

There is no special syntax or language features required to listen for and respond to events.  So listen up!

hub.on('user:add', function(params, callback) {
    var user = params.user
          , pass = params.pass
    ;


    // Do something interesting (probably throw more events to
    //     save off to the DB) & when done if no error:
    callback(null, { success: true });
});

That's really it, attach a function to an event - the first parameter will be an object and the second will be a callback.  Both parameters are optional.

Note these examples use Javascript but THAT OF COURSE IS NOT REQUIRED!

Not all events require a response!  It's all about the documentation and expectation - event listeners MUST supply some sort of documentation to emitters:

/**
 * @method user:add handler
 * @param user username
 * @param pass password
 * @param callback required - response will contain 'success' 
 *    true or false
 */

Something like that - exactly as you would document a method-based API.  This handler can just as easily throw a 'user:Added' event instead of a callback:

hub.fire('user:Added', { success: true, user: params.user });


Firing an event as a response is preferable if you can get away with it so everyone can know what just happened, especially if it was successful, to give other parts of your application knowledge of what is going on.  Sometimes you do not need any response - like logging.


And sometimes you need a specific response directly back to you, for instance state information.


That's it for this round - stay tuned for MUCH more!

Events

Before reading this please read part 1:
http://randomgoo.blogspot.com/2012/02/release-event-hub-web-30-introduction.html

Quick recap - Web 3.0 is two-way asynchronous programming - events on the way out and another event or a callback on the way back.

So let's look at the event side of Web 3.0.

Event Syntax

  • Events Must have a string name
  • Events Might have an optional JSON-able set of parameters.
  • Events Might have an optional callback.

Event Names


Event names are strings, probably namespaced, separated from the namespace with a colon ':'.  It could also be a good idea to put a version number in there too if ya like, this can help keep your code in sync.  Up to you, play with it.

Here are some good event names:

user:add
user:delete
user:update
user-1.0:add    # module versioned
user:add-1.0    # listener versionsed
session:create

Event Parameters


Event parameters are serialized as JSON text so no function pointers or other funny business.  Toss in there whatever you need.  An important key is a session key.

Event Callback

Providing an optional callback allows event listeners to respond directly, asynchronously, back to the event emitter with data just for it.  The callback function should accept two paramters, a possibly null error object (or string) and a (possibly null) object with data for the emitter.

Check it:

hub.emit('user:add', { username: 'foobie', password: 'bloobie' },
    function(error, resp) {
        if (!error) {
            // sweet
        } else {
            // no dice
        }
    }
);

Look ma - no dependency on a 'user' object!

Event Semantics

Events are prayers that we expect to be answered.  It's possible they don't get answered.  What happens when events do not get answered?  Life goes on.

We'll look at event listeners next time...
(and still to come: the event hub itself, programming languages, and an implementation and experimentation)

Release The Event Hub: Web 3.0 - An Introduction

There are 2 factors of utmost import when coding: size and isolation.  While they both impact each other they are not the same.

Small code has fewer bugs.  Isolatable code has fewer dependencies and is easier to maintain.  So maintable code with few bugs, sign me up for that!

Small code is hard to write because code tends to get bound up in all the other code around it, despite our best efforts.

Especially over time feature creep and bug fixes tend to litter our once small code.  Plus it's just darn simpler at that moment to add code to already existing code instead of starting fresh.  So code grows and grows and without serious discipline that we all lack it never shrinks.

Isolatable code is hard to write because making everything an isolated unit is a giant pain in the ass.  There just is not any incentive day-to-day to write truly isolatable code.  If you do it still needs to be integrated into your application, why you are writing this code in the first place, and no one wants to keep doing that over and over again.  Besides have you ever seen an isolatable piece of
code?  Typically only the must mundane and obvious code is written as isolatable (or you're using 3rd party/open source code) - like obvious AOP stuff like logging and authentication.  Even then authentication is rarely isolatable from the HTTP server.  Same with session management.  Add authorization and message routing to all of that too.  Finally pulling 'business logic' away from the
HTTP server is difficult too.

Dependency management has almost single-handedly destroyed code quality since our ancesctors first hacked code on clay tablets back in the 1960s.  Creating, storing, calling, and destroying foreign objects has led to some of the most unmaintainable, tightly coupled, fan-out-crazy, untestable, downright ugly code imaginable.

With one stroke we can get rid of dependency hell, tightly coupled code, and useless blocking - while enhancing scalability, testability, maintainability, and code isolation.

Release The Event Hub!

Imgaine an army of independent handlers, each handler doing only one thing, communicating via only events and callbacks.  No external dependencies and no HTTP server requirement.  I'm talking about truly independent hunks of code 'Sofware as a Service' connected by an event hub.

Gone are the same-origin policy, HTTP servers routing messages, and tightly coupled code.

So how does it work?  Every independent module of code connects to a central event hub.  This hub can live on a separate host from your HTTP server and is actually a relatively simple piece of code.  It accepts connections from modules and passes emitted events to all connected listeners.  It also proxies callbacks back to the event emitter, is there is one (a callback, that is).

Event emitters connect to the hub and emit events and either:

1. are done
2. are listening for another event in response to theirs (or not)
3. wait for a callback from the listener

Event listeners connect to the hub and wait to service fired events.  In response they:

1. do nothing
2. fire another event
3. execute the provided callback

Of course a hunk of code can be both an event emitter and a listener.

OK that's enough for the first post - next up we'll look at how this actually all works (including sessions and security).  We will all miss multi-threading and method calls greatly: RIP.

Wednesday, August 10, 2011

Javascript Unit Testing Environment

Ready to kick your Javascript Unit Testing up to the next level?  Or even to the very first level?  


Javascript Unit Testing suffers from lack of standardization.  There is no universal 'JUnit' or 'PHPUnit' to 'rule them all'.  There are lots of very good Javascript testing frameworks available, especially YUI3's test framework.

YUI3's framework provides the foundation for writing unit tests, collecting them into test cases and suites, and even mocking objects.  And that's great.  But we can do more, and do it easier!

The Javascript Unit Test Environment (JUTE) combines the YUI3 testing framework, automatic dynamic code coverage, a web UI, a command line interface, seamless client- and server-side Javascript testing and 3 testing back ends (Capture, Selenium, and V8) in one easy to setup and use package.  This is all provided with very little setup by you - just like we all like it!

Anatomy of a client-side Javascript Unit Test


First let's look at what a simple client-side Javascript Unit Test looks like.  Here's some simple code we want to test (not JUTE does NOT require that code you want to test be written using YUI3!).

In 'mySum.js':

function mySum() {
    var result = 0, i = 0;


    if (typeof arguments[0] == 'object' && arguments[0].length) {
        for (;i < arguments[0].length; i++) {
            result += arguments[0][i];
        }
    } else {
        for (;i  < arguments.length; i++) {
            result += arguments[i];
        }
    }
    return result;
}


A slightly bizarre 'sum' function - does it work?  Let's write a test for it using JUTE!  JUTE builds on top of the YUI3 test module, so we need to use that to write our tests.  Again, the code you are testing does NOT need to use or have anything to do with YUI3 (although it can!) - only the TESTING code needs to utilize the YUI3 test stuff - which is good test stuff to use regardless!

In 'testMySum.js':


YUI({                                                                                                                                                                     
    logInclude: { TestRunner: true },
    gallery:    'gallery-2011.06.22-20-13'
}).use('gallery-jute', function(Y) {

    var suite = new Y.Test.Suite('mySum');
    suite.add(new Y.Test.Case({
        name:'simple sums',
        testTwoNumbers: function() {
            Y.Assert.areEqual(mySum(5, 5), 10);
        },

        testArray: function() {
            Y.Assert.areEqual(mySum([5, 5]), 10);
        }

    }));
    Y.Test.Runner.add(suite);
    Y.UnitTest.go();
});


So those are two reasonable tests for our 'mySum' function.  Now we need an HTML file to pull it all together.

In 'testMySum.html':


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">                                                                                                           
<html lang="en">
    <head>
         <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    </head>
    <body class="yui3-skin-sam">
        <div id="log" />
        <script src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
        <script src="mySum.js?coverage=1"></script>
        <script src="testMySum.js"></script>
    </body>
</html> 



OK so we've got all we need for a basic client-side Javascript Unit Test.  We have what we want to test (mySum.js), our test code (testMySum.js) and finally an HTML file to pull it all together (testMySum.html).  We could be done here, run the tests, hope it all passes and move on.

The only things different here than a vanilla unit test are the inclusion of the 'gallery-jute' module (which also pulls in YUI3's 'test' module for you) in testMySum.js AND node the '?do_coverage=1' query string I snuck in testMySum.html on the mySum.js file!  This will transparently tell JUTE that IF you want to run these tests with code coverage THIS is the file we want code coverage for - which, surprise surprise, is the file we're testing.


Anatomy of a server-side Javascript Unit Test


Our 'mySum' function can clearly just as easily be run on the server side using NodeJS.  What would a unit test for server-side Javascript look like?

First off our mySum.js file will change slightly because we want to utilize the NodeJS 'require' feature.

myServerSum.js:

module.exports = {
    mySum: function() {
    var result = 0, i = 0;


    if (typeof arguments[0] == 'object' && arguments[0].length) {
        for (;i < arguments[0].length; i++) {
            result += arguments[0][i];
        }
    } else {
        for (;i  < arguments.length; i++) {
            result += arguments[i];
        }
    }
    return result;
}
};


Here we just wrapped our 'mySum' function into a module.exports declaration.  Now our tests will change slightly to use 'require' instead of relying on an HTML file to link everything together.

In 'testServerMySum.js:



YUI({                                                                                                                                                                     
    logInclude: { TestRunner: true },


}).use('jute', function(Y) {


    var suite = new Y.Test.Suite('mySum'),
          mySum = require('myServerSum', true).mySum;
    suite.add(new Y.Test.Case({
        name:'simple sums',
        testTwoNumbers: function() {
            Y.Assert.areEqual(mySum(5, 5), 10);
        },

        testArray: function() {
            Y.Assert.areEqual(mySum([5, 5]), 10);
        }

    }));
    Y.Test.Runner.add(suite);
    Y.UnitTest.go();
});


No not a lot of (visible!) magic here - we just 'require' the myServerSum javascript & pull out the 'mySum' function.  Besides there being NO HTML file I've snuck something else in - note:


        mySum = require('myServerSum', true).mySum;


In 'testServerMySum.js'!  Similarly to '?do_coverage=1' in the client-side example, this tells JUTE that IF we run unit tests wanting code coverage THIS is the file to apply code coverage to.  And, surprise surprise, this is the file we are testing.

Ready To Rumble


At this point JUTE now gives you the flexibility to run your tests via a web UI or a command-line interface.  JUTE will persist not only your unit test output in JUnit XML format, but will also automatically generate pretty HTML for code coverage AND give you the option of running these tests in either Captured browsers, on a Selenium RC or Grid host, or directly thru V8.  Of course the NodeJS version of mySum can ONLY be run thru the V8 backend.  However in this case the client-side version CAN be run thru any of the 3 backends.

So you've actually done all the hard parts already:  for client-side Javascript testing you have the file you want to test, the file with your tests in it, and an HTML file tying them all together.  For server-side Javascript you've got the file you want to test and file containing all of your test code.

Now lets sit back and run it all thru JUTE and start living the good life!

Installing JUTE


First you need to install the thing - JUTE requires only the current versions of NodeJS (0.4.10) and npm (1.x).  Simply:
% npm install jute -g
Starting, stopping, and restarting JUTE is equally easy:
    % npm start jute
    % npm stop jute
    % npm restart jute
Basic Configuration


JUTE is a standalone webserver so before you start it you need to tell it where your document root is, where your test files are, and where it should put its output.  You can also give JUTE another port to run on and some other configuration.  Regardless all configuration is accessible via npm config variables:
% npm config set jute:docRoot /var/htmlroot
% npm config set jute:testDir test
% npm config set jute:outputDir output
% npm config set jute:port 8080
SO JUTE will look for all of your *.html 'glue' test file in docRoot + testDir (/var/htmlroot/test) in this example and output test results and code coverage information into docRoot + outputDir (/var/htmlroot/output) in this case.  AND JUTE will listen on port 8080.

If you make ANY changes to JUTE variables you MUST restart JUTE for your changes to take effect:
% npm restart jute
Now that JUTE is configured you are ready to run some tests the JUTE way!

Backends


Before we run our tests let's quickly divert and discuss the testing 'backends' available with JUTE.

Capture


Capture mode runs tests on all 'captured' browsers.  A 'captured' browser is simply one that is currently pointing to http://<JUTE_SERVER>:<JUTE_PORT>/  All such browsers (desktop, mobile, whatever) are 'captured' by JUTE and any submitted 'capture' unit tests will run on ALL currently captured browsers in parallel.

Selenium


JUTE plays nicely with Selenium RC and Grid.  The Selenium back end will ship all requested tests to a Selenium RC or Selenium Grid instance.  Just specify the Selenium browser specification (e.g. '*firefox') and off your tests go.
The Selenium back end is only available via JUTE's command-line interface.

V8

Some client-side Javascript and of course and all server-side Javascript will run through the V8 back end.  The V8 back end is only available via JUTE's command-line interface.

Running Your Tests

Hey we are just about ready to run our awesome unit tests the JUTE way!  You have two choices to kick off your unit tests, via the WebUI or the command-line interface.  Note ONLY Capture tests can be run via the web UI - Selenium and V8 back ends are only accessible via JUTE's command-line interface.  See below for details!

WebUI


JUTE comes with a snazzy webui available here:
http://<JUTE_SERVER>:<JUTE_PORT>/
This will bring up a lot of information - the most useful being the list of unit tests available to be run assuming you set up docRoot and testDir correctly!
From the WebUI you are able to run any/all tests in Capture mode.  You can also see output from ALL modes in the 'results' pane on the right.

Command-Line Interface


This is where things get especially interesting.  From the command-line interface you can run tests in any of the 3 back ends with code coverage or not.  Let's look at some examples!  NOTE!!!!!!  All testfiles are specified RELATIVE to <docRoot>/<testDir>!!
% jute_submit_test --test myTestSum.html
This is as simple as it gets - submits that 1 HTML file to be unit tested in capture mode.
% jute_submit_test --test myTestSum.html --v8
Same thing BUT use the V8 backend.

% jute_submit_test --test myTestSum.html --sel_host our.selenium.rc.com -sel_browser '*firefox'
How about multiple tests?

% jute_submit_test --test myTestSum.html --test myOtherTest.html
Again added the '--v8' or '--sel_host' flags for those back ends.

How about code coverage?

% jute_submit_test --test myTestSum.html?do_coverage=1 --v8
Simply stick the '?do_coverage=1' querystring at the end any test to enable code coverage.

Now JUTE will go off and run you test(s) using the specified back end and will dump output into <docRoot>/<outputDir>.  JUTE will also generate pretty HTML for code coverage if requested - all available for viewing via the webui - EVEN Selenium and V8 tests!


More Information

I hope you've seen writing Javascript unit tests CAN be fun AND profitable!  More examples are available at the JUTE homepage - so check it out!
Don't let your client- or server-side Javascript get out of control!  JUTE makes it easy and seamless to get started or kick up to the next level your Javascript Unit Testing today!

% npm install jute -g

FTW!