Skip to main content
Participating Frequently
August 9, 2010
Question

How to use SequenceRunner with FlexUnit 4

  • August 9, 2010
  • 1 reply
  • 5937 views

Hi,

I just read the Wiki page about Fluint Sequences at http://docs.flexunit.org/index.php?title=Sequences#Sequences_from_Fluint. I really would like to use sequences as it seems a great way to test flows in UI components.

So I created a first test based on the examples in the wiki. Unfortunately it does not work as I hoped.

The testcase:

package flex.filter.eventFilter.view
{

      import flash.events.Event;

     import mx.events.FlexEvent;

  import net.digitalprimates.fluint.tests.TestCase;

  import org.fluint.sequence.SequenceRunner;
  import org.fluint.sequence.SequenceSetter;
  import org.fluint.sequence.SequenceWaiter;


  public class RelativeDateInputFluintSequence extends TestCase
  {

    private var form:RelativeDateInput;

    [Before(async)]
    override protected function setUp():void
    {
      form = new RelativeDateInput();
      form.addEventListener(FlexEvent.CREATION_COMPLETE, asyncHandler (pendUntilComplete, 100), false, 0, true);
      addChild(form);
    }


    [After(async)]
    override protected function tearDown():void
    {
      removeChild(form);
      form = null;
    }

    [Test(async)]
    public function testForm():void
    {
      var passThroughData:Object = new Object();
      passThroughData.value = 5;
      passThroughData.selectedUnit = "hours";

      var sequence:SequenceRunner = new SequenceRunner(this);

      // Set time in stepper
      sequence.addStep (new SequenceSetter(form.timeStepper, {value:passThroughData.value}));
      sequence.addStep(new SequenceWaiter(form.timeStepper, FlexEvent.VALUE_COMMIT, 100));

      // Set units
      sequence.addStep (new SequenceSetter(form.unitCombo, {selectedItem:passThroughData.selectedUnit}));
      sequence.addStep(new SequenceWaiter(form.timeStepper, FlexEvent.VALUE_COMMIT, 100));

      sequence.addAssertHandler(handleFiveHoursSet, passThroughData);

      sequence.run();
    }


    private function handleFiveHoursSet(event:Event, passThroughData:Object):void
    {
      assertEquals(passThroughData.value * 60 * 60000, form.milliseconds);
    }
  }
}

Note that I did not add the test annotations at first as they were ommitted in the Wiki. I added these later after I got the error below.

When sequence.run() is executed I get this error:

Cannot add asynchronous functionality to methods defined by Test,Before or After that are not marked async
Error: Cannot add asynchronous functionality to methods defined by Test,Before or After that are not marked async
    at org.flexunit.async::AsyncLocator$/getCallableForTest()
    at org.fluint.sequence::SequenceWaiter/setupListeners()
    at org.fluint.sequence::SequenceRunner/continueSequence()
    at org.fluint.sequence::SequenceRunner/run()
    at com.hp.opr.flex.filter.eventFilter.view::RelativeDateInputFluintSequence/testForm()[/home/cschlipf/data/dev/svn/opr/components/common/flex/lib/opr-fx-common/src/test/flex/com/hp/opr/flex/filter/eventFilter/view/RelativeDateInputFluintSequence.as:56]
    at net.digitalprimates.fluint.tests::TestCase/protect()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at net.digitalprimates.fluint.tests::TestCase/executeMethodWhileProtected()
    at net.digitalprimates.fluint.tests::TestCase/runTestMethod()
    at net.digitalprimates.fluint.ui::TestRunner/runTestMethod()
    at net.digitalprimates.fluint.ui::TestRunner/handleTestProcess()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at net.digitalprimates.fluint.tests::TestCase/handleAsyncEventFired()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at net.digitalprimates.fluint.async::AsyncHandler/handleEvent()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.core::UIComponent/dispatchEvent()
    at mx.core::UIComponent/set initialized()
    at mx.managers::LayoutManager/doPhasedInstantiation()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at mx.core::UIComponent/callLaterDispatcher2()
    at mx.core::UIComponent/callLaterDispatcher()

So my guess is that the SequenceRunner is not fully compatible with FlexUnit 4 as asyncronous calls that are internal to the SequenceRunner are not marked as async.

Best regards,

Carsten

This topic has been closed for replies.

1 reply

Inspiring
October 10, 2010

I tr y to find a solution with the sequencer runner as well, did you find one?

Romu

Inspiring
October 10, 2010

If you are interested, I solved it with the TestCase class in the flexunit.framework package:

package com.soma.core.tests.suites.commands {
    import flexunit.framework.TestCase;
    import flash.events.Event;
    import com.soma.core.tests.suites.support.TestSequenceCommand;
    import mx.core.FlexGlobals;
    import flash.display.Stage;
    import com.soma.core.tests.suites.support.TestAsyncCommand;
    import com.soma.core.tests.suites.support.TestEvent;
    import com.soma.core.Soma;
   
    /**
     * <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
     * <b>Class version:</b> 1.0<br />
     * <b>Actionscript version:</b> 3.0<br />
     * <b>Date:</b> Oct 10, 2010<br />
     * @example
     * <listing version="3.0"></listing>
     */
   
    public class SequenceTestCaseSuccess extends TestCase {

        //------------------------------------
        // private, protected properties
        //------------------------------------
       
        private var _soma:Soma;
        private var _count:int;
       
        private static var _stage:Stage;

        //------------------------------------
        // public properties
        //------------------------------------
       
       
       
        //------------------------------------
        // constructor
        //------------------------------------
       
        public function SequenceTestCaseSuccess() {
           
        }
       
        //
        // PRIVATE, PROTECTED
        //________________________________________________________________________________________________
       
        override public function setUp():void {
            _stage = FlexGlobals.topLevelApplication.stage;
            _count = 0;
            _soma = new Soma(_stage);
            _soma.addCommand(TestEvent.TEST, TestAsyncCommand);
            _soma.addCommand(TestEvent.TEST_SEQUENCE, TestSequenceCommand);
        }
       
        override public function tearDown():void {
            var command:TestAsyncCommand = _soma.getCommand(TestEvent.TEST) as TestAsyncCommand;
            if (command) command.dispose();
            _soma.removeEventListener(TestEvent.TEST_ASYNC_COMPLETE, testSequenceHandler);
            _soma.dispose();
            _soma = null;
        }
       
        //
        // PUBLIC
        // ________________________________________________________________________________________________
       
        public function testSequence():void {
            _soma.addEventListener(TestEvent.TEST_ASYNC_COMPLETE, addAsync(testSequenceHandler, 500));
            _soma.dispatchEvent(new TestEvent(TestEvent.TEST_SEQUENCE));
        }

        private function testSequenceHandler(event:TestEvent):void {
            _soma.removeEventListener(TestEvent.TEST_ASYNC_COMPLETE, testSequenceHandler);
            if (++_count < 5) {
                _soma.addEventListener(TestEvent.TEST_ASYNC_COMPLETE, addAsync(testSequenceHandler, 500));
            }
            else {
                _soma.addEventListener(TestEvent.TEST_SEQUENCE_COMPLETE, addAsync(testSequenceCompleteHandler, 100));
            }
            trace("TestSequenceCommand: step", _count + "/5");
        }

        private function testSequenceCompleteHandler(event:TestEvent):void {
            assertNull(_soma.getLastSequencer());
            assertEquals(_soma.getRunningSequencers().length, 0);
            assertNull(_soma.getSequencer(Event(event.data)));
        }
       
    }
}

Participating Frequently
October 10, 2010

Hi All:

Sorry I missed this post before. I did not even see it until a reply was posted.

The problem in these examples is that concepts are being mixed and matched.

In FlexUnit 4, you will never extend from a TestCase class.If you are extending from TestCase, you are no longer running in FlexUnit 4. You are now running inside of Fluint (or FlexUnit .9) depending on which TestCase class you extend from. FlexUnit 4 allow you to still write cases this way for backwards compatibility but it literally delegates the running of this test to the old framework.

Concepts like Before and After were not present in those original frameworks. They are FlexUnit 4 concepts. Therefore, when you extend from TestCase but then use a Before or After... all of the Before/After and other code is completely and totally ignored.

The SequenceRunner stuff is 100% compatible with FlexUnit 4 and works properly. We actually use it to test parts of FlexUnit 4.

So, going back to the very first post in this thread. If you removed the words "extends TestCase" It probably would have worked fine.

Mike