a little madness

A man needs a little madness, or else he never dares cut the rope and be free. -Nikos Kazantzakis

Zutubi

Ready to Test: Maven + TestNG + Hamcrest + Mockito

I’m no Maven fanboy, but for a new, small Java project the ultra-fast setup time is compelling. So, for my latest little application, I decided to give it a go. Sadly, the default Maven archetype lumped my project with JUnit 3.8.1. Boo. And although the TestNG website mentions an alternative archetype, it appears to have disappeared off the face of the internet.

Luckily, dragging my project into the present wasn’t difficult. Along the way I also added my essential testing libraries: Hamcrest for matchers and Mockito for mocking (well, stubbing, but that’s another story). For posterity’s sake, and for others that share my testing tastes, here’s how it’s done.

Requirements

I’m assuming that you have Maven 2 installed already. If not, it’s trivial to:

  1. Download the latest (2.1.0 at time of writing); and
  2. Install it according to the instructions provided.

You can check if you have Maven ready to go by running:

$ mvn –version
Apache Maven 2.1.0 (r755702; 2009-03-18 19:10:27+0000)
Java version: 1.6.0_12
Java home: /usr/local/java/jdk1.6.0_12/jre
Default locale: en_AU, platform encoding: UTF-8
OS name: “linux” version: “2.6.28-11-generic” arch: “amd64″ Family: “unix”

Bootstrap

With the lack of an available alternative, I found it easiest to start with the default archetype. To create a new project, run something like:

$ mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app

Remember that if you’ve just installed Maven it will take this opportunity to download the internet. Be patient. If you’re new to Maven, you might also want to check out the 5 minute guide which walks through this in more detail.

Check that your bare application has been created:

$ cd my-app
$ find . -type f
./src/main/java/com/mycompany/app/App.java
./src/test/java/com/mycompany/app/AppTest.java
./pom.xml
$ mvn package

$ java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
Hello World!

Add the Dependencies

Next you need to update the project POM to add the testing libraries as dependencies to your build. This involves three changes:

  1. Removing the default dependency on JUnit.
  2. Adding new dependencies for TestNG, Hamcrest and Mockito to the “test” scope.
  3. Configuring the compiler to accept Java 5 source.

The last step is necessary as the Maven default setting assumes Java 1.3 source, which apart from being ancient doesn’t support goodies such as annotations that are required for the new testing libraries. Your updated pom.xml file should look something like:

<project xmlns=“http://maven.apache.org/POM/4.0.0″ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
  xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd”>

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>my-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>5.8</version>
      <scope>test</scope>
      <classifier>jdk15</classifier>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.0-rc2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-all</artifactId>
      <version>1.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins> 
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

I’ve used the latest available versions of each of the libraries in this example — tweak them to suit your current reality.

Update the Sample Test

Now you’re ready to try updating the sample test case to use the trinity of TestNG, Hamcrest and Mockito. The easiest way to do this is to get Maven to generate a project for your IDE, e.g.

$ mvn eclipse:eclipse

or:

$ mvn idea:idea

Fire up your chosen IDE, open the AppTest class, and edit it to exercise all of the dependencies:

package com.mycompany.app;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.annotations.Test;

import java.util.Random;

public class AppTest
{
    @Test
    public void testApp()
    {
        Random mockRandom = mock(Random.class);
        when(mockRandom.nextInt()).thenReturn(42);
        assertThat(mockRandom.nextInt(), equalTo(42));
    }
}

What are you waiting for? Try it out:

$ mvn test

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 18 seconds
[INFO] Finished at: Wed Jun 24 16:11:48 BST 2009
[INFO] Final Memory: 20M/100M
[INFO] ————————————————————————

If you got this far, then everything you need is in place. Now you just have to … implement your project!

Extra Credit

If you poke about a bit, you will also find that the maven surefire plugin, which manages the tests, generates some reports by default. Along with HTML output, it also produces a JUnit-like XML report at:

target/surefire-reports/TEST-TestSuite.xml

This report is ideal for integration with a continuous integration server (in my case Pulse, naturally, but many will support it).

Happy testing!

Citconf Brisbane 2009

Well, it’s that time of year again. Citconf is heading down under, this time to sunny brisvegas on the 26-27th of June. If you have been before, you know how much fun citconf can be, and if you haven’t, I strongly recommend checking it out.

Both Jason and I have been regulars at citconf over the past couple of years. Whilst we will not be there for Brisbane, we will be at citconf paris.

And as always, a big thank you to Jeffrey Fredrick, Paul Julius and the volunteers for doing the leg work to get the ball rolling.

Boost.Test Tutorial Sample Code

Given the fact that people seem to have found my short Boost.Test tutorial, I thought they might appreciate having access to the sample code. So I have cleaned up the code, added a README, and created a repository for it on GitHub:

http://github.com/jsankey/boost.test-examples/

The easiest way to access the code if you have git is to clone:

$ git clone git://github.com/jsankey/boost.test-examples.git

If you don’t have git, you can download a zip or tarball from GitHub.

Happy testing!

Agile: Methodology With Another Level of Indirection

Despite the natural desire to find the “perfect” software development methodology, the simple fact is there is no one-size-fits-all solution. This led me to wonder: are so-called “agile” methodologies just a passing trend? Knowing that there is no silver bullet, can agile really be considered different to trends that have come before?

In fact, I think there is something different about the agile way. The problem of finding the perfect method has been solved in the same way we solve everything in programming: by adding another level of indirection.

Take the Agile Manifesto:

We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value:

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan

That is, while there is value in the items on the right, we value the items on the left more.

I read this of a recognition of the fact that the two toughest parts of software development are:

  1. Dealing with people (communication, collaboration); and
  2. Coping with change (rather than pretending you can avoid it).

These challenges have been and always will be the key to successful projects. By defining agile in terms of these fundamental challenges, rather than specific practices, it can adapt to different circumstances. In fact, thanks to this abstraction, it is not really accurate to think of agile as a methodology — it is much more about culture than specific tools or practices.

The problem with this indirection, however, is it doesn’t give people an easy answer. If you want to try agile, where do you start? There is no secret here: the answer is simply to try things out and see what works. Just remember:

  1. If something works, that’s great, but don’t become complacent. No practice is perfect, always aim for improvement.
  2. If something doesn’t work, think about why. Can you tweak it? Has it run its course? There are no “best” practices: if you give something a proper chance and it doesn’t fit your team, cut it loose.

Put another way, the “secret” to agile is it is constant refactoring — of the process itself.

Pulse 2.0.32: Custom Continuous Integration Trend Reports

I’ve just released another Pulse 2.0 build, and the new features are still coming :). In this case, I have added the long-anticipated ability to capture custom metrics with your build results, then report trends for these metrics over time. You can capture any benchmark of your build that you can imagine, then have Pulse chart it for you. All sorts of charts are supported, with flexible configuration.

As an example, imagine capturing some simple performance measures as numbers. You can then configure Pulse to show them in a line chart:

Configure Report

Pulse stores the metric values with each build, so you can easily see how performance is changing over time:

chart

Most importantly, if performance drops, it is easily visible exactly when it happened, making it much easier to figure out why. You can learn more about how to configure custom reports in the Cookbook.

As part of this change, I also tweaked the default reports that Pulse generates for you. Now all of these reports are configured in the same way as the custom ones above, allowing you to change them to suit your preference. Not only that, but more reports come “out of the box”:

chart2

Sweet! Interested in continuous monitoring of your project’s performance? Try Pulse 2.0 today with a free small team, open source or evaluation license.

Not just good for your project

It seems to be commonly accepted that high levels of Cholesterol is a bad thing

High blood levels of cholesterol are a risk factor for coronary artery disease (heart attacks and angina).

source

So, imagine my surprise when I found out that Pulse, already known to reduce stress levels, is also good for your cholesterol levels.

Nuttelex Pulse Lowers Cholesterol

Nuttelex Pulse Lowers Cholesterol

Hiring “Rock Star” Programmers

I always groan inwardly when I see another job ad calling for a “Rock Star Programmer”. Obviously the idea is that the hiring company is after the top talent. In that sense alone it’s kind of stating the obvious. But is this a good way to attract real talent?

I’m not the only person to think asking for “Rock Stars” is a bad idea. However, several of the other posts I’ve read on the issue, while making some good points, dwell a lot on their own definition of a “Rock Star”. They ascribe several traits to such programmers, none of which directly follow from the vague term. That’s not to say that there isn’t a real point underlying these definitions, though.

To me, the big question is: Do you want to hire someone that would describe themself as a “Rock Star”?. I’ve been fortunate enough to work with a bunch of bright people, and none of them got that way by having overactive egos. On the contrary, even if they knew they had talent, they also knew their limitations. I’m certain, in fact, that this trait was key in allowing them to continue learning and improving.

Naturally job ads always ask for talent — but specifically asking for a “Rock Star” seems to go beyond that. Be careful what you ask for!

You Break (the build), You Bought It

The Pulse 2.0 feature train keeps on rolling. Latest stop: using Pulse to communicate responsibility for a build.

Breaking the build is something to avoid, but even more important is the reaction when it inevitably does break. The key is fixing it fast, before it starts breaking the team’s flow. The worst possible scenarios are:

  • Everyone assumes somebody else is responsible, so nobody fixes it. The build stays broken.
  • Multiple people assume responsibility without talking to each other. Effort is wasted as they all work on fixing the same problem.

Both of these scenarios can be fixed by the same solution: communication. Responsibility for fixing the build needs to be taken by one person, quickly, and communicated to the rest of the team. If nobody has taken responsibility, everyone needs to be aware.

Pulse now supports this directly via the take responsibility feature. When you see the build is broken, you can click a link to take responsibility, optionally adding a comment:

Take Responsibility

Everybody can see who is responsible, both on the project home page, and the summary pages for all builds for the project:

Who's Responsible

Only one person can be responsible at a time, so there’s no confusion. It’s up to the person responsible to decide when their job is done — although you can optionally have responsibility automatically cleared when a build completes successfully (a pretty good indicator that it’s fixed!).

So, start communicating today, and stop wasting time! You can download Pulse and try a free evaluation today. Happy building!

Pulse 2.0: Little Bits of Betterness

Since we initially announced Pulse 2.0 four odd months ago, most of our new feature work has naturally been poured in to Pulse 2.1 (currently in early access). This doesn’t mean, however, that Pulse 2.0 has been standing still. On the contrary, as feedback comes in from customers we continue to tweak — mostly by the addition of minor fixes and features that each make life with Pulse a little better.

Enough improvements have piled up that I thought it would be worthwhile to round up the more important ones, especially for the sake of existing customers wondering what the latest versions can offer. Even the smallest features (implementation-wise) can have a big impact, depending on your usage pattern. Here it goes…

  • Reworked dashboard and browse views: both of these views have been rewritten to be more dynamic, and they now allow you to save the collapsed state of groups using a simple toolbar.
  • Greater dashboard configurability: more control over which groups and projects are shown in which order on your dashboard.
  • Links from configuration pages to reports: you could always jump quickly to a project or agent’s configuration, now you can jump back easily too.
  • Better log time-stamping: a stamp on every line of output for easier diagnosis of build issues.
  • Free-form property descriptions: document your build properties for the benefit of your users.
  • Option to run hooks for personal builds: you can now choose on a per-hook basis whether the hook should be run for personal builds.
  • Import support for pulse files: manage complex pulse files by breaking them down into import-able pieces.
  • Trigger-specific properties: you can pass values through to your build depending on how it was triggered, including remote API triggers.
  • Support for new Trac versions: updates to Trac integration for compatibility with the latest Trac release.
  • Support for Boost.Test: a new plugin to integrate test results from the popular Boost C++ library.
  • Support for skipped test cases: test reporting now understands that tests may be skipped and displays them accordingly.
  • Improved Perforce integration: including better client management, building at a label, and support for ticket authentication.

We hope these features make Pulse just that little bit nicer to work with, and look forward to delivering some even bigger features in 2.1. If you want a slice of the action, download the latest Pulse release now!

Concurrency: Are We Focusing On the Wrong Thing?

It is fairly widely accepted that concurrent programming is becoming more important, and that this trend will only accelerate over coming years. This can be traced back to Herb Sutter’s excellent article The Free Lunch Is Over, which elaborates on how we hit the wall in terms of CPU clock speed around 2003, and further CPU performance has concentrated on hyperthreading and multicore ever since. The figure used in that article is such a dramatic illustration that I’ve seen it used dozens of times in talks and articles since:

Intel CPU Introductions (sources: Intel, Wikipedia)

Intel CPU Introductions (sources: Intel, Wikipedia)

But something bothers me in all the talk about concurrency, and I think it derives from focusing too much on speed. It is true that CPU-bound applications no longer benefit from the “free lunch” of increasing clock speeds. However, I would contend that the vast majority of applications are not CPU bound. Further, many applications that do need a lot of CPU power are already naturally parallelisable: such as the fast-growing category of multi-user web applications.

So although clock speeds have stagnated, for many programmers it won’t have any real performance impact. Most desktop applications will get along just fine, still bound on I/O or a squishy, organic, slow-moving user. Web applications will naturally take advantage of more cores as they appear. The only programmers likely to notice the performance impact are those working in areas where performance has always been at the bleeding edge, which frankly is a small minority.

This doesn’t mean we’re all off the hook, though. Even though few of us write CPU-bound code, many more of us write multithreaded code. Badly. The only reason our code works is because it isn’t run on truly multi-processor systems, and certainly not on systems with dozens of CPUs (or more). Whole classes of concurrency bugs don’t show up until code is stressed on highly parallelised hardware. And it just gets worse as more CPUs or cores are added. We’ve got away with this for a while, but when every desktop has dozens of cores, ignorance will cease to be bliss.

Sutter’s article covers these points, but like most other discussions I think it both underplays them relative to the performance issues, and underestimates how difficult it is to learn concurrent programming. This is a much greater challenge than learning a design technique like OO — concurrent programs, at least those using current locking techniques, are insanely hard to reason about. The true solution, in the opinion of many (myself included), is to move away from shared memory and explicit locking as much as possible. This is a key reason why pure functional programming is seeing a resurgence.

Sutter was right: the free lunch is over. Only it’s not performance we’ll have to pay for: it’s correctness.