Skip to main content
Known Participant
September 27, 2009
Answered

FlexUnit 4 assert failures have "explosive" stack traces

  • September 27, 2009
  • 1 reply
  • 2084 views

With FlexUnit 4 in Flash Builder 4 Plugin Beta, I created 1 suite with 1 class with 1 default failing test method. When I ran it, the assert failure had a call stack 60 methods high. Is this a bug?

The stack trace has several "async" methods, e.g. applyExplosivelyAsync(). This seems strange because  I'm not using async at all. Is this intended behavior?

Robert


Test method Not yet implemented

       at flexunit.framework::Assert$/

fail()
        at WidgetTest/testWidget()
        at Function/http://adobe.com/AS3/2006/builtin::apply()
        at flex.lang.reflect::Method/apply()
        at ReflectiveCallable/run()
        at org.flexunit.runners.model::FrameworkMethod/applyExplosivelyAsync()
        at org.flexunit.runners.model::FrameworkMethod/invokeExplosivelyAsync()
        at org.flexunit.internals.runners.statements::InvokeMethod/evaluate()
        at org.flexunit.internals.runners.statements::StackAndFrameManagement/evaluate()
        at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.token::AsyncTestToken/sendResult()
        at org.flexunit.internals.runners.statements::AsyncStatementBase/sendComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/sendComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.runners::BlockFlexUnit4ClassRunner/runChild()
        at org.flexunit.internals.runners::ChildRunnerSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.token::AsyncTestToken/sendResult()
        at org.flexunit.internals.runners.statements::AsyncStatementBase/sendComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/sendComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.runners::ParentRunner/run()
        at org.flexunit.runners::Suite/runChild()
        at org.flexunit.internals.runners::ChildRunnerSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.token::AsyncTestToken/sendResult()
        at org.flexunit.internals.runners.statements::AsyncStatementBase/sendComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/sendComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()
        at org.flexunit.internals.runners.statements::StatementSequencer/handleChildExecuteComplete()
        at org.flexunit.internals.runners.statements::StatementSequencer/evaluate()
        at org.flexunit.runners::ParentRunner/run()
        at org.flexunit.runner::FlexUnitCore/beginRunnerExecution()
        at org.flexunit.token::AsyncListenersToken/sendReady()
        at org.flexunit.runner.notification.async::AsyncListenerWatcher/sendReadyNotification()
        at org.flexunit.runner.notification.async::AsyncListenerWatcher/handleListenerReady()
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at flexunit.flexui::FlexUnit4TestRunner/handleConnect()
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at flash.net::XMLSocket/reflectEvent()
This topic has been closed for replies.
Correct answer mlabriola

The FU4 and FU1 support as well as theories and parameterized tests are all actually pluggable runners already. In addition, the community has written pluggable runners that support FUnit, Structured Log Testing and a few other testing frameworks which will be made available soon (projects not under my control so I don't think I should comment on them just yet). It effectively means that FU4 is responsible for identifying a test but then hands off execution to a separate class.

To be a pluggable runner, you simply need to implement 1 interface (org.flexunit.runner.IRunner) and be able to provide the descriptions and hand-shaking required. You specify that you wish to use a plugable runner via the RunWith metadata

You could absolutely write your own to eliminate some of the stacktrace overhead (but there would still be some while FU4 introspects the classes and figures out that you intend to run in a separate runner).

Mike

1 reply

Participating Frequently
September 27, 2009

Not a bug and fully expected behavior.

FlexUnit 4 is really just a collection of runners that can handle just about anything that is thrown at it as well as handle any pluggable runners that others write. The level of extensibility comes with some complexity. So, by the time that single method of yours is executed, there are actually probably a hundreds methods in the framework for getting everything setup, inspected and ready to go.

The stacktrace always looks up the stack from your failure to the last point where a particular chunk of code execution began, so the 60 is basically just that number of methods. There isn't a whole lot that can be done about it save for eventually provinding filtering to eliminate showing some of our stuff and making the track more legible.

Regarding the async thing, your method isn't async but FlexUnit4 is. Inside of the Flash Player we are operating on frames. We don't have the luxury of threads and the like that Java has, so we have to handle the possibility that something might be async on a much deeper level. We also do something called green threading where we actually watch how much time we take in execution. Once we have taken 90% ish of the time available in a given frame, we wait until the next one before we begin executing again. This allows us to run long and compelx test suites without getting a timeout from the flash player (which happens if any single frame takes longer than 15 seconds to execute). So, even though your method isn't doing anything async, all of these other pieces have to account for the chance that something will be. Hence the reason that you see async pieces in the stack trace.

Hope that helps,

Mike

Known Participant
September 27, 2009

Thanks for the explanation, Mike. Pluggable runners sound interesting--what's being worked on in that area (you or others)?

Robert

Known Participant
September 27, 2009

I am curious, though--what does "explosively async" mean?