assertTrue is the professional blog of Luke Bayes and Ali Mills

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.start method
  • addChild/removeChild TestCase helpers
  • addAsync helper 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 start method.

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
public function testSetSomeAsynchronousProperty():void {
    var handler:Function = function(event:Event):void {
        assertEquals(200, instance.otherProperty);
    }

    instance.addEventListener(Event.COMPLETE, addAsync(handler));
    instance.setSomeAsynchronousProperty();
}

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).

Tags  | 4 comments | no trackbacks

Comments

  1. Tony Fendall replied: Avatar I still don't fully understand how this can be used to test visual components. Would you be able to post an example of what you describe?
    Posted: about 4 hours later.
  2. Luke Bayes commented: Avatar Hey Tony,

    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.
    Posted: about 7 hours later.
  3. James Tann replied: Avatar Hey there, just updating an old project and am missing the functionality of addAsync in ASUnit 2.5, is there any chance you are adding it sometime soon? Cheers Jim
    Posted: 7 days later.
  4. Luke Bayes commented: Avatar Hey James,

    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!
    Posted: 13 days later.

Trackbacks

Use the following link to trackback from your own site:
http://asserttrue.com/articles/trackback/1474

Your Reply

Comment Form.

Fields denoted with an "*" are required.