I'm in the process of converting a Flex 3 project to use FlexUnit4 tests.
Everything compiles in Flashbuilder 4.5 and runs nicely. I've converted all the tests
to use flexunit 4, which highlighted a few issues, but nothing too major, and all the
tests now pass when run in Flashbuilder.
So... now, I'm trying to convert the CI build to use the 4.5 SDK and flexunit4. So far,
so good. Everything runs and I get a nicely formatted JUnit report. Unfortunately, though,
any test that uses the UIImpersonator fails with an async method timeout, suggesting that
the CreationComplete event hasn't fired.
Here's a typical example of one of my UI test cases:
[Test(async, ui)]
public function testAvailableProductsSetupAdminForSell() : void {
var view:OrderBasketView = new OrderBasketView();
var user:CfxUser = new CfxUser();
user.admin = true;
ModelLocator.instance.userDetails = user;
view.buyOrSell = OrderType.SELL;
helper.createComponentAndAddListener(view, this, availableProductSetupAdminForSellCreationComplete);
}
private function availableProductSetupAdminForSellCreationComplete(event:Event, view:OrderBasketView) : void {
Assert.assertTrue(view.availableProductTypes.contains(ProductType.PRODUCT_1));
Assert.assertTrue(view.availableProductTypes.contains(ProductType.PRODUCT_2));
Assert.assertTrue(view.availableProductTypes.contains(ProductType.PRODUCT_3));
}
and helper.createComponentAndAddListener looks like this:
public function createComponentAndAddListener(view:UIComponent, testCase:Object, creationComplete:Function) : void {
_view = view;
_view.addEventListener(FlexEvent.CREATION_COMPLETE, Async.asyncHandler(testCase, creationComplete, 4000, _view));
UIImpersonator.addChild(_view);
}
If I use FlexGlobals.topLevelApplication.parent.addChild(_view) in place of UIImpersonator.addChild(_view), all the tests pass.
I was wondering if it's a function of the fact that my helper class has no metadata that indicates it's a ui test, but that wouldn't explain why it works in FlashBuilder and not when run with ant.
I also wondered if it was a function of running with headless server set to true, but when I changed it to false the same thing happened.
My environment is:
ubuntu 11.04
ant 1.7.1
Sun jdk 1.6.0_26
Flex SDK 4.5.1.21328
FlexUnit 4.1.0-8-4.1.0.16076
I'm using the auto-generated TestRunner.mxml
Any thoughts, anyone? Now that I can get it to work by adding the UI components to the topLevelApplication, at least I can make progress, but I'd like to get to the bottom of the problem, because that shouldn't be necessary.
Thanks in advance,
-Chrisl
Hi Michael, thanks for the quick reply!
Yes, that's correct.
Non-UI tests pass in flashbuilder, and pass in the CI environment.
UI tests pass in flash builder, but fail in the CI environment when using UIImpersonator.
UI tests pass in flash builder, and also pass in the CI environment when using topLevelApplication.
Obviously it's ugly having the UI components added to topLevelApplication, but it's the only thing I've found that will get my tests to pass under ant.
okay i will try to replicate. the uiimpersonator is effectively a container or a group added to the system manager to receive those children. in the short term do the top level app hack or make a singelton container attached to the app. i will hopefully figure this out for you today but i confirmed our ui tests are working in our ci environment so it might not be straight forward.
Our CI is Hudson, and we are running the flex tasks headless. In our build.xml file we run the debugPlayer for unix using the following path: ${FLEX_HOME}/runtimes/player/10.1/lnx/flashplayerdebugger... This works great with all unit tests that don't use UIImpersonator.
I just tried the workaround listed here and am waiting for an executor to build on to see if that worked... Will post when I know.
If that didn't answer your question, feel free to let me know. And thanks for the quick reply!! ![]()
Changing to the topLevelApplication did not work. What's funny is that it then failed on a completely unrelated test by hanging and never returning... I'm thinking there must be something else that is going on here, but it's not clear what... :-/ Here is an example of my setup/teardown and a test that work great in the UI but not in CI...
[Before(async, ui)]
public function setUp():void
{
_fromToList = new FromToList();
_fromToList.setStyle('skinClass', FromToListSkin);
Async.proceedOnEvent(this, _fromToList, FlexEvent.CREATION_COMPLETE, 1000);
FlexGlobals.topLevelApplication.parent.addChild(_fromToList);
// UIImpersonator.addChild(_fromToList);
}
[After(ui)]
public function tearDown():void
{
FlexGlobals.topLevelApplication.parent.removeChild(_fromToList);
// UIImpersonator.removeChild(_fromToList);
_fromToList = null;
}
[Test(async)]
public function should_remove_selected_item_in_to_list_to_from_list():void
{
_fromToList.fromArrayList = _dpArray;
_fromToList.toArrayList = _toDpArray;
var sequence:SequenceRunner = new SequenceRunner(this);
sequence.addStep(new SequenceSetter(_fromToList.toList, { selectedItem: _toDpArray[1]}));
sequence.addStep(new SequenceWaiter(_fromToList.toList, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceCaller(_fromToList, _fromToList.remove));
sequence.addStep(new SequenceWaiter(_fromToList, FromToListChangeEvent.FROM_TO_LIST_CHANGE_EVENT, 100));
sequence.addAssertHandler(handleListHasChangedThenRemoveEvent, {});
sequence.run();
}
private function handleListHasChangedThenRemoveEvent(event:FromToListChangeEvent, passThruData:Object):void
{
assertThat(_fromToList.toArrayList.length, equalTo(_toDpArray.length - 1));
assertThat(_fromToList.fromArrayList.length, equalTo(_dpArray.length - _toDpArray.length + 1));
assertTrue(_fromToList.fromArrayList.contains(_toDpArray[1]));
}
So you can see that I'm using Sequences to manage waiting for stuff to get updated in the background, and basically testing when I select an item in a list and act on it that it updates the model like I expect. Again, works GREAT in the UI Runner.
I'm open to suggestions...
What if you just remove the sequence stuff, in other words:
[Before(async, ui)]
public function setUp():void
{
_fromToList = new FromToList();
_fromToList.setStyle('skinClass', FromToListSkin);
Async.proceedOnEvent(this, _fromToList, FlexEvent.CREATION_COMPLETE, 1000);
UIImpersonator.addChild(_fromToList);
}
[After(ui)]
public function tearDown():void
{
//FlexGlobals.topLevelApplication.parent.removeChild(_fromToList);
UIImpersonator.removeChild(_fromToList);
_fromToList = null;
}
[Test(async)]
public function should_remove_selected_item_in_to_list_to_from_list():void
{
//leave me blank
}
Does it complete the test or timeout?
Mike
I setup my FlexBuilder (4.5) to run the ant task in my windows environment. When I did that, I'm seeing the following exception get thrown (which is probably causing the hang):
Error: Skin for FromToList132.FromToListSkin133.VGroup134.fromList cannot be found.
at spark.components.supportClasses::SkinnableComponent/attachSkin()[E:\d ev\4.x\frameworks\projects\spark\src\spark\components\supportClasses\S kinnableComponent.as:632]
at spark.components.supportClasses::SkinnableComponent/validateSkinChang e()[E:\dev\4.x\frameworks\projects\spark\src\spark\components\supportC lasses\SkinnableComponent.as:405]
at spark.components.supportClasses::SkinnableComponent/commitProperties( )[E:\dev\4.x\frameworks\projects\spark\src\spark\components\supportCla sses\SkinnableComponent.as:419]
at spark.components.supportClasses::ListBase/commitProperties()[E:\dev\4 .x\frameworks\projects\spark\src\spark\components\supportClasses\ListB ase.as:785]
at spark.components::List/commitProperties()[E:\dev\4.x\frameworks\proje cts\spark\src\spark\components\List.as:907]
at mx.core::UIComponent/validateProperties()[E:\dev\4.x\frameworks\proje cts\framework\src\mx\core\UIComponent.as:7933]
at mx.managers::LayoutManager/validateProperties()[E:\dev\4.x\frameworks \projects\framework\src\mx\managers\LayoutManager.as:572]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.x\framewo rks\projects\framework\src\mx\managers\LayoutManager.as:730]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.x \frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]
This might be off-topic for the original post and if so I'm happy to start a new one. This looks like when I try to set the skinClass, it doesn't like what is in that class... This is our first spark component to get unit tests wrapped around it... It errors with "Skin for FronToList132 cannot be found." if you don't include the skin at all.
I now suspect that once I figure out the skin thing, that the sequence tests and UIImpersonator will run fine. I'm assuming the skin issue is related to running headless, but we can't be the only ones who have done this... Again, let me know if this is really a different topic.
Thanks for the help!
I had the same problem. For Continuous Integration with Ant and Hudson I've found working this code:
// this works _only_ for GUI runner
// UIImpersonator.addChild(myComp)
// this works for CI:
Application.application.parent.addChild(myComp);
I couldn't firure out how to report this bug to FU team, but maybe I didn't try too hard.
Hoppe they will fix this soon.
North America
Europe, Middle East and Africa
Asia Pacific