Search code examples
apache-flexunit-testingflash-builderflexunit

Flash Builder 4.5 & FlexUnit 4.1


We have a large, multi-module product we are writing in Flex 4.1 running on top of a Java-based middle-tier.

Coming from a Java background, I want to have support in our Flex environment for writing and running unit tests.

I've updated Flash Builder 4.5 with the 4.1 release of FlexUnit and I can write and execute unit tests successfully on an application project, but I haven't worked out how to get unit tests working on module or library projects within Flash Builder.

Problems with Library Projects

Since we need the tests compiled to an application (SWF), I either need to create a companion project in Flash Builder or change the linkage type on the library (SWC) project's dependencies to avoid external, since external dependencies are expected to made available by someone else (usually the top-level application).

As an experiment I tried changing the linkage on a sample library project: a test runner SWF was successfully generated, but FlexUnit failed to run it as a #1065 error was reported on something that didn't make any sense to me.

For our headless build (using Gradle), I found this easy to solve by simply merging all dependencies irrespective of their original linkage when generating the test runner SWF. I can also run this easily from within Eclipse using the external tool support as the results are JUnit-compatible XML results that display in the usual JUnit view.

How do you do it?

How do other Flex developers structure their unit tests in a multi-module and multi-library project? Do you run the tests from within Flash Builder 4.5? Can you run tests independently for any library or module project?


Solution

  • OK, this is the 2nd time I've answered my own question (the last one was also around Flex).

    I've went for adding tests to each individual project, but I run the tests from a central test project.

    Each project should have:

    • a test directory
    • a MLXML application with the naming convention of <project name>Test.mxml in the test directory
    • a top-level test suite aggregating all tests in the project under the test directory in the usual package structure
    • some unit tests ;-)

    Flash Builder doesn't like MXML applications living in any other directory than src, so it's important to NOT set the test directory as another source directory.

    Now add the test source directories from each project to the overall testing project. You'll need to add all dependencies needed (both runtime and test) to this project.

    I find FlexUnit a bit weird in how it manages the runner for the unit tests. It will offer to generate a test runner MXML application when you select 'run as -> Flex Unit Tests' in Eclipse (you can choose which tests it should run). Selecting the 'Execute FlexUnit Tests' from the context menu doesn't cause the MXML generation.

    You shouldn't check this MXML file into source control, but ignore it. The reason is that FlexUnit doesn't regenerate this file successfully if you want to run a different set of tests. This means you need to manually delete the file whenever you want to re-generate it.

    Here's an example of the MXML we use for the test runner in a library project:

    <?xml version="1.0" encoding="utf-8"?>
    
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               minWidth="955" minHeight="600" creationComplete="onCreationComplete()">
    
    <fx:Script>
        <![CDATA[
            import net.infonic.hs.AllTestsSuite;
    
            import org.flexunit.listeners.CIListener;
            import org.flexunit.runner.FlexUnitCore;
    
            private var core: FlexUnitCore;
    
            public function currentRunTestSuite(): Array {
                var testsToRun:Array = new Array();
                testsToRun.push(AllTestsSuite);
                return testsToRun;
            }           
    
            private function onCreationComplete(): void {
                core = new FlexUnitCore();
                core.addListener(new CIListener());
                core.run(currentRunTestSuite());
            }           
        ]]>
    </fx:Script>
    
    </s:Application>