Developing Visual Components with AsUnit
Posted by Luke Bayes Tue, 22 Jan 2008 17:07:00 GMT
I’ve been meaning to write up a huge tutorial on this subject for years now. Since I still haven’t gotten around to it, I’m just going to jam out some quick notes for those of you that might not have caught this stuff buried in the AsUnit 2.5 and AsUnit 3.0 sources.
There are a handful of features in AsUnit that help us develop visual entities. These features are:
TestRunner.startmethodaddChild/removeChildTestCase helpersaddAsynchelper method
For the sake of getting this thing done, I’m not going to go into insane amounts of detail here, so here’s the quick and dirty.
The TestRunner.start Method
The start method of the TestRunner accepts three arguments.
- TestCase Class (required, class): A reference to the TestCase or TestSuite that you would like to run
- Test method name (optional, string): The string method name within the aforementioned test case that you would like to execute
- Show Trace (optional, boolean, defaults to false): Whether or not you would like test results printed to trace output. There is a static member at TestRunner.SHOW_TRACE if you’d prefer to use that.
The typical usage of this method looks like this:
start(AllTests, null, TestRunner.SHOW_TRACE);Now, if you’re working on a particular TestCase, and don’t want to wait for the entire suite to run everytime you compile, you can just update that start method to run only your TestCase as follows:
start(SomeFeatureTest, null, TestRunner.SHOW_TRACE);Where SomeFeatureTest is a class that extends TestCase.
Now, to get to the meat of the matter….
If you’re developing a visual component, you can send in a particular test method name to that second argument. Once this argument has a non-null value, the TestRunner will do the following:
- Instantiate your
TestCase(from the first argument) - Call
setUp()in your custom test case - Call the method name you sent to the
startmethod.
That’s it! This might seem dumb and trivial, but there is something missing here, can you guess what it is?
The tearDown() method is not called.
This means that if you put some visual entities on screen during your set up phase or within your test method, they will still be on screen for you to visually examine.
This dovetails nicely with the next feature that I’d like to talk about.
The addChild/removeChild (and attachMovie) TestCase Helpers
A little-known feature of our TestCase base class is that we added a handful of methods that make it much easier to deal with visual component development. No, the TestCase class does not extend MovieClip or DisplayObjectContainer. We just implemented a couple of methods that make it behave as if it does. What these methods effectively do, is allow you to attach and remove visual entities from the display list (in ActionScript 2 or ActionScript 3).
Usually, I call addChild in setUp and then call removeChild from the tearDown method.
Using these methods during normal test suite execution should result in a perfectly acceptable cleanup after each test method, but using them in combination with the aforementioned methodName argument means that you can instantiate an element of your application in an isolated test context, then visually (manually) ensure that it does in fact look and behave as you expected, and then write tests to automate most of that verification!
(Sorry for the exclamation, I get a little over-excited)
And last but certainly not least….
The addAsync Helper Method
The AsUnit 3 framework has an addAsync method that allows us to pause test execution while waiting for a callback. When called, this method pauses test execution and returns a function. Test execution will be resumed when that returned function is called, or when the timeout has been exceeded. The function that addAsync returns is usually just a delegate to the function that it accepted.
This method can accept two arguments:
- callback (closure, optional): The function that should be called when test execution is expected to resume.
- timeout (number, optional, default 1000): The time in milliseconds that test execution should wait for the callback to be called before throwing a timeout exception.
This method can be called once inside of setUp and it can be called once inside of any test method. If this method is called, test execution will pause until the function that it returned is called.
Following is a short example of how I usually find myself using addAsync.
1 2 3 4 5 6 7 8 | |
The strange thing is that these features are where I live in AsUnit, but very few folks seem to know about them!
So please help us out by spreading the word on how addAsync, addChild/removeChild and the custom TestRunner.start method can change how we all develop features (and tests).













You're definitely not alone! Writing helpful unit tests against visual entities is a challenging and sometimes contentious issue.
We have implemented MVC code-behind schemes in the past where our controller code is extended by an MXML view, which is data-bound to a non-visual Model.
We have then written integration tests against this controller code by initiating a user gesture (event) and then verifying that our view state has been updated, which is an indication that the entire MVC scaffold has been configured correctly.
It's debatable how helpful these tests really are for a variety of reasons, but the one thing that has proven unquestionably valuable to me, is the ability to instantiate and interact with application entities in isolation and outside of their sometimes deep application context.
It's actually been so long since I've written ActionScript 2, I thought we had that feature in there!
As it turns out, I can't promise anything in the near term as I'm completely jammed up on Sprouts development, but if you or anyone else is interested in contributing, definitely let us know!