Monday 9 December 2013

I should pay attention to what my readers tell me! expectException()

G'day:
Sometimes I don't pay attention very well, or my attention span wanders...

... what was I saying?

Oh yeah, MXUnit. And me not paying attention to good advice people give me. I've just adjusted a bunch of my tests from previous articles in my unit testing / TDD series, to handle exceptions better.

A while back Julian pointed this out to me in a comment, and he reminded me again over the weekend in another comment. But this time I paid attention.

At work we are required to write our functions using <cffunction>. I disagree with this policy (and I am trying to get it changed), but that's where we are at the moment. And when we're writing a test function which tests an exception is being raised, we use this syntax:

<cffunction name="tagBasedMetadata" mxunit:expectedexception="TestException">
    <cfthrow type="TestException">
</cffunction>

That's the only way I was aware of doing it. And that's fine. I think the ability to add metadata to a function like that is handy.

However for all my non-work code, I write pretty much everything in script, unless I'm just outputting something quick and a tag seems more expedient.

One can still add metadata like that to a script based function:

// metadata.cfm
function f() foo="bar" {
    writeDump(var=getMetadata());
}

f();

struct
FUNCTIONS
array
1
struct
FOObar
NAMEf
PARAMETERS
array [empty]

There's our foo/bar in the metadata.

But MXUnit has thrown us a bit of a curve-ball here. Let's try using a metadata element with a colon in it, like "mxunit:expectedException":

function f() mxunit:expectedException="SomeException" {
    writeDump(var=getMetadata());
}

BAM:

The following information is meant for the website developer for debugging purposes.
Error Occurred While Processing Request

Invalid CFML construct found on line 3 at column 20.

ColdFusion was looking at the following text::
The CFML compiler was processing:

  • A script statement beginning with function on line 3, column 1.
  • A cfscript tag beginning on line 1, column 2.
The error occurred inC:/apps/adobe/ColdFusion/10/cfusion/wwwroot/shared/git/blogExamples/cfml/functions/badMetadata.cfm: line 3
1 : <cfscript>
2 : // badMetadata.cfm
3 : function f() mxunit:expectedException="SomeException" {
4 :  writeDump(var=getMetadata());
5 : }

(note: this is only a problem on ColdFusion: Railo deals with it OK).

So I had fallen back to the alternate metadata annotation that CFML supports. Doing it in a comment. Now... I can't stand this syntax. It is completely completely completely and utterly wrong that ColdFusion compiles comments as functional, meaningful code. This has to be about the most stupid thing Adobe have added to CFML that I can think of. Even more stupid than <cfmessagebox>. I just can't imagine what they were thinking when they decided to do this.  Cough... anyway... ahem... I mean this syntax:

/**
* @mxunit:expectedException SomeException
*/ 
function g() {
    writeDump(var=getMetadata());
}
g();


If one uses a special comment syntax (/** as opposed to /*), then one can add metadata to a function:

struct
FUNCTIONS
array
1
struct
MXUNIT:EXPECTEDEXCEPTIONSomeException
NAMEg
PARAMETERS
array [empty]

I hate doing it, but that was the only way I was aware of doing it.

Julian has twice now pointed out to me that MXUnit supports an expectException() assertion. And I did not pay attention to him until just now. And I have tested it and it works perfectly. Fantastic. Here's the goods:

public void function viaAssertion(){
    expectException("TestException");
    throw(type="TestException");
}

Note how it needs to go before the expression being tested, not afterwards like most assertions.

This is "documented" as an aside, and in the middle of some sample code, on this page: "What to put in your tests (Assertion Patterns)".

I dunno what version of MXUnit we have in the office, but this works perfectly for my purposes when not at work.

Cool!

How many beers is that I owe you now, Julian? Is that the third? You better collect 'em at some point.

--
Adam