Home >
Introduction
AsUnit is an open source framework for unit testing in Flash. AsUnit provides a low level automated testing system that is your first line of defense for catching bugs in your application. The concept of unit testing has been around for a long time as part of the traditional Waterfall model of software development. However, it has gained in popularity recently as one of the main tenets of Extreme Programming. One of the tenants of Extreme Programming is that you write unit tests first and then your code. You also refactor code often as you add features. Unit tests help find errors quickly as code is refactored and can be used as part of regression testing to make sure the new code has not affected existing functionality.
Unit testing is not the end all be all of testing. It is used to catch low level errors, but there are many classes of errors that are outside its ability to detect such as integration errors, system errors, and performance issues.
What is Unit testing?
To understand unit testing, you must first understand what a “unit” is. A unit is the smallest piece of code that is testable. This doesn’t mean each line of code, but a piece of code that performs a specific task. In Flash, this means a function, or more appropriately a method in ActionScript class. Unlike many other forms of software testing, unit tests are usually completed by the developer. The developer tests code at a low level to make sure each method is performing as expected. In theory, if each function is working properly at a low level then the higher levels of integration testing should have fewer errors. Unit testing is available in many languages and is typically referred to as Xunit where X is specific to the language. For instance unit testing in Java is called JUnit, the As in AsUnit stands for ActionScript.
Getting Started with AsUnit
As of this writing Flash CS3 is the latest version of Flash and that is what I’m going to cover in this article. If you are interested in using AsUnit with previous version of Flash Tim Beynart has written a good tutorial on using AsUnit with ActionScript 2. I’ve included a link to his article in the resources at the end of the article.
When you visit the AsUnit homepage you’ll see they have several ways of incorporating AsUnit into your project. You can just grab the framework off of SourceForge, use XUL UI, or use MXP. XUL UI helps you build entire classes along with test cases. MXP is an extension for Flash MX 2004 and Flash 8 that adds AsUnit support. The MXP for AsUnit doesn’t support Flash CS3 and this article is really about learning how to use AsUnit so we are going to use the framework.
Once you have downloaded the AsUnit framework and unzipped it, you will see several directories. There is an as2, as25, as3, and as3docs. The as2 and as25 directories are for previous versions of Flash. The as3docs directory contains the documentation for the as3 implementation of AsUnit in ASDoc format. The instructions are for the AsUnit API and won’t be that useful if you are just trying to learn the basics. That leaves us with as3 (for ActionScript 3), which contains the framework we want.
There are a couple approaches to getting AsUnit into your project. You can just copy the contents of the as3 directory into the directory for your project or you can add the as3 directory to your class path. For those unfamiliar with compiler terminology the class path is where the flash complier is going to look for ActionScript classes when compiling your fla and as files into a swf file. The current directory is added by default which is why you can copy the as3 files into your main project directory. To add the as3 directory to the class path in Flash you go to Edit -> Preferences -> ActionScript (option) -> ActionScript 3.0 Settings (button). Select the plus icon to add a new path and then select the target icon to browse to the location on your file system where the as3 directory is located. Click ok to finish.
Once you add the as3 directory to your class path you can use AsUnit for all your projects without copying the directory over. Regardless of which option you choose the remaining instructions are the same.
Test Subject
Now that we have ASUnit set up, we need something to test. Below is a simple bank account class that will be used as an example. The class allows you to make deposits, withdrawals, and keeps track of your balance.
BankAccount.as
Create Unit Tests
Next we create our unit tests. Our unit tests will be contained in a new class that extends the base TestCase class. I’m going to call it BankAccountTest. This class will contain methods with our unit tests in them. You typically create a new method for each unit you are testing. In this case I’ll be testing the deposit and withdraw methods of the BankAccount, so my test class method names will be testDeposit and testWithdraw. It is also standard to create an instantiation test just to make sure the constructor is working properly, we will call this testInstantiated.
There are also three additional utility functions that will be created: a constructor, setUp, and tearDown. The constructor will accept a string that will be name of the method to be tested. This will be used later to set up the unit tests. The setUp method overrides a method in the base TestCase class and is automatically called before every test. It is used to set up anything needed for the test cases, for this example we’ll be creating an instance of the BankAccount to use in our tests. The tearDown method is similar. It overrides the method in the base TestCase class and is automatically called after a test to do any clean up that is necessary.
We know we are going to have two test methods, but how do you actually create a unit test? A unit test is made up of logical assertions. If an assertion is true, the unit test passes. If an assertion is false then the unit test fails.
There are several assertion methods available for our unit tests such as: assertTrue, assertFalse, assertNull, assertEquals, and several others. The methods are all similar and take an optional text message and Boolean test of some type. Although text messages are optional, it’s a good idea to use them to help you quickly locate which test failed. If the result of the Boolean test is true, the assertion succeeds, and if not it fails. For example, if I create a BankAccount and deposit $50, then my balance should be $50. The unit test for this case is:
This test is pretty straight forward. If my balance isn’t 50 after I deposit 50, then either I have a problem with deposit method, or my getBalance method. For this sample I only have a few assertions, but you typically want to cover as many cases as possible. This is what my final test class looks like with a few more tests added:
BankAccountTest.as
Creating the Test Suite
Now that we have created our unit tests, we need to tell the framework to run them. Unlike the previous version, AsUnit version 3 comes with a built in TestRunner that will run our tests, but we still need to define the TestSuite. The built in TestRunner named AsUnitTestRunner.as is set up to call a TestSuite named AllTests, so we will create an AllTests.as class to add our tests. This class will extend the base TestSuite class in the AsUnit framework and add our test cases. Test cases are added using the addTest method as show in the AllTest.as example below:
AllTests.as
Running the Tests
The last step before we can run the test cases is to create a fla movie to run our tests. This movie will not contain any code, but instead will use the test runner as its document class. The document class is a new feature of CS3 and allows you to specify a class to be instantiated when the movie starts. If you look at the AsUnitTestRunner.as in the AsUnit framework code you will see that it runs the unit tests when it instantiates. No additional code is needed. In the flash movie access the movie properties and enter “AsUnitTestRunner” into the document class field as shown below.
Now you can run the movie by selecting Control->Test Movie. A window pops up showing the results of the tests as shown in the following image:
Successful Test
If a test fails, a stack dump will occur and you will see the error message in the window. I’m going to deliberately generate an error by making one of my assertions invalid. In the testDeposit test I’m going to check for the wrong the balance using the following code:
Running the movie now produces the following result:
Unsuccessful Test
Here you can see the test method that failed and the error message that was specified in the code: AssertionFailedError: Balance on a new account after 50 deposit is 50. Since no line number is included in the stack trace, you should make sure you use good descriptions in your assertion text. Once an assertion in a test method fails, the method is considered to have failed and no further tests are run in that method. However, any other test methods still run.
Conclusion
AsUnit provides an automated way to test code at a low level. It provides a framework to automate testing that would otherwise be very time consuming and helps identify bugs much earlier in the development process. It should not be the only type of testing you perform, but it is a valuable addition to the testing process. The example in this article introduces the basics of unit testing with ActionScript, but it opens the door to many interesting possibilities such as test driven development and extreme programming.
Additional Resources
AsUnit Home Page
http://www.asunit.org/
Extreme Programming
http://www.extremeprogramming.org/
Tutorial on Using AsUnit with ActionScript 2 by Tim Beynart
http://www.flashcodersny.org/wordpress/?p=103
AsUnit is an open source framework for unit testing in Flash. AsUnit provides a low level automated testing system that is your first line of defense for catching bugs in your application. The concept of unit testing has been around for a long time as part of the traditional Waterfall model of software development. However, it has gained in popularity recently as one of the main tenets of Extreme Programming. One of the tenants of Extreme Programming is that you write unit tests first and then your code. You also refactor code often as you add features. Unit tests help find errors quickly as code is refactored and can be used as part of regression testing to make sure the new code has not affected existing functionality.
Unit testing is not the end all be all of testing. It is used to catch low level errors, but there are many classes of errors that are outside its ability to detect such as integration errors, system errors, and performance issues.
What is Unit testing?
To understand unit testing, you must first understand what a “unit” is. A unit is the smallest piece of code that is testable. This doesn’t mean each line of code, but a piece of code that performs a specific task. In Flash, this means a function, or more appropriately a method in ActionScript class. Unlike many other forms of software testing, unit tests are usually completed by the developer. The developer tests code at a low level to make sure each method is performing as expected. In theory, if each function is working properly at a low level then the higher levels of integration testing should have fewer errors. Unit testing is available in many languages and is typically referred to as Xunit where X is specific to the language. For instance unit testing in Java is called JUnit, the As in AsUnit stands for ActionScript.
Getting Started with AsUnit
As of this writing Flash CS3 is the latest version of Flash and that is what I’m going to cover in this article. If you are interested in using AsUnit with previous version of Flash Tim Beynart has written a good tutorial on using AsUnit with ActionScript 2. I’ve included a link to his article in the resources at the end of the article.
When you visit the AsUnit homepage you’ll see they have several ways of incorporating AsUnit into your project. You can just grab the framework off of SourceForge, use XUL UI, or use MXP. XUL UI helps you build entire classes along with test cases. MXP is an extension for Flash MX 2004 and Flash 8 that adds AsUnit support. The MXP for AsUnit doesn’t support Flash CS3 and this article is really about learning how to use AsUnit so we are going to use the framework.
Once you have downloaded the AsUnit framework and unzipped it, you will see several directories. There is an as2, as25, as3, and as3docs. The as2 and as25 directories are for previous versions of Flash. The as3docs directory contains the documentation for the as3 implementation of AsUnit in ASDoc format. The instructions are for the AsUnit API and won’t be that useful if you are just trying to learn the basics. That leaves us with as3 (for ActionScript 3), which contains the framework we want.
There are a couple approaches to getting AsUnit into your project. You can just copy the contents of the as3 directory into the directory for your project or you can add the as3 directory to your class path. For those unfamiliar with compiler terminology the class path is where the flash complier is going to look for ActionScript classes when compiling your fla and as files into a swf file. The current directory is added by default which is why you can copy the as3 files into your main project directory. To add the as3 directory to the class path in Flash you go to Edit -> Preferences -> ActionScript (option) -> ActionScript 3.0 Settings (button). Select the plus icon to add a new path and then select the target icon to browse to the location on your file system where the as3 directory is located. Click ok to finish.
Once you add the as3 directory to your class path you can use AsUnit for all your projects without copying the directory over. Regardless of which option you choose the remaining instructions are the same.
Test Subject
Now that we have ASUnit set up, we need something to test. Below is a simple bank account class that will be used as an example. The class allows you to make deposits, withdrawals, and keeps track of your balance.
BankAccount.as
package
{
public class BankAccount
{
private var balance:Number=0;
public function deposit(amount:Number):void{
balance=balance+amount;
}
public function withdraw(amount:Number):void{
balance=balance-amount;
}
public function getBalance():Number{
return balance;
}
}
}
Create Unit Tests
Next we create our unit tests. Our unit tests will be contained in a new class that extends the base TestCase class. I’m going to call it BankAccountTest. This class will contain methods with our unit tests in them. You typically create a new method for each unit you are testing. In this case I’ll be testing the deposit and withdraw methods of the BankAccount, so my test class method names will be testDeposit and testWithdraw. It is also standard to create an instantiation test just to make sure the constructor is working properly, we will call this testInstantiated.
There are also three additional utility functions that will be created: a constructor, setUp, and tearDown. The constructor will accept a string that will be name of the method to be tested. This will be used later to set up the unit tests. The setUp method overrides a method in the base TestCase class and is automatically called before every test. It is used to set up anything needed for the test cases, for this example we’ll be creating an instance of the BankAccount to use in our tests. The tearDown method is similar. It overrides the method in the base TestCase class and is automatically called after a test to do any clean up that is necessary.
We know we are going to have two test methods, but how do you actually create a unit test? A unit test is made up of logical assertions. If an assertion is true, the unit test passes. If an assertion is false then the unit test fails.
There are several assertion methods available for our unit tests such as: assertTrue, assertFalse, assertNull, assertEquals, and several others. The methods are all similar and take an optional text message and Boolean test of some type. Although text messages are optional, it’s a good idea to use them to help you quickly locate which test failed. If the result of the Boolean test is true, the assertion succeeds, and if not it fails. For example, if I create a BankAccount and deposit $50, then my balance should be $50. The unit test for this case is:
/* Note: "instance" is an instance of BankAccount created by the setUp method */
instance.deposit(50);
assertTrue("Balance on a new account after 50 deposit is 50", instance.getBalance() == 50);
This test is pretty straight forward. If my balance isn’t 50 after I deposit 50, then either I have a problem with deposit method, or my getBalance method. For this sample I only have a few assertions, but you typically want to cover as many cases as possible. This is what my final test class looks like with a few more tests added:
BankAccountTest.as
package {
import asunit.framework.TestCase;
public class BankAccountTest extends TestCase {
private var instance:BankAccount;
/**
* Constructor
*/
public function BankAccountTest(testMethod:String) {
super(testMethod);
}
/**
* Set up instance of BankAccount to test with
*/
protected override function setUp():void {
instance = new BankAccount();
}
/**
* Delete instance used for testing
*/
protected override function tearDown():void {
instance=null;
}
/**
* Test BankAccount instantiation
*/
public function testInstantiated():void {
assertTrue("Example instantiated", instance is BankAccount);
}
/**
* Test Deposit
*/
public function testDeposit():void {
instance.deposit(50);
assertTrue("Balance on a new account after 50 deposit is 50", instance.getBalance() == 50);
instance.deposit(25);
assertEquals("Balance after 50 deposit and another 25 deposit is 75", 75,instance.getBalance());
}
/**
* Test withdraw
*/
public function testWithdraw():void {
instance.deposit(100);
instance.withdraw(50);
assertTrue("Balance on a new account after 100 deposit and a 50 withdraw is 50", instance.getBalance() == 50);
}
}
}
Now that we have created our unit tests, we need to tell the framework to run them. Unlike the previous version, AsUnit version 3 comes with a built in TestRunner that will run our tests, but we still need to define the TestSuite. The built in TestRunner named AsUnitTestRunner.as is set up to call a TestSuite named AllTests, so we will create an AllTests.as class to add our tests. This class will extend the base TestSuite class in the AsUnit framework and add our test cases. Test cases are added using the addTest method as show in the AllTest.as example below:
AllTests.as
package {
import asunit.framework.TestSuite;
public class AllTests extends TestSuite {
public function AllTests() {
super();
addTest(new BankAccountTest("testInstantiated"));
addTest(new BankAccountTest("testDeposit"));
addTest(new BankAccountTest("testWithdraw"));
}
}
}
Running the Tests
The last step before we can run the test cases is to create a fla movie to run our tests. This movie will not contain any code, but instead will use the test runner as its document class. The document class is a new feature of CS3 and allows you to specify a class to be instantiated when the movie starts. If you look at the AsUnitTestRunner.as in the AsUnit framework code you will see that it runs the unit tests when it instantiates. No additional code is needed. In the flash movie access the movie properties and enter “AsUnitTestRunner” into the document class field as shown below.
Now you can run the movie by selecting Control->Test Movie. A window pops up showing the results of the tests as shown in the following image:
Successful Test
If a test fails, a stack dump will occur and you will see the error message in the window. I’m going to deliberately generate an error by making one of my assertions invalid. In the testDeposit test I’m going to check for the wrong the balance using the following code:
assertTrue("Balance on a new account after 50 deposit is 50", bankAccount.getBalance() == 40);
Running the movie now produces the following result:
Unsuccessful Test
Here you can see the test method that failed and the error message that was specified in the code: AssertionFailedError: Balance on a new account after 50 deposit is 50. Since no line number is included in the stack trace, you should make sure you use good descriptions in your assertion text. Once an assertion in a test method fails, the method is considered to have failed and no further tests are run in that method. However, any other test methods still run.
Conclusion
AsUnit provides an automated way to test code at a low level. It provides a framework to automate testing that would otherwise be very time consuming and helps identify bugs much earlier in the development process. It should not be the only type of testing you perform, but it is a valuable addition to the testing process. The example in this article introduces the basics of unit testing with ActionScript, but it opens the door to many interesting possibilities such as test driven development and extreme programming.
Additional Resources
AsUnit Home Page
http://www.asunit.org/
Extreme Programming
http://www.extremeprogramming.org/
Tutorial on Using AsUnit with ActionScript 2 by Tim Beynart
http://www.flashcodersny.org/wordpress/?p=103








Facebook Application Development
Hey Kelly,
Thanks so much for putting this tutorial together!
I just wanted to comment on one feature in our TestSuite class.
If you instantiate your TestCases without the optional method argument, and then send them to the addTest method, all of your test methods will automatically be executed.
So you can save yourself some maintenance headaches by changing your AllTests constructor to something more like:
addTest(new BankAccountTest());
Thanks again for the post!
Gorilla Logic has just open sourced its FlexMonkey GUI testing framework for Flex. FlexMonkey provides record/playback of Flex user interactions and generates actionscript-based test scripts that can be run within the asunit framework.
You can check it out at http://flexmonkey.googlecode.com
Excellent article. Found a typo, though: I think you meant "One of the tenets of Extreme Programming."
I can't find the AsUnitTestRunner.as file in any of the folders I've dwnloaded for the latest as3 version of AsUnit. Has it been removed? Does anyone know what changes need to be made to get this tutorial to work with the latest version?
Thanks for this nice tutorial. It helped me a lot and saved my time.
There is no AsUnitTestRunner.as file in the package
I managed to launch the test using .../as3/src as class path in Flash Preferences, and the class AsUnitRunner from .../as3/test directory as document class.
Thank you for the nice tutorial