Debugging Flex Unit Tests without Flash Builder Premium

If you have a Flash Builder Standard license, chances are good that you’re lamenting the lack of FlexUnit support. You can run your tests from the command line but then you lose debugging and an integrated results display. You could add a second Application to your project to embed a test runner but due to an annoying bug in Flash Builder, this application file needs to be in your main source folder or else it can’t be added as a run configuration. I set out to find a new solution with the following in mind:

I managed to find a solution that satisfied all my criteria and wasn’t too messy. I’m sure there’s still room for improvement so please comment if you have any suggestions.

Main Project Structure

Package Explorer view of DemoProject

First, make sure that your test cases are in a separate source tree. Create a test suite that references the test cases you want to run:

package com.instantdelay.flex.demo.test
{
   [Suite]
   [RunWith("org.flexunit.runners.Suite")]
   public class Suite
   {
      public var test1:TestWidget;

      public function Suite() {}
   }
}

Create a new MXML component that inherits from Sprite. I named mine DemoProjectTestModule. Declare a variable in this component of type Suite to force the compiler to include your test classes:

<mx:Sprite xmlns:fx="http://ns.adobe.com/mxml/2009"
           xmlns:mx="library://ns.adobe.com/flex/mx">
   <fx:Script>
      <![CDATA[
         public var s:Suite;
      ]]>
   </fx:Script>
</mx:Sprite>

Now, edit your project properties and create a module from this component. Set it to “Do not optimize”. Flash builder will now create a SWF containing all your tests and any application classes they reference.

Screenshot of the Add Module dialog in Flash Builder

The Test Project

Create a new Flex project to hold the test running code. I made mine an AIR app so I could run it in a window and named it TestDemoProject.

  1. In your test project properties, add a source folder pointing to the output directory of your main project which contains the test module SWF. (This will be a subdirectory of bin-debug.)
  2. In the main MXML file for your test project, add the following:
<ns:TestRunnerBase id="runner" />

and

import mx.events.FlexEvent;
import org.flexunit.runner.FlexUnitCore;

private static const TEST_MODULE:String = "DemoProjectTestModule.swf";
private static const TEST_SUITE:String = "com.instantdelay.flex.demo.test.Suite";

private function creationCompleteHandler(event:FlexEvent):void {
   var loader:Loader = new Loader();
   loader.contentLoaderInfo.addEventListener(Event.COMPLETE,
      loaderCompleteHandler);
   loader.load(new URLRequest(TEST_MODULE),
      new LoaderContext(false, ApplicationDomain.currentDomain));
}

private function loaderCompleteHandler(e:Event):void {
   var suite:Class = Class(getDefinitionByName(TEST_SUITE));
   runTestSuite(suite);
}

private function runTestSuite(suite:Class):void {
   var core:FlexUnitCore = new FlexUnitCore();
   core.addListener(runner);
   core.run(suite);
}

This code is where the majority of the work happens. A Loader loads the SWF containing the tests and all your main application classes into the current domain (your test project.) When it finishes, we retrieve the test suite and run it.

And now you’re done! This test project only needs to be built once. When you change your main project the module containing the test cases will build and the test project loads that during runtime. Run the test project in debug mode and debugging support will be enabled.

Screenshot of a breakpoint getting hit during a test

You also get this nice results view:

Screenshot of FlexUnit runner application

Comments