You are here

Blogs

Introducing node-unittest

After being unable to find a reasonable xUnit-style for Node.js I decided to write my own implementation with async concepts based on Twisted's Trial testing framework.

Welcome to node-unittest :)

Existing frameworks don't work at all how we expect:

  • JSpec is based on RSpec and jumps down the same domain-specific-language rabbit hole that so many Ruby projects do, presenting you with a swath of object method overrides and pre-processors so that you get to learn a new language to use it.
  • nodeunit is based on QUnit which is the jQuery testing framework that provides a very functional (as opposed to object-oriented) approach to testing that throws away all the patterns and knowledge we've already built up writing xUnit tests in every other programming language.
  • assert, the built in library does very nicely for what it does but it provides no framework for organization or running tests.

So, node-unittest, it's very early right now but as I have at least two projects depending on it for tests it should mature quickly. It does what you'd expect, allows you to return Deferreds from tests to deal with async tests, examples and more are on the project page.

Java is a workaround for Java

14:59 < termie> you know what is broken for me? java as a language
14:59 < verbal> just for you? :)
14:59 < termie> a lot of other people seem to be using some kind of workaround
15:00 < verbal> haha

OAuth with XML-RPC

Gave a bit of a explanation about how JaikuEngine intends to use OAuth via an XML-RPC interface over on Jaiku so I figured I'd mostly duplicate it here.

Quick background:

JaikuEngine expects the request coming in over XML-RPC to be in the form of a single parameter which is a struct of strings (emulated in python as a dictionary of strings)

First off using XML-RPC obviously isn't covered in the spec, the spec only talks about headers and POST and GET, what we are doing however is following the spec for signing a set of request parameters.

Step 1: Get the parameters.

The spec describes three sources for parameters, the header, POST application/x-www-form-urlencoded and GET query string. The reason it specifies a content type there is to explicitly say this is data expected as key-value pairs, no mime attached files, no atompub, only things that are made of the same kind of key-values as one would expect in a query string.

In our case we choose to also allow those key-value pairs to come in via xml-rpc. When you boil it all down, what you are trying to sign is the important part of the request, in atompub the organization of the actual xml can have significance, tags will have attributes, etc; however, in xml-rpc (when used the way we are using it) the "information," the important part of the request, is just the key-value pairs, we completely ignore all that extra xml that makes up the xml-rpc protocol: all we want is the content.

Step 2: Normalize the parameters

Once you have those key-value pairs you need to apply predictable and repeatable transformations to it to make sure that each key and value looks exactly the same as it does to the person who sent them, in the case of oauth that is a specific type of urlencoding.

Regardless of where you got the variables from, be it POST, GET, headers, xml-rpc, you will have a key and a value and your web app will have successfully decoded them from whatever format they were in to the actual values of the key and the value without any escaping, that is inherently necessary if you plan on using those values to make changes to your site. From there it is a simple matter of allowing the OAuth library to normalize them for use in the signature.

When writing the OAuth libraries, I explicitly included the option of passing a parameters dict or associative array into the request constructors so that the libraries can be transport protocol agnostic.

Step 3 and onward:

I'm pretty confident you've got the rest from there, it plays out according to the spec without any hitches.

OAuth.php - Now With RSA-SHA1!

Merged in a bunch of patches from fangel and added support for RSA-SHA1 to the library.

There are still some gotches related to keys, they are marked in the code but for the moment you'll have to extend the OAuthSignatureMethod_RSA_SHA1 class in order to use it because the method for fetching your public and private keys is being skipped.

You can go test using the test client and test server

The keys being used are down at the bottom when RSA-SHA1 is selected as the current signing method.

As always, code is available at http://code.google.com/p/oauth/source/browse/code/php

Google App Engine Helper for Django

Wee, some of the code I worked on has been released (and there's a blog post about it), it's an SDK that lets you use the Django development process with App Engine.

Works really well already and there is an active google code project where you can report bugs and get your patches reviewed.

What Is Capistrano Designed For?

Seems like every time I try to make use of it I am hacking around it.

To deploy to different environments, one must either do a switch or define an extra task to set the necessary variables. It's a bit of code duplication but not really very bad. It gets a little bit worse when you also would like to be able to deploy from a branch or tag. The smarter way, of course, would be to have a built-in feature for defining different deployment environments, I don't know anybody who has only one environment.

Where it starts to get annoying is when you want to deploy similar things that have some small difference between them, for example a debug version of a website as well as staging and production. Staging and production are just duplicating some settings and changing some paths, for debug currently you need to mark a server as debug and do something different for it, you end up setting a global variable and adding a branch anywhere that needs to check that code. For some reason using something like

task :stage do role :web, "staging.example.com" end

task :dev do role :web, "debug.example.com", :debug => true end

task :set_debug, :only => { :debug => true } do set :debug, "1" end

namespace :deploy do task :before_symlink do set_debug p debug # WRONG: always prints "1" end end

doesn't work because it is always called regardless of this "only" business, so you have to resort to branching and global variables set at the top. Even if somebody offers up a solution or workaround to that particular bug the issue remains that one should simply be able to do something based on properties of the current host rather than having to define a sub-task to filter actions.

Furthermore, the /real/ annoyance begins when you have to deploy differing environments from the same code in the same deployment. Due to the same reasons as above I cannot do something with an intention like

role :front, "front.example.com", :readonly => true
role :web, "web.example.com"

task :set_debug, :only => { :debug => true } do set :readonly, "1" # this will fail because it sets it for both end

namespace :deploy do task :before_symlink do set_readonly p readonly # WRONG: always prints "1" end end

without resorting to environment variable hackery based on role or hostname checking.

Obviously what we all want from a deployment tool is a way to declaratively define the servers and their attributes and capistrano just falls flat on its face when faced with any of these very average deployment scenarios.

Update Hmm, Vlad the Deployer sounds nice

OAuth Public Test Server: Now With Client!

Added some client code to this beast so that I can start testing interop with other servers, the only site claiming support at the moment is Ma.gnolia but I can't get it to work yet (thread). The client is part of the example code too: http://term.ie/oauth/example/client.php I've only tested it against my own stuff so far because I can't get any debug info out of Ma.gnolia yet, hopefully they help out tomorrow :)

Pages

Subscribe to RSS - blogs