For much of this week I have been taken from my bug fixing work to drag a functional test kicking and screaming across the fine line that separates working from broken.

This test was to ensure that Jira’s “Johnson” servlet filter will correctly stop incoming requests from waking up the plugin system or the micro container (picocontainer) while the system is unable to respond. Cases include while Jira is being setup, during an import etc. Jira returns a 503 Service Temporarily Unavailable response for SOAP, RSS, AJAX etc. URLs.

The functional test is a JWebUnit test which uses HttpUnit underneath so I set HttpUnitOptions.setExceptionsThrownOnErrorStatus(false); to enable my code to assert the 503 response instead of it causing an exception.

After the commit I arrived at work to find that I misread an auto completed method and had broken the build because the static state of the jwebunit test client had not been reset upon teardown.

In the Jira team, you get _The Broken Yo Yo_ if you break the build:


Oops. I commit the change after testing it again.

After lunch, I come back to my screen and see the broken yoyo again:


Bummer. This time I was overzealous in asserting the status message after the 503. That’s server specific and I only ran my tests on Tomcat. Our Bamboo Resin build had failed. OK if it’s 503 that’s good enough. I commit the change after testing on Resin and Tomcat and go home.

Next morning:


Websphere in the overnight build. What now? Wow! Websphere is really crap. It seems to return some weird response that, when using jdk 1.5 or 1.6 results in a runtime exception wrapping an IOException in JWebUnit. Not in JDK 1.4, which we support. My default JDK is 1.4 so I don’t accidently use more recent API features, but I switch over to verify the problem and put this in the test:

catch (RuntimeException re)
// If we get here, it's possible that we are running on java 1.5 +
// and the server is websphere. in this combination (and only this
// one AFAIK) the HttpUnit client receives a null from
// HttpUrlConnection.getErrorStream() which, according to the JDK javadoc
// is supposed to indicate that there is no error. It certainly means
// nothing can be read from it!
// Unfortunately, when HttpUnit then follows the getInputStream() call
// tree it ends up with an IOException it didn't expect.
// To add insult to injury, this IOException is not set as the cause
// of the RuntimeException jwebunit wraps it in so we just make some small
// efforts to ensure the basis of the
// exception is the 503 we were hoping for.
log.warn("Can't assert 503 response, using crude websphere workaround");
WebResponse webResponse = getDialog().getResponse();
assertEquals("expected service unavailable response for url: '" + atUrl + "'",
503, webResponse.getResponseCode());
assertEquals("should be no content for this url: '" + atUrl + "'", 0,

Whew! Finally I test that on Websphere and commit my fix. After lunch my team help me realise my mistake (did you spot it?)


OK. So I used a 1.5 API feature while I had my JDK switched. STOOOPID! It’s looking embarrasing now so I quickly commit after testing on JDK 1.4, 1.5, 1.6, Tomcat, Resin and Websphere and go back to my bug.

The next day I come in:


What!? As I walk in Dylan is ready with his “it wasn’t me…”. Some people are starting to feel sorry for me. Others are busy with the photocopier.

Turns out in the nightly uber build Orion failed due to what now seems to be a bug in Orion 2.0.2 (fixed in 2.0.7). I also found that the specific failure point was checking for the 503 on a URL that our filter is configured to ignore anyway, so I can safely remove that part of the test case and commit. Also, the Orion builds in Bamboo were simultaneously dying with an OutOfMemoryException and Orion wasn’t working on my box. Smackdown!

Even now I am fearful to kick off the builds again. I do get the feeling the universe somehow didn’t want this func test to be written. At least that theory might help me offload some responsibility! 🙂

But on the positive side, Even after working at Atlassian for a while now I can still learn about the team’s prefered methods in the gentle art of communication in the event of a broken build and intend to fully utilise this knowledge should the opportunity arise. (Andreas this means war)

Somebody Didn't Want Me To Func Test This