Better Unit Tests With FlexUnit

June 17th, 2008 by Joey

This is probably not news. In fact, it's definitely not _new_ news on account of I learned about it from Theo Hultberg's blog from a post from last year (http://blog.iconara.net/2007/02/06/flexunit/). However, it was, rather embarassingly, news to me, and therefore I'll post it just in case someone else doesn't know this. You can write unit tests with FlexUnit using what is probably a more familiar structure to most people than the structure promoted by the FlexUnit documentation.

I've been using FlexUnit for a few years. And during this time I naively thought you _had_ to write tests using the structure that Darron Schall wrote about (http://www.darronschall.com/weblog/archives/000216.cfm). However, I never really cared much for that structure. I found it strange, and it didn't provide the flexibility I wanted in unit tests. For client work I just accepted this. However, recently I started writing a new chapter for the pending Programming Flex 3, and I decided to mention unit tests with FlexUnit. It was at that point that I thought "there must be a better way to write these tests." It was only then that I ran a Google search and read Theo's blog post.

Although Theo's blog post describes how you can alternately write FlexUnit tests I'll summarize with examples as well.

Basically, the popular FlexUnit approach is to use a static method that returns a TestSuite for every test, and the test's constructor accepts a string parameter naming the test method to run. This is the approach that Darron writes about. It's an approach that was unfamiliar to me until working with FlexUnit. My previous experience with unit testing was purely via the (excellent) book Test Driven Development By Example, and in that book the tests are structured differently. Theo describes how to structure tests in that way. That way requires that the test constructor does not require a parameter, and instead the test runner will run all methods on the test class where the method names start with "test". I'll show a simple example.
Consider the following, very complex and useful class that you need to test.


package {
	public class Adder {

		public function Adder() {
		}

		public function add(a:Number, b:Number):Number {
			return a + b;
		}

	}
}

The following shows a simple example test case class. This class defines three test methods, which is clear because the method names start with "test".


package {
	import flexunit.framework.TestCase;

	public class AdderTest extends TestCase {

		public function AdderTest() {
			super();
		}

		public function testPositiveInts():void {
			var adder:Adder = new Adder();
			assertEquals(adder.add(5, 4), 9);
		}

		public function testNegativeInts():void {
			var adder:Adder = new Adder();
			assertEquals(adder.add(-5, -4), -9);
		}

		public function testNaN():void {
			var adder:Adder = new Adder();
			assertTrue(isNaN(adder.add(5, NaN)));
		}

	}
}

The test runner looks like the following.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="creationCompleteHandler();" xmlns:flexui="flexunit.flexui.*">
	<mx:Script>
		<![CDATA[
			import flexunit.framework.TestSuite;

			private function creationCompleteHandler():void {
				var suite:TestSuite = new TestSuite();
				suite.addTestSuite(AdderTest);
				testRunner.test = suite;
				testRunner.startTest();
			}

		]]>
	</mx:Script>
	<flexui:TestRunnerBase id="testRunner" width="100%" height="100%" />
</mx:Application>


Note that we use addTestSuite() to add a reference to the test case class to the test runner. This will automatically run all the methods starting with "test".
Apart from the simplicity and clarity of this way of structuring tests you also get to use setUp() and tearDown(), which automatically run before and after every test method. The following is another example illustrating setUp() and tearDown(). This time we'll use a sort-of VO class called Example that has a static method for creating a new Example object from XML data.


package {
	public class Example {

		private var _a:String;
		private var _b:String;

		public function get a():String {
			return _a;
		}

		public function set a(value:String):void {
			_a = value;
		}

		public function get b():String {
			return _b;
		}

		public function set b(value:String):void {
			_b = value;
		}		

		public function Example() {
		}

		static public function parseFromXml(xml:XML):Example {
			var example:Example = new Example();
			example.a = xml.a.toString();
			example.b = xml.b.toString();
			return example;
		}

	}
}

The test for this looks like the following.


package {
	import flexunit.framework.TestCase;

	public class ExampleTest extends TestCase {

		private var _example:Example;

		public function ExampleTest() {
			super();
		}

		override public function setUp():void {
			_example = Example.parseFromXml(Value 1Value 2);
		}

		override public function tearDown():void {
			_example = null;
		}

		public function testA():void {
			assertEquals(_example.a, "Value 1");
		}

		public function testB():void {
			assertEquals(_example.b, "Value 2");
		}

	}
}

Notice that both setUp() and tearDown() are overridden.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • Fark
  • LinkedIn
  • Live
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati
  • Twitter
  • Yahoo! Bookmarks
  • RSS
  • email

2 Responses to “Better Unit Tests With FlexUnit”

  1. Theo says:

    Since writing that blog post I’ve started using dpUnit instead of FlexUnit. dpUnit is better structured and provides tools more suited to Flex. FlexUnit is more or less a straight port of JUnit, which means it was never designed with Flex in mind.

  2. sandrar says:

    Hi! I was surfing and found your blog post… nice! I love your blog. :) Cheers! Sandra. R.

Leave a Reply