A rewrite is probably in order for FlexUnit.  The original goal (of the folks who wrote the AS2 version) was to make it as close to JUnit as possible.  With the asynchronous nature that may be more difficult. 

 

Anyway, what we did in our unit tests when it was possible to receive the fault was just write the async handler to accept both ResultEvent and FaultEvent (using their superclass which I think is RPCEvent).  Then we’d just assert that the event was a ResultEvent and if it wasn’t the assertion failed and the test failed and voila.  Basically you need to do one addAsync for every invocation that could lead to an event, not for every possible return event.

 

Matt

 


From: [email protected] [mailto:[email protected]] On Behalf Of kaleb_pederson
Sent: Friday, August 25, 2006 12:06 PM
To: [email protected]
Subject: [flexcoders] Re: Asynchronous TestCase.setUp in FlexUnit (and another use case)

 

Thanks Matt!

Here's a real-world example of where the fixed ordering of the
addAsync calls just bit me:

I'm testing what is essentially an HTTPService, that could throw a
result or a fault. I instinctively wrote the following:

public function testChangeUser():void {
// cp is my service object that throws results and faults
var tempfunc:Function = addAsync(handleChangeUserPart1,TIMEOUT);
cp.faultCallback = addAsync(
handleUnexpectedFault,
TIMEOUT,
"testChangeUserPart1",
onNotCalledIgnore);
// NOTE: I had to use a temporary function because I don't expect
// the fault handler to be called, but the error must be caught if
// it is
cp.addUser("userToBeAdded",tempfunc);
}

private function handleChangeUserPart1(data:ResultEvent):void {
assertEquals("true",data.[EMAIL PROTECTED]);
// ok, user has been added, verify that I can change the username
var tempfunc:Function = addAsync(handleChangeUserPart2,TIMEOUT);
cp.faultCallback = addAsync(
handleUnexpectedFault,
TIMEOUT,
"testChangeUserPart2",
onNotCalledIgnore);
cp.changeUserName("oldname","newname",tempfunc);
}

private function handleChangeUserPart2(data:ResultEvent):void {
assertEquals("true",data.[EMAIL PROTECTED]anged);
}

private function handleUnexpectedFault(e:*,d:*=null):void
{fail("blah");}
private function onNotCalledIgnore(d:*):void {}

The above seems pretty straightforward. I add the user, when the
response comes back and I confirm that the user was added, I change
the username and then confirm that the username was changed.

However, it doesn't work like that. Because I have a second call to
addAsync() in testChangeUser, the Unit Test framework expects that
the next async callback to come is my fault event, which is not the
case -- my next event is the receipt of my call to change the
username. I don't care if it gets skipped nor do I want to require
that it gets called. Thus, my testcase errors out because of
ordering.

I can't remove the call or reference to addAsync(myFaultCallback)
because I need it to handle faults....

I haven't been able to come up with a workaround for this case --
any suggestions?

Matt, I'll gladly try to help fix these issues, but I need a bit
more direction on where to look (ok... I could figure it out, but
I'm not that zealous nor do I have quite that much time ;).

BTW, I have wondered many times if FlexUnit would work better if the
whole thing was structured on async events. Of course, that would
require a major re-work, but it seems a lot more natural given the
number of async events that need to be dealt with in Flex....

Thanks for the help everyone.

--Kaleb

--- In [EMAIL PROTECTED]ups.com, "Matt Chotin" <[EMAIL PROTECTED]>
wrote:
>
> Doing a while loop won't work, if it did we wouldn't have all the
> complications of this system :-) Your idea of #1 is exactly
right,
> setup now needs to become more like the async calls.
>
>
>
> Sorry, I haven't looked at this code in a year, you'll need to
muddle
> through but it should be doable.
>
>
>
> Matt
>
>
>
> ________________________________
>
> From: [EMAIL PROTECTED]ups.com
[mailto:[EMAIL PROTECTED]ups.com] On
> Behalf Of kaleb_pederson
> Sent: Tuesday, August 22, 2006 12:19 PM
> To: [EMAIL PROTECTED]ups.com
> Subject: [flexcoders] RE: Asynchronous TestCase.setUp in FlexUnit
(and
> another use case)
>
>
>
> Matt and all,
>
> I took a quick stab at this as it didn't look too bad, but
> unfortunately, it isn't quite that simple. FlexUnit is written
such
> that it expects a number of things to happen synchronously, which
> causes some other problems in this case.
>
> Let me explain. After modifying TestCase::runMiddle() to wait for
a
> flag indicating that the testcase setup has completed, runMiddle
> fires off a timer and waits for the flag to change. At this point,
> runMiddle, as called by ProtectedMiddleTestCase::protect(),
returns
> and the next TestCase is fired off. In the end, this results in
the
> setup function being called many times before the test cases
> actually fire off (as the test cases are now waiting for the flag
to
> change) and many test functions being called in parallel when the
> flag changes.
>
> There are a couple of different ways that seem like obvious
> solutions:
>
> 1) Change the setup process so that it worked kind of like the
async
> calls as handled by addAsync.
> 2) Instead of allowing runMiddle to return (as its synchronous),
put
> it in a while loop waiting for the flag to change [!BAD HACK!]
>
> I don't fully understand the interactions between all the
different
> classes and objects at this point, so I'm not sure if there is an
> easy way to get to a reasonable solution, so I'm asking for
> feedback. Is there an easier way to make this work correctly?
> Other suggestions?
>
> Another sample use case:
>
> Unfortunately, when callbacks are registered with addAsync(), the
> order in which the calls are made imposes a restriction on the
order
> in which the callbacks can return.
>
> For example, assume my test requires two different XML files
loaded
> from externally:
>
> public function testValidateExternalRefs():void {
> var loader1:URLLoader = new URLLoader();
> var loader2:URLLoader = new URLLoader();
> loader1.addEventListener(Event.COoverride
> MPLETE,addAsync(onComplete1,TIMEOUT));
>
>
loader2.addEventListener(Event.COMPLETE,addAsync(onComplete2,TIMEOUT));
>
> loader1.load(new URLRequest(myUrl1));
> loader2.load(new URLRequest(myUrl2));
> }
>
> The use case above presents a problem because I cannot guarantee
> which response is going to come back first. Admittedly, in this
> case I could load the files in the setUp call (or chain a bunch of
> events so that the first one has loaded, and then the second one
has
> loaded, and so on and so forth). The problem that I'm running into
> is because of the required strict ordering of asynchronous
> responses, I'm having to chain a lot of events for something that
> could be quite simple. Although the above use case is fabricated,
I
> hope it shows the problem.
>
> Does anybody have some suggestions on how I might work around
these
> issues? I'll gladly modify code if I need to -- I'm just trying to
> avoid having to understand all the code from the ground up to come
> up with a solution.
>
> Thanks for the help.
>
> --Kaleb
>
> -----Original Message-----
> From: Matt Chotin [EMAIL PROTECTED]
> Sent: Mon, 06 Mar 2006 22:40:46 -0800
> Subject: [flexcoders] Asynchronous TestCase.setUp in FlexUnit
>
> My thought is that this is a good use-case and you should look
into
> proposing how a class should indicate asynchronous setup and
> teardown
> and then go ahead and implement. Then submit as a proposal :-)
>
> One idea is that we could add a variable called ready to the
> TestCase
> that is by default true. We would then adjust the runMiddle()
> method to
> check the ready variable and if it is true go ahead and call
> runTestOrAsync. If it is false it simply would wait and call
itself
> again a little later. Then in your setup you set ready to false,
> and
> when your data loads you set ready to true.
>
> I haven't thought it all the way through, but something like this
> could
> work. Check the source out and maybe override some of those
methods
> in
> your own testcase to see how it works out.
>
> Matt
>
> -----Original Message-----
> From: bringrags [EMAIL PROTECTED]
> Sent: Monday, March 06, 2006 2:02 PM
> Subject: [flexcoders] Asynchronous TestCase.setUp in FlexUnit
>
> Hi,
>
> I've been using FlexUnit with one of my projects and ran into a
> problem. In one of my test cases, I want to load a bunch of data
> from
> an XML file in the TestCase.setUp() method, and have all of the
> individual tests use this as a fixture.
>
> The problem is that loading a file is an asynchronous operation,
but
> there's no mechanism to make setUp asynchronous. Consider the
> following excerpt:
>
> public function setUp():void
> {
> var loader:URLLoader = new URLLoader();
> loader.addEventListener(Event.COMPLETE,onComplete);
> loader.load(new URLRequest("myfile.xml"));
> }
>
> private function onComplete(event:Event):void
> {
> var loader:URLLoader = URLLoader(event.target);
> myXML = new XML(loader.data);
> }
>
> public function testSomething():void
> {
> assertTrue("Should pass", myXML.someElement = "some value");
> }
>
> The problem is that testSomething() gets called before
onComplete().
> Ideally I would like to prevent the tests from running until the
> onComplete() method is called.
>
> FlexUnit provides support for having a chain of asynchronous
tests,
> but it doesn't seem to provide support for chaining asynchronous
> setup
> tasks. One possible workaround is to have each test method
> explicitly
> prepare the setup fixture:
>
> public function testSomething():void
> {
> beginTestSetup(testSomethingHandler);
> }
>
> private function testSomethingHandler(event:Event):void
> {
> endTestSetup(event);
>
> assertTrue("Should pass", xml.someElement = "some value");
> }
>
> private function beginTestSetup(eventHandler:Function):void
> {
> var loader:URLLoader = new URLLoader();
>
>
loader.addEventListener(Event.COMPLETE,addAsync(eventHandler,1000));
> loader.load(new URLRequest("myfile.xml"));
> }
>
> private function endTestSetup(event:Event):void
> {
> var loader:URLLoader = URLLoader(event.target);
> myXML = new XML(loader.data);
> }
>
> But this is less than ideal. Any thoughts?
>
> -- Brian
>

__._,_.___

--
Flexcoders Mailing List
FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt
Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com





SPONSORED LINKS
Web site design development Computer software development Software design and development
Macromedia flex Software development best practice


YAHOO! GROUPS LINKS




__,_._,___

Reply via email to