Pounding A Nail: Old Shoe or Glass Bottle?

I just found this article from 2005, but it’s a classic!

Pounding A Nail: Old Shoe or Glass Bottle? – Alex Papadimoulis’ .NET Blog.

(via Stack Overflow Blog)

How to Embed Almost Anything in your Website

Another summary of useful tips. This time about how to use existing software and familiar techniques to give a richer web experience.

How to Embed Almost Anything in your Website

Context and problems with “Best Practice”

I sometimes have to suppress a shudder when people use the term “best practice”. Despite a positive sounding name, the idea of “best practice” is almost always used in a way that is restrictive rather than enabling. Declaring one approach or solution as “best practice” by implication shuts out other answers.

I will admit that for some (very narrow) fields there can be a common understanding of the one best way to do something, but this is often so well understood that it does not even get a name. Walking on your feet is generally better than walking on your hands or knees, for example, but I have never met anyone who referred to foot-walking as “best practice”.

In my world of software development, where the landscape changes at a moment’s notice, naming something as “best practice” is tantamount to declaring it obsolete. Yet large numbers of software developers still numbly follow the its lead.

James Bach tackles a similar issue in testing James Bach’s Blog » Blog Archive » The Great Implication of Context-Driven Methodology.

ChromeWatir release 1.0.0

Every now and then we discuss ways of better automating the manual tests which accompany our web applications. This is especially poignant right now as both the development and test teams have been recently reduced in size. We have had some success with Watir in the past, but it was always dependent on Internet Explorer and Windows. So it’s cool to read that there is now an equivalent for Chrome.

ThoughtWorkers on Open Source: Announcing ChromeWatir release 1.0.0

Options for developing mobile apps: PhoneGap, Palm Pre, etc.

Mobile application development is certainly a hot topic at the moment. People seem to be climbing over one another to produce iPhone apps, and Google’s Android is never far from the tech news. But there are also other players, and several want to enable a more familiar web development experience on mobile devices.

SitePen Blog » PhoneGap, Palm Pre, and the State of Mobile Apps

Test-Driven Development of HTTP and REST interfaces with Mojasef

Test-Driven Development (TDD) of HTTP and REST interfaces can be tricky. This post contains some examples of how to do it using the open source Mojasef toolkit. I was prompted to write this post after recently finding and fixing an irritating bug using just this technique.

First, let’s set the scene. In TDD the rules are very simple: No production code is written without a failing test; just enough code is written to satisfy the current set of tests; duplication is mercilessly refactored. TDD is a very powerful and effective technique which can improve both the quality and delivery time of software. HTTP and REST interfaces provide access to a system or component using the HTTP protocol. This access may be by fetching HTML or WML pages, for example, or it may be by sending, receiving and updating resources in some other format such as XML or JSON.

For a first scenario imagine we have an existing HTTP interface for which we want to write a client using TDD. This service is relatively simple to start with. To send a message requires a POST request to a particular URL with two parameters “destination” and “text”. If the destination is valid, the text message is sent to the destination and a “200″ status code is returned. If the destination is not recognized, a “404″ status code is returned. This interface is so simple that it is tempting to just write the client, test it manually and move on. But if we were to do that, then we might not think of all the test case possibilities, and there would be no regression tests to help protect the software from unexpected side-effects later. So we opt to do the right thing, and use TDD.

For the sake of simplicity, I will assume we are using the Stringtree HTTPClient as described in an earlier post. So let’s start with a simple test to make sure the code compiles and the test libraries and stuff are in place:

import org.stringtree.http.*;
 
public class MessageSendingTest extends junit.framework.TestCase {
  public void testExceptionFromUnknownURL() {
    Form form = new Form();
    form.put("destination", "name@example.com");
    form.put("text", "hello from HTTP");
    HTTPClient client = new HTTPClient();
    try {
      client.post("http://localhost:9999/send", form);
      fail("should throw an exception");
    } catch (Exception e) {}
  }
}

This test serves two purposes. First, compiling it helps drive the structure of the test case, what classes need to be imported and so on. Second it documents the expected behaviour of our client if the server is not running or not where it is expected to be. I always like to start with this sort of “null” test case wherever possible. Once we get this test working we are ready to move on to the next step, testing against an actual server.

It might be possible to test against a real server, perhaps by manually examining log files, or checking the actual receipt of a message. Feel free to do that, but understand that that is really integration testing rather than unit testing, and neither helps us design and debug the client, nor document and enforce the proper behaviour of our code once we move on to other work. To gain these benefits we need a server which may be started, examined and stopped quickly and under the control of a simple unit test. This is where Mojasef comes in.

Mojasef is a server and web application framework designed for efficient test-driven development of web applications. Although usually used for building applications, it is just as suitable for building test harnesses. In this case we will build a simple application which implements the HTTP interface described above. And yes, we will do it using TDD, so we leave the MessageSendingTest for the moment and start a new one to drive our test harness without requiring HTTP. As usual, I start with a “null” test to get started:

public class MessageHarnessTest extends junit.framework.TestCase {
  MessageHarness harness;
 
  public void setUp() {
    harness = new MessageHarness();
  }
 
  public void testNoAction() {
    assertFalse(harness.wasCalled());
  }
}

This won’t compile without a MessageHarness class, so let’s make the minimum necessary.

public class MessageHarness {
  public boolean wasCalled() {
    return false;
  }
}

Good, our test now runs, so let’s add some behaviour. First another test:

  public void testCalledWithoutArguments() {
    harness.send();
    assertTrue(harness.wasCalled());
  }

To make this compile we need to add another method to MessageHarness

  public void send() {
  }

Our new test fails, so we need to make it work.

public class MessageHarness {
  private boolean called = false;
 
  public boolean wasCalled() {
    return called;
  }
 
  public void send() {
    called = true;
  }
}

That seems enough to start with. Now back to the main test case. Add a new test to call the application we have just built over HTTP and check that all the communication stuff works. With a bit of refactoring to keep the tests clean and duplication low.

import org.stringtree.http.*;
import org.stringtree.mojasef.standalone.InlineServer;
 
public class MessageSendingTest extends junit.framework.TestCase {
  HTTPClient client;
  Form form;
  InlineServer server;
  MessageHarness app;
 
  public void setUp() throws Exception {
    client = new HTTPClient();
    form = new Form();
    app = new MessageHarness();
    server = new InlineServer(app, "9998");
    server.start();
  }
 
  public void tearDown() {
	server.halt();
  }
 
  public void testExceptionFromUnknownURL() {
    form.put("destination", "name@example.com");
    form.put("text", "hello from HTTP");
    try {
      client.post("http://localhost:9999/send", form);
      fail("should throw an exception");
    } catch (Exception e) {}
  }
 
  public void testHarnessWiring() throws Exception {
    form.put("destination", "unknown@example.com");
    form.put("text", "hello from HTTP");
    assertFalse(app.wasCalled());
    client.post("http://localhost:9998/send", form);
    assertTrue(app.wasCalled());
  }
}

This probably needs a bit of explanation. The MessageHarness class we produced above is a Mojasef web application. Really, without any other configuration, base classes or nonsense. It’s just a “plain old Java object” (POJO). The job of the Mojasef code is to take an object of that class and make its methods available as HTTP URLs.

To serve it over HTTP we could use a MojasefServlet and run it in any Servlet Container, but for this test we want an ultra-light server which can be started and stopped in a test. So we use the InlineServer provided in the Mojasef jar. It’s a real HTTP server which you can use from a regular web browser, but it’s mainly designed for streamlined use in tests.

This server is configured to serve the MessageHarness application on port 9998. Having configured the server we start it in startUp and stop it in tearDown to ensure that nothing is left behind between tests.

The new test makes a HTTP request to the freshly started server, then checks (by calling the MessageHarness method we created earlier) that the test harness application was successfully called. This verifies that the server has been correctly started and called.

It’s still not really testing the message API. To do that we need more tests.

Now, we know from the introduction above that our resource should return a HTTP 404 (“not found”) error if we try to send to an unrecognised address.

  public void test404FromUnknownDestination() throws Exception {
    form.put("destination", "unknown@example.com");
    form.put("text", "hello from HTTP");
    Document result = client.post("http://localhost:9998/send", form);
    assertEquals("404", result.getHeader(HTTPClient.HTTP_RESPONSE_CODE));
  }

Making this test work is pretty simple, especially as we have no other tests which say anything about the HTTP Response code. The only “cleverness” is that we now need to use some slightly smarter features of the Mojasef code.

import org.stringtree.finder.StringKeeper;
import org.stringtree.mojasef.HTTPConstants;
 
public class MessageHarness {
  private boolean called = false;
 
  public boolean wasCalled() {
    return called;
  }
 
  public void send(StringKeeper context) {
    called = true;
    context.put(HTTPConstants.RESPONSE_CODE, "404");
  }
}

Mojasef will try a variety of ways to call a public method. We have seen the basic one – a method with no parameters mapped directly to a URL. This is another one – a method taking a “context” as an argument. This context will be pre-loaded with any POST or URL parameters, as well as any request headers and plenty of other stuff which is not of interest right now. This context also provides a way of setting information to be sent back to the client.

Now, our application code is passing all its tests, but it does so by returning a “404″ error code for all requests. This is not really desirable behaviour, so we need another test:

  public void test200FromKnownDestination() throws Exception {
    form.put("destination", "known@example.com");
    form.put("text", "hello from HTTP");
    Document result = client.post("http://localhost:9998/send", form);
    assertEquals("200", result.getHeader(HTTPClient.HTTP_RESPONSE_CODE));
  }

This test fails, so we need to modify the application to add some understanding of the supplied form data.

import org.stringtree.finder.StringKeeper;
import org.stringtree.mojasef.HTTPConstants;
 
public class MessageHarness {
  private boolean called = false;
 
  public boolean wasCalled() {
    return called;
  }
 
  public void send(StringKeeper context) {
    called = true;
    String destination = context.get("destination");
    if ("known@example.com".equals(destination)) {
        context.put(HTTPConstants.RESPONSE_CODE, "200");
    } else {
        context.put(HTTPConstants.RESPONSE_CODE, "404");
    }
  }
}

Now we reach an interesting point in the development process. It is perfectly feasible to continue in this vein, step-by-step bringing the application into existence. However, even the streamlined InlineServer still needs to set itself up, bind and unbind ports, deal with network traffic and so on. This is considerably slower than a regular method call, and as more tests are added the test case will continue to slow down.

The advantages of the Mojasef approach to web applications really begin to pay off at this point. The tests we already have prove the basics of HTTP Communication are working, so further tests do not really need to bother with HTTP, provided the tests are testing exactly the same code. Luckily (as pointed out earlier) a Mojasef application is just a regular Java class, which needs no modification to be tested using regular JUnit tests. Here are the same tests as above, but implemented as simple method calls:

import org.stringtree.finder.StringKeeper;
import org.stringtree.mojasef.HTTPConstants;
import org.stringtree.mojasef.HTTPConstants;
 
public class MessageProcessingTest extends junit.framework.TestCase {
  StringKeeper context;
  MessageHarness app;
 
  public void setUp() {
    context = new MapStringKeeper();
    app = new MessageHarness();
  }
 
  public void test404FromUnknownDestination() throws Exception {
    context.put("destination", "unknown@example.com");
    context.put("text", "hello from HTTP");
    app.send(context);
    assertEquals("404", context.get(HTTPConstants.RESPONSE_CODE));
  }
 
  public void test200FromKnownDestination() throws Exception {
    context.put("destination", "known@example.com");
    context.put("text", "hello from HTTP");
    app.send(context);
    assertEquals("200", context.get(HTTPConstants.RESPONSE_CODE));
  }

I shall stop there, leaving the development of the rest of the application to interested readers.

From the above steps, I hope you can see that the normal process of Test-Driven Development is quite possible for both web applications, and web-application clients. When using a framework which gets all the fiddly stuff out of the way it can even be as simple, quick and productive as in-process development.

How Agile Benefits the Individual

This is an interesting idea. It’s common for agile techniques to be defined by their benefits to the business, but there is often a benefit to the development of the individual people involved in the agile process, too.

InfoQ: How Agile Benefits the Individual

Smart = Agile++ ?

Despite some concerns for the direction of the term, I consider myself an “agile” software developer. Recently Ivar Jacobson presented a conference session during which he discussed the idea of “smart” as some sort of successor to agile.

Smart = Agile++ by Ivar Jacobson

From the above summary there seem to have been some good points – the issue of the education system not actually covering the attitudes and skills necessary for software development, even in supposedly appropriate courses is one I have ranted about many times.

TDD: Does it make you slower?

I use Test-driven Development (TDD) all the time. Although my immediate work colleagues have “bought in” to the idea, I sometimes find my self explaining about it to other people in other situations. A common question is whether the extra effort of writing all those tests slows down the overall development process. Mark Needham has an article on this very question.

TDD: Does it make you slower? at Mark Needham

Distribute Development and the Quality Will Suffer

A solid, though relatively brief article on the issues facing distributed development.

InfoQ: Distribute Development and the Quality Will Suffer

The Defect Black Market

Every now and then we have a discussion about bugs, whether and how they should be fixed, and the relative importance of each bug compared with key missing features. Solutions range from the naive to the overcomplicated, but at least nobody yet has suggested something like the following…

The Defect Black Market – The Daily WTF

Software Craftsmanship 2009

This looks like a really interesting conference. Now I’m thinking seriously about whether to put together a session and propose it…

Software Craftsmanship 2009 – Home

What’s Missing From the Agile Manifesto

An interesting summary of some thoughts on the agile manifesto, it’s place in software development history, and how/whether it should grow or change.

InfoQ: Brian Marick: What’s Missing From the Agile Manifesto

Clearing my backlog, a mix of links

My browser is full of tabs, each representing something I intend to blog about. I need to clear some space, so here’s a few interesting links without comments.

The Parable of the Two Programmers

I’d not seen this before, but it certainly has echoes of real life.

The Parable of the Two Programmers

Mark Needham on Pair Programming

Two solid articles of the subject recently:

Pair Programming: Driving quickly at Mark Needham

Pair Programming: Benefits of the pair switch mid story at Mark Needham

Who plays the role of technial producer on Agile teams?

Looking at the the way collaborative, creative, teams work in fields other than software development can be very useful. There’s an argument that creating a software release is a lot like creating a music album, for example. Chris Johnston has followed this train of thought and asks if we need an analogue to the “producer”.

Chris Johnston » Who plays the role of technial producer on Agile teams?

Sharing Project Development Knowledge

To make software development work, everyone involved needs a good working knowledge of the product, the domain, the solution and so on. Communicating enough, but not too much, information can be tricky, especially in an agile environment where anything can change at any time.

Tarek Abdelmaguid has an interesting list of ways to communicate while working on a project. I have done almost all of them with various clients and employers, and also made a lot of use of instant messaging. There is definitely scope for using more structured communications such as mailing lists, internal blogs and forums, though.

On Programming and Applications Development: Project Development Knowledge: Sharing and Enduring

Iterating To Acquire Knowledge, Not Just ‘Business Value’

Planning what order to do stuff in is a vital, yet very difficult, part of software development. Agile wisdom usually stresses the need to do things in order of “business value”, but this can sometimes be extremely tricky to evaluate.

Another approach is to do things in an order intended to decrease risk, such as starting with the most worrying, or least understood parts of a system.

InfoQ: Iterating To Acquire Knowledge, Not Just ‘Business Value’

While this sounds plausible, I am not sure I entirely agree the reasoning. Behind the idea of ordering things by risk seems to be the idea that there is some bounded set of requirements, known early enough in the process to be able to determine their “worry”. To me the whole point of agile development is to step outside that assumption into the real world where work needs to start before full scope is defined, where priorities change on a whim, and development on a product may be cancelled at any time.

Starting work by spending a few iterations investigating complex/risky parts of some imagined future product instead of delivering usable but minimal versions from the first iteration seems somewhat irresponsible.

Code reviews and the second worst programmer

Gojko Adzic has written another insightful post, this time about a common trap that teams can fall into, and how promiscuous code reviews help to solve it.

Gojko Adzic » Beware of the second worst programmer