Question about FlexUnit 4/ ui-input Integration

19 views
Skip to first unread message

Florian

unread,
Oct 8, 2010, 11:24:29 AM10/8/10
to givwenzen-flex
Hi,

I've just started learning givwenzen-flex, it looks like a great
project.

I downloaded the source code and looked at how you can integrate it
with FlexUnit 4 and ui-input.

There is a well explained page on the wiki for that :
http://bitbucket.org/loomis/givwenzen-flex/wiki/UITesting
However FlexUnit 3 is used in this tutorial.

What I'd like to know is how I should call the ApplicationStartup
class that initialize ui-input with FlexUnit4. (With FU3, you override
provideBeforeTest() method)

Because I never call ApplicationStartup, I get a "Did you forget to
add install' which makes sense.

Kris

unread,
Oct 8, 2010, 2:24:56 PM10/8/10
to givwenz...@googlegroups.com
Hi Florian,

I'm glad you want to try givwenzen! Indeed flexunit4 tutorial is still pending but now I have more motivation to make it happen ;).

Just to let you get started I'm posting here some stuff we use in our projects. First of all flexunit4 is a bit different from the flexunit3 due to some limitations.

1) A base class that you inherit from to create a driver for individual test:

package functional
{
import flash.display.DisplayObject;

import mx.core.Application;
import mx.events.FlexEvent;
import mx.managers.ISystemManager;

import org.flexunit.async.Async;
import org.flexunit.rules.IMethodRule;
import org.morefluent.integrations.flexunit4.MorefluentRule;
import org.uinput.install;

public dynamic class FunctionalScenario
{
    [Rule]
    public var morefluent:IMethodRule = new MorefluentRule(); // this gives morefluent assertions and async support

    // below is to link AllSteps with the app - AllSteps keeps references to all domain steps in the application to make sure they are linked with the swf
    AllSteps;

    public function FunctionalScenario()
    {
    }

    public function instantiateComponent(componentClass:Class = null):void
    {
        componentClass = componentClass || MyMainApplication;
        if (!applicationInitialized(componentClass))
        {
            var component:DisplayObject = new componentClass();
            // adds the application
            installComponent(component);
            // needed by u-input
            install(component);
            // make sure the test is not executed before the components are ready
            Async.proceedOnEvent(this, component, FlexEvent.CREATION_COMPLETE);
        }
    }

    protected static function applicationInitialized(componentClass:Class):Boolean
    {
        var systemManager:ISystemManager = Application(Application.application).systemManager;
        for (var i:int = 0; i < systemManager.numChildren; i++)
        {
            if (systemManager.getChildAt(i) is componentClass)
            {
                return true;
            }
        }
        return false;
    }

    protected static function installComponent(component:DisplayObject):void
    {
         // a bit ugly but still works - forget about the UIIpersonator for any reason it does not work well
        var application:Application = Application(Application.application);
        var systemManager:ISystemManager = application.systemManager;
        systemManager.removeChild(application);
        systemManager.addChild(component);
    }
}
}

2) Then when you create your individual test you do:

package functional.stories
{
import functional.FunctionalScenario;

import org.givwenzen.integration.flexunit4.GWZRunner;

// make sure you mark the test driver with a GWZRunner otherwise it won't work
[RunWith("org.givwenzen.integration.flexunit4.GWZRunner")]
public dynamic class OurFirstStory extends FunctionalScenario
{
    // embed acceptance criteria with appropriate mime-type! it's also nice to make paths relative to source root to improve feedback messages
    [Embed(source="/functional/stories/OurFirstStory.gwz", mimeType="application/octet-stream")]
    public static var criteria:Class;

    public function OurFirstStory()
    {
        // always register scenario on the constructor
        GWZRunner.addValidationScriptFromResource(criteria, this);
    }

    // this part is crucial - must the Before instead of BeforeClass - Async does not work with BeforeClass - this is flexunit limitation
    // but no worries the instantiateComponent() does it only once
    [Before(async, ui)]
    public function prepareToTest():void
    {
        instantiateComponent();
    }

    [AfterClass(async)]
    public static function cleanUpBeforeNextTest():void
    {
        // bring back the system into a neutral state to avoid test dependencies and interference
    }
}
}

Some tips/gotchas:

1) We prefer single *Story.as driver class for a single acceptance criteria *.gwz file
2) We chose to use Story*.as or *Story.as pattern for the drivers to ease maven integration
3) The criteria tear down can be done easily with AfterClass, but any prerequisites require extra step in the acceptance criteria that can provide right setup
4) Create 'inprogress' folder to separate acceptance criteria that must pass from those that you currently work on to support TDD
5) We created a nice IntelliJ template for a new acceptance criteria driver. I'll post it if you are interested
6) All of our steps are market with a [Mixin] annotation and they register their selves in the GivWenZen - all you need to do is to make sure they are linked with the app

If you are interested in maven integration let me know. I'll add the example setup.

Hope this helps!
Kris

Florian

unread,
Oct 10, 2010, 9:16:31 AM10/10/10
to givwenzen-flex
Kris,

First, thanks for this quick and detailled answer!

I followed all the steps from your answer but there is probably
something I did wrong because
I get an error : "Cannot find component userName"

After debugging, I found out that my main application was not
completely created before
the tests are executed (If I look at the debugger, subcomponent such
as userName are null).

I'm still looking at it but I haven't figured out yet why it behaves
like this.
I've uploaded the sample on my dropbox in case you have some time to
look at it :
http://dl.dropbox.com/u/12625401/TestBDD.zip

3 other things :
- Of course, I'm interested in maven integration but I'll spend more
time on the subject once I'm comfortable with givwenzen.
- I'm using Flash Builder but I'm curious about your IntelliJ
template. What does it do exactly?
- I see u-input only works for Flex 3 components now. Any idea about
when spark components will be added?

Thanks.

Florian

Kris

unread,
Oct 10, 2010, 10:41:11 AM10/10/10
to givwenz...@googlegroups.com
Hi,

Your issues result from a mistake you made  in line 52 of BaseFunctionalScenario.as. The source code reads:

            systemManager.addChild(application);

Should be:

            systemManager.addChild(component);

After changing it your test passes.


The template simply saves some time and makes adding new acceptance criteria a breeze.

As far as uinput - since I'm stuck with flex 3 for now I cannot promise anything. But it's open source - you are welcome to contribute. I spent some time trying to get the SDK4 build but apparently there were changes made to the automation framework and some functionality does not work anymore for the mx components.

Regards,
Kris


Florian

unread,
Oct 10, 2010, 11:03:54 AM10/10/10
to givwenzen-flex
Thanks for the catch Kris, I couldn't figure out what was going
on...now it seems so obvious!

I don't know much about the automation framework but that doesn't mean
I won't try to contribute
or at least have a look of how u-input uses it.

Florian

On 10 oct, 16:41, Kris <kris.karczmarc...@gmail.com> wrote:
> Hi,
>
> Your issues result from a mistake you made  in line 52 of
> BaseFunctionalScenario.as. The source code reads:
>
>             systemManager.addChild(*application*);
>
> Should be:
>
>             systemManager.addChild(*component*);
Reply all
Reply to author
Forward
0 new messages