Tag Archives: as3

it happens to the best of us

Sigh. Yesterday, I was digging through a data class on one of our projects and found this little gem:

[as3]
public function hasChanged() : Boolean {
return false;
}
[/as3]

Upon further investigation of the SVN logs, I can confirm that – yes – I was the one to blame.

Now, the method has to exist for interface reasons… but I’ve also confirmed that it’s never being called anywhere. So… I’ve attached an apologetic comment to the function and will pretend this never happened 😛

as3 dec <-> hex

Actionscript suffers like many other languages from poor string parsing commands. What would take one line of well crafted perl is… a bit more complex here.

[as3]
public function hex2dec( hex:String ) : String {
var bytes:Array = [];
while( hex.length > 2 ) {
var byte:String = hex.substr( -2 );
hex = hex.substr(0, hex.length-2 );
bytes.splice( 0, 0, int("0x"+byte) );
}
return bytes.join(" ");
}

private function d2h( d:int ) : String {
var c:Array = [ ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’ ];
if( d > 255 ) d = 255;
var l:int = d / 16;
var r:int = d % 16;
return c[l]+c[r];
}

public function dec2hex( dec:String ) : String {
var hex:String = "0x";
var bytes:Array = dec.split(" ");
for( var i:int = 0; i < bytes.length; i++ )
hex += d2h( int(bytes[i]) );
return hex;
}
[/as3]

What do these methods do? Well, hex2dec takes a hexadecimal string (and assumes you have a throwaway prefix of “0x” or “#”) and returns a space-separated list of decimal values. dec2hex does the same thing, but in reverse.

hex2dec("0xF00F04") returns “240 15 4”.
dec2hex("240 15 04") returns “0xF00F04”.

Also, the method doesn’t much care if you’ve got 6 hex digits or 60.

There are a few optimizations I could make on this code here, but it’s not getting called that frequently anyway. The performance gains in my application would be trivial.

And just by way of warning, this is AS3 code. It’d need a few tweaks to work reliably in AS2 or (shudder) AS1 environments.

update – may 7, 2008

It has come to my attention that people keep stumbling across this old post. While I don’t have the time or interest to optimize these functions for real environments in any of the several ways they could be improved… I figure I’d take a moment for the benefit of those who are probably just looking for the quick answer.

The easiest way of getting a hex string from an int value is to call its toString() method with a radix argument of 16. Likewise, you can request any integer base from 2 to 36. Results use lower-case letters when outputting in a base higher than ten.

240.toString(16) returns “f0”.
240.toString(8) returns “360”.

flexunit basics

The following is adapted from a brief tutorial I wrote for our company‘s internal conventions wiki.

And yes, I know the syntax hiliting could be better. I’m looking into switching over to WordPress and a new stylesheet, so hopefully this sort of thing will all be resolved in the nearish future.


FlexUnit

FlexUnit is a powerful unit testing framework for as3/flex2 projects. There are two API’s out there called FlexUnit, one is a SourceForge project and one is official from Adobe. The SF project is ancient and unmaintained, I will be referring to the official API.

FlexUnit also has some competition from the AsUnit project, but seems to be slightly less well suiteded for our needs when testing AS3 projects. It does, however, seem to offer fairly good support for AS2 projects. The two frameworks are generally very similar and switching between them should be fairly painless if necessary as they both evolved from and are modeled after JUnit, the industry standard for unit testing in Java.

FlexUnit is available for download from Adobe Labs. You want the zip file.

The official API documentation for FlexUnit is at http://weblogs.macromedia.com/as_libraries/docs/flexunit.

Warning: If your default run target in Flex doesn’t use the right flash player version/options, it is entirely possible that your failures might not be documented. Run the swf again in the standalone debugging player and you should get the information you missed. I’m not entirely certain why this is happening but I don’t much care at the moment.

Using FlexUnit

To make use of FlexUnit in a Flex 2 project only two bits of prep work need to be done:

  • Add the flexunit.swc file (found in the zip on Adobe’s site) to your project’s library path.
  • Create a test runner application in the project. This is Flex, so remember that applications have to be in the root of the project tree.

An example simple test runner (adapted very slightly from Darron Schall’s howto post):

Test Cases

The way the framework functions is by running a series of test cases. Each test case is an instance of the TestCase class which may or may not do any number of things. Test cases may also be organized into TestSuites which are little more than a list of test cases which will be run in order if desired. TestSuite.add() may accept either individual TestCase instances or TestSuites.

The constructor for a test case accepts one argument, the name of the method to be called when the test is run. Thus it is possible and advisable to create a single class for each group of related tests and instantiate multiple copies, each instructed to run a different test.

When a test runs it counts the results of all assertion methods called. These methods are:

  • AssertEquals()
  • AssertFalse()
  • AssertNotNull()
  • AssertNotUndefined()
  • AssertNull()
  • AssertStrictlyEquals()
  • AssertTrue()
  • AssertUndefined()
  • fail()

Each of the assertX() methods takes two parameters, a string describing the error to describe if the test fails and a value to be tested.

Fail may be used to throw error messages if you want to perform more complex tests than the prefab asserts provide.

A sample test case class:
[as3]
package test {
import flexunit.framework.TestCase;
import flexunit.framework.TestSuite;

public class SomeTest extends TestCase {

// declaring the redundant constructor saves you from having to cast when you construct
public function SomeTest( methodName:String ) {
super( methodName );
}// end: constructor

// this method returns a suite containing all of the tests provided by this class in
// the order they should be run
public static function suite() : TestSuite {
var ts:TestSuite = new TestSuite();

ts.addTest( new SomeTest( "testA" ) );
ts.addTest( new SomeTest( "testB" ) );
return ts;
}// end: suite

public function testA() : void {
AssertTrue( "True does not equal true?!", true );

var tmp:Object;
AssertNull( "Tmp should be null here.", tmp );
tmp = {};
AssertNotNull( "Tmp shouldn’t be null any more.", tmp );
}// end: testA

public function testB() : void {
fail( "This test always fails" );
}// end: testB

}// end: class
}// end: package
[/as3]

Asynchronous Tests

FlexUnit offers good support for asynchronous event-driven test cases. AsUnit apparently has also recently (ie, as of early-mid October, 2006) added this support for AS3 projects.

There are a number of asynchronous methods that tests can call but the actual 1st-party documentation on how to use them is a bit thin. In stead, Adobe refers us to hunt down and comprehend the test cases written for the Mappr API. I’ve attempted a bit of this comprehension. The only one of their test suites to use asynchronous calls is the MapprServiceTest class.

Even in this case, they’re only using one aspect of the functionality. That is the TestCase.addAsync() call. This function looks like it might be enough for what we need, it adds a checkpoint to the queue (and pauses it?) and then returns a proxy function that looks like it should clear the checkpoint and then execute the next function in your list.

The framework looks like it has more robust options than this for writing asynchronous tests, but I believe this is all we need for now.

A sample class that tests loading data from an external source might look something like this:
[as3]
package test
{
import flexunit.framework.TestCase;
import flexunit.framework.TestSuite;
import flash.net.URLLoader;
import flash.net.URLRequest;

public class RemoteXMLTest extends TestCase {
private static var TIMEOUT:int= 10000; // 10 seconds
private var loader:URLLoader;

public function RemoteXMLTest( methodName:String ) {
super( methodName );
}

public static function suite() : TestSuite {
var ts:TestSuite = new TestSuite();
ts.addTest( new RemoteXMLTest("doIt") );
return ts;
}

public function doIt() : void {
var request:URLRequest = new URLRequest("http://somewhere.com");
assertNotNull( "request is null", request );

loader = new URLLoader();
assertNotNull( "loader is null", loader );

loader.addEventListener( "complete", addAsync( onLoaded, TIMEOUT ) );
loader.load( request );
}

public function onLoaded( result:Object ) : void {
// don’t actually have to do anything here, but eh, why not?
assertNotUndefined( "we got no result?", result );
}
}
}
[/as3]