I Prefer Jim Developer James Schubert shares his code and his thoughts.

6Feb/120

Mastering Node: Addons and FunctionTemplate (uuid.node)

Last night, I pushed an addition to my fork of Mastering Node. I decided to add a bit to the Addons chapter. The first example in this chapter only shows how to add a function to a natively-compiled module (i.e. an addon). This example shows you how to start a module which can be used in the following way:

var Uuid = require('./uuid.node').Uuid;
var uuid = new Uuid();
var myId = uuid.generate();

The project files referenced in the following text can be downloaded from the repo: jimschubert/masteringnode


FunctionTemplate

In v8, a FunctionTemplate is used to create the equivalent to:

var template = function() { }

The function at this point is an object and not an instance of the function.

As an example, we will use the linux package uuid to generate a uuid. We will define the header for this addon as:

flattr this!

22Dec/11Off

Install nodejs under ChromeOS (CR-48)

Why would I want to do this?

I'm a software developer. I love javascript. I love node.js. I love the direction Google is taking web development, user interaction, and the web in general. Installing node.js opens up a lot of possibilities for me on my CR-48. I don't know if this will work on anything other than the CR-48, considering the machine has to be in developer mode for these instructions.

If you don't have a chromebook yet, or you don't know what they are... where have you been? But seriously, visit http://www.google.com/chromebook/ and check them out.

Before I start, let me first say that following these instructions may void your warranty if you have one, open your machine up to vulnerabilities, or replace existing files and cause instability. If you don't know how to revert or fix any issues that may occur, don't continue. I offer no sort of warranty, support, or anything else. Consider this a 'hack' of sorts.

I found a blog post detailing how to install an archive package and ruby on rails in ChromeOS. I followed part of these instructions and I have modified them to fit my needs.

Prerequisites

  • You must have a Chromebook, possibly only the CR-48
  • You must be in 'developer mode'
  • You must have a writable rootfs (see above link for developer mode)

Instructions

Downloading and installing xz

  1. Download the xz package
  2. Enter crosh or VT-2 (CTRL+ALT+T or CTRL+ALT+→)
  3. If VT-2, login to the shell
  4. Run on the terminal: cd /home/chronos/user/Downloads
  5. Run on the terminal: tar -zxf xz-*.tar.gz
  6. Run on the terminal: cd usr
  7. Run on the terminal: cp * /usr/

Now that xz is installed in /usr/bin (verify by running on the command line: which xz), you will be able to extract certain files that are necessary for nodejs and possibly any other package you'd like.

Download and install nodejs and openssl.
The site claims openssl is optional, but node wouldn't open without it

  1. Download nodejs
  2. Download openssl
  3. Enter the terminal again and navigate to /home/chronos/user/Downloads
  4. Run on the terminal: xz -d node*.xz
  5. Run on the terminal: tar -zxfv openssl*.tar.gz
  6. Run on the terminal: cd usr
  7. Run on the terminal: cp * /usr/

Now you should have a working install of nodejs. You can use npm, for instance, to install express and jade.
node.js and express running on ChromeOS

flattr this!

28Sep/11Off

Makefile setup for minifying .js files in an expressjs application

There's not really any reason to uglify or minify your JavaScript files on a per-request basis or on a pre-cache basis. This should be done at deployment time only. This can be achieved by adding uglify-js to your package.json file.

// default package.js for an expressjs app using ejs and uglify-js
{
    "name": "application-name"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.4.6"
    , "ejs": ">=0.4.3"
    , "uglify-js": ">=1.1.0"
  }
}

Make sure the dependencies are installed with

npm install -d

Then, add the following make file and minify your JavaScripts as part of your make process!

JS = $(shell find public/javascripts/*.js)
MINIFY = $(JS:.js=.min.js)

all: clean $(MINIFY)

clean:
	rm -f ./public/javascripts/*.min.js

%.min.js: %.js
	node ./node_modules/uglify-js/bin/uglifyjs -o $@ $<

.PHONY: clean js minify

(expandable source is the same as the gist. It is doubled here to show in RSS feed readers.)

flattr this!

17Aug/11Off

[node.js] Getting started with nodeunit

The following code is part of the testing chapter I previously worked on in my fork of Mastering Node.

Throughout this post, you'll see references to files from a relative directory. If you clone my fork of Mastering Node, these file locations are relative to the root directory of that cloned repository.

For a pretty simple example of real-world testing using nodeunit, check out the initial testing done on my project, brushes.js [?].


Testing

Testing is a very large topic. There are different types of testing, each with different methodologies. Then, there are also strong feelings of developers toward which type of testing is the best or most effective.

  • Assertion Testing
    • Tests a true or false condition against known objects or values
  • Behavioral Testing
    • Tests how one object acts when interacting with another
  • Functional/Acceptance Testing
    • "Black box" testing of a system, usually code-agnostic
  • Regression Testing
    • Tests for consistency after changes have been made to code
  • Others...

There are many other types of testing, but these are some large topics in the testing arena. Development practices include Test-Driven Development (TDD), Behavior-Driven Development, and others. Some programmers don't believe in testing, others believe tests should be written before the code, while others still believe tests should only be written for the most important code. As you can see, this is a large and complex topic.

Whether you write tests before you code, test only the most important code, or casually write tests when there is time, it is important to choose a testing tool that fits your needs.

assert Module

To begin, require the assert module:

var assert = require('assert');

This module exposes a few functions common to assertion testing:

// equality
assert.equal(actual, expected, [message])
assert.notEqual(actual, expected, [message])
assert.deepEqual(actual, expected, [message])
assert.notDeepEqual(actual, expected, [message])
assert.strictEqual(actual, expected, [message])
assert.notStrictEqual(actual, expected, [message])

// exception
assert.throws(block, [error], [message])
assert.doesNotThrow(block, [error], [message])
assert.ifError(value)

// condition
assert.ok(value, [message])
assert.fail(actual, expected, message, operator)

These are pretty self-explanatory if you've written assertion tests before. Let's look at a pretty simple test, anyway. We'll code in an object for the test that will do what we want for each test.

Synchronous Testing with Assert

// testing/equality_no_errors.js
var assert = require('assert'),
    tester_a = {
      val : 'a'
    },
    tester_b = {
      val : 'b'
    };

assert.equal(tester_a.val, 'a');
assert.equal(tester_b.val, 'b');

In this example, we're using the assert module to check that a value on each of these objects is the expected value. This works well because the values are equal. But, the assert module throws an AssertionError whenever an assertion fails. So, it doesn't really make sense to have a single file with end-to-end assertions as in the ./src/testing/equality_no_errors.js file. This is where testing frameworks like nodeunit or expresso come in very handy. They offer common functionality of test frameworks (like metrics, etc.).

To see how the AssertionError being thrown from assert.equal can be problematic, change the expected value in the first test to an incorrect value. Then, change the expected value in the very last test to an incorrect value and run node src/testing/equality_no_errors.js again. You'll see that, because of the procedural style of the code, the last test never runs!

In order to run multiple assertions and provide feedback, the simplest test (without a testing framework) would use a try/catch and provide output to stdout.

// testing/equality_with_errors.js
var assert = require('assert'),
    tester_a = {
      val : 'aa'
    }, total = 0, good = 0;

// assert.equal(actual, expected, [message])
try {
    console.log("assert.equal(tester_a.val, 'a')");
    assert.equal(tester_a.val, 'a');
    passed();
} catch (err) { writeException(err); }

console.log("%d of %d tests passed", good, total);

function writeException(err) {
    console.log("Test failed!");
    util.inspect(err);
    if(err["name"] === "AssertionError") {
        console.log("Message: " + (err["message"] || "None"));
        console.log("Expected: " + err["expected"]);
        console.log("Actual: " + err["actual"]);
        console.log("Operation: " + err["operator"]);
    }
    console.log("");
    total = total + 1;
}

function passed() {
    good = good + 1;
    total = total + 1;
    console.log("Test passed!\n");
}

The above code is part of the code from within ./src/testing/equality_with_errors.js. It shows how to run synchronous tests with a minimal amount of redundant code, without writing a lightweight testing module for your tests. This may be what you want, but most likely it isn't.

The problems

You could write a simple helper module to run these tests for you. But, how do you verify the order of your tests? This can become complex very quickly.

You can partially resolve this with the try/catch block example above, but this requires a lot of redundant code. Compare ./src/testing/equality_with_errors.js and ./src/testing/equality_no_errors.js to see how the testing quickly expands! Run node testing/equality_with_errors.js to see the output. That's more like it! Isn't that nice?

Yes and no. There are a few problems with this code:

  1. It isn't evented
  2. It hard-codes test objects
  3. It is very redundant
  4. It isn't scalable

Well, then, what are other options?

Nodeunit

Nodeunit is a framework similar to nunit in that it allows for multiple test cases (running in parallel), and supports mocks and stubs. It is easy to use, and even allows you to run tests in the browser.

Nodeunit testing starts with exporting a test or two from a module.

// testing/nodeunit_basics.js
module.exports = {
    'Test 1' : function(test) {
        test.expect(1);
        test.ok(true, "This shouldn't fail");
        test.done();
    },
    'Test 2' : function(test) {
        test.expect(2);
        test.ok(1 === 1, "This shouldn't fail");
        test.ok(false, "This should fail");
        test.done();
    }
};

Here, we have a module exporting two tests, Test 1 and Test 2. You may have noticed that the test object in the functions have an ok() method just like the assert module mentioned above. Good eye. In fact, test supports all of the assert functions and adds two others: expect(number) and done(). The expect function tells nodeunit how many tests are being run within the context of the current test case. When all tests are finished, call test.done() to let nodeunit know the test case has completed (and a callback may have failed).

The output of nodeunit is visually helpful.

$ nodeunit src/testing/nodeunit_basics.js 

nodeunit_basics.js
✔ Test 1
✖ Test 2

Assertion Message: This should fail
AssertionError: false == true
    at Object.ok (/usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/types.js:81:39)
    at /home/jim/projects/masteringnode/src/testing/nodeunit_basics.js:10:14
    at Object.runTest (/usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/core.js:54:9)
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/core.js:90:21
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:508:13
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:118:25
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:129:25
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:510:17
    at Array.&lt;anonymous&gt; (/usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/types.js:144:17)
    at EventEmitter._tickCallback (node.js:108:26)

FAILURES: 1/3 assertions failed (8ms)

Nodeunit will list all test cases run within the test, followed by any AssertionError output and the number of passing or failing assertions. This is the default (minimal) output.

Nodeunit reporters

Nodeunit ships with a number of reporters and it is possible to add custom reporters.

$ nodeunit --list-reporters
Build-in reporters:
  * default: Default tests reporter
  * minimal: Pretty minimal output
  * junit: jUnit XML test reports
  * html: Report tests result as HTML
  * skip_passed: Skip passed tests output
  * browser: Browser-based test reporter

To output to junit, run the command as:

$ cd src/testing && nodeunit --reporter junit nodeunit_basics.js --output junit.out

This creates an xml file (whitespace has been condensed):

   // testing/junit.out/nodeunit_basics.js.xml
   <?xml version="1.0" encoding="UTF-8" ?>
    <testsuite name="nodeunit_basics.js"
             errors="0"
             failures="0"
             tests="2">
      <testcase name="Test 1">
      </testcase>
      <testcase name="Test 2">
      </testcase>
    </testsuite>

This is great, but in a real-world development environment, you may be asked to write reports with a specific format, wording, or links (in html) to files with failing test cases. Luckily, nodeunit allows us to customize this output.

Nodeunit Custom reporters

To write a custom reporter for nodeunit, first decide how you'd like nodeunit to report information about your tests. As a simple example, let's take a look at a different take on the minimal reporter.

Here are the modifications I'd like to see:

  • Show the start time of the test
  • Show the filename as bold/green
  • Add [PASS] or [FAIL] after the or
  • Prefix a test case with a '|'

These may seem like contrived requirements. But, what if my manager wants me to parse textual output for [FAIL] and, for whatever reason, it has to say [FAIL]?

The modifications to the minimal reporter are too spread out to include inline here, so be sure to check out the file at ./src/testing/reporterse/example.js.

Here is the slightly modified minimal output, meeting all of the requirements.

$ cd src/testing && nodeunit --reporter reporters/example.js nodeunit_basics.js
Tests started: Tue Mar 22 2011 21:24:42 GMT-0700 (PDT)
nodeunit_basics.js: 

✔ [PASS] | Test 1
✖ [FAIL] | Test 2

AssertionError: false == true
    at Object.ok (/usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/types.js:81:39)
    at /home/jim/projects/masteringnode/src/testing/nodeunit_basics.js:10:14
    at Object.runTest (/usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/core.js:54:9)
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/core.js:90:21
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:508:13
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:118:25
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:129:25
    at /usr/local/lib/node/.npm/nodeunit/0.5.1/package/deps/async.js:510:17
    at Array.&lt;anonymous&gt; (/usr/local/lib/node/.npm/nodeunit/0.5.1/package/lib/types.js:144:17)
    at EventEmitter._tickCallback (node.js:108:26)

FAILURES: 1/3 assertions failed (9ms)

These were small modifications, but following through the reporters included in nodeunit, it will be easy to output test reports to your desired format.

flattr this!

9Apr/11Off

[node.js] Mastering Node excerpt: Addons

Addons

The node documentation for addons is self-admittedly pretty weak as of v0.4.0.

This chapter doesn't aim to be a replacement for the official documentation. Instead, we'd hope this can expand on some of the basics a little more than a simple "Hello, World!" and drive you as a developer more on the path toward mastering node through its source code.

In fact, for now, we're only going to cover some shortcuts for creating properties on an object, functions, and interacting with function prototypes. This doesn't reach the evented level of node's awesomeness, but you should be able to look at examples in node's source and the documention for libev and libeio to find answers.

Pre-requisites

* Some C/C++ knowledge
* V8 JavaScript
* Internal Node libraries
* libev
* libeio

hello.node

Our first example is the very same one from node's docs. We're going to include it for those who haven't read through the docs and have instead trusted in the knowledge of this ebook's authors (thanks, by the way).

A node addon begins with a source file containing a single entry point:

flattr this!

16Mar/11Off

Mastering Node

I've forked a project at github called "Mastering Node".
https://github.com/jimschubert/masteringnode

I've wanted to familiarize myself with node.js for some time, and this seems to be the best way. It's an amazing framework for server-side JavaScript.

flattr this!