I’m a fan of unit tests. And, although I probably wouldn’t blazen it across my chest like some, I am sold of the benefits.
However, coming from .NET, I miss quite a bit of the elegance present in NUnit when working with FlexUnit.
Most specifically, the setup of a test suite is kinda clunky.
Normally, you have several classes of unit tests, each which have a static suite() method, returning a test suite comprising the unit tests in that class.
Check out the following example:
public static function suite():TestSuite {
var ts:TestSuite = new TestSuite(); ts.addTest( new MyTestClass(”testMethodA”) );
ts.addTest( new MyTestClass(”testMethodB”) );
ts.addTest( new MyTestClass(”testMethodC”) );
ts.addTest( new MyTestClass(”testMethodD”) );
return ts;
}
As you can appreciate, it doesn’t take long for this to get long and clunky. Also, maintanence is a pain in the butt — adding tests don’t get run if you forget to add it in the Suite method, changing names causes RTE, etc etc etc.
In NUnit (and, presumably JUnit), you just decorate a class with [TestFixture], and a method with [Test], and NUnit takes care of the rest using that groovy cat, Reflection.
Luckily for us, Flex gives us the ability to tell the compiler to retain custom metatags in Flex 3. This means we can achieve similar functionailty — at least at the method level.
The first step is to set the compiler option. In Flex Builder 3, right click your project, hop into Flex Compiler, and add this to the list of compiler options:
-keep-as3-metadata+=Test
Then, using flash.utils.describeType() we can find any methods within a class that are decoared with our [Test] method.
The following method examines a class, and returns a TestSuite which contains a test for each decorated method.
/**
* Generates a test suite with all the methods in a class decorated with [Test] metadata
* @param clazz
* @return
*
*/
public static function fromClass(clazz:Class):TestSuite {
var suite:TestSuite = new TestSuite();
var testMethodNames : XMLList = describeType(clazz).method.(metadata.(@name==”Test”)).@name
for each (var node:XML in testMethods) {
var methodName:String = node.value()
var test:Test = new clazz(methodName);
suite.addTest(test);
}
return suite;
}
Personally, I chose to add this to the TestSuite class in FlexUnit, though you may prefer a seperate util class.
Now, getting all the tests for a class is as simple as:
var suite:TestSuite = TestSuite.forClass(myClass);
Much more readable!
Comments welcomed.
Marty
Update : I modified the disvoery method to use the E4X expression suggested by Theo. I must’ve been having a brain-fart at the time, as I’m a huge fan of the E4X syntax. Nice spotting Theo!