Why?
Unit testing should be done for several purposes:
- If you write your tests before the actual class code, you design the public interface of the class to be conveniently callable
- The class you create is by definition testable
- Unit tests shortens the code-debug-fix-cycle because you won’t have to load your application and click around to test stuff
- When you refactor the code you will know directly if something breaks, but only if you run all the tests in the suite.
How?
Flex Unit is an open source project lead by Adobe. It will be integrated with Flash Builder 4, but as it is an ActionScript3 project it can be used with Flex Builder. It has a graphical test runner based on Flex. You can create either a separate application for the test runner or you could integrate it into your application. The FlexUnit project consists of a couple of swc-files which you put in your test project.
You write tests in ActionScript for all your code by extending the class TestCase. Below is an example of a test for one of the methods in the GAV Flash class ArrayHelper:
package gavtests.utils
{
import flexunit.framework.TestCase;
import gav.utils.ArrayHelper;
public class ArrayHelperTest extends TestCase
{
public function testCreateArray(): void
{
function filler(i:uint, arr:Array): * {
return i*i;
}
assertObjectEquals([0,1,4,9,16,25],
ArrayHelper.createArray(6, filler));
}
}
}
The TestCase class provides several methods named assertXXX which are used to do the actual testing. In this case two objects are compared using the assertObjectEquals, one is the return value from createArray and the other is what we would expect it to be. Whenever an assertion fails, the test is stopped.The ArrayHelperTest class is added to a test suite, which is added to the test runner. Below is a simple testing application which features a graphical test runner and runs the test class above:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="onCreationComplete()"
layout="absolute"
xmlns:flexui="flexunit.flexui.*">
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import flexunit.framework.TestSuite;
import gavtests.utils.ArrayHelperTest;
private function onCreationComplete(): void
{
testRunner.test = createTestSuite();
testRunner.startTest();
}
private function createTestSuite(): TestSuite
{
var testSuite:TestSuite = new TestSuite();
// Add your test cases here:
testSuite.addTestSuite(ArrayHelperTest);
return testSuite;
}
]]>
</mx:Script>
<flexui:TestRunnerBase id="testRunner" width="100%" height="100%"/>
</mx:Application>
What should be tested?
Test as much as possible. But here are some examples:
- All public functions - this should actually exercise all private functions as well. What you should aim for is to cover every single path through your code.
- Invalid arguments – define how your square root function should behave if you hand it a negative number and assert that it behaves that way
- Boundary conditions – how should your array manipulating algorithm behave when you pass it an empty array?
- Properties – You might find it unnecessary to test that a property actually has the value you assign to it, but if you at some point mess up a property setter it might take a long while for you to debug that. If you have a test case for it you will find out directly. What if you assign null? I’ve seen code that keeps the old value in this case, which is probably incorrect.
- That event listeners are removed from the old property value if you assign a new one
- Bugs. Whenever you find a bug reproducible by code, add a test case for it and fix it. That way the bug won’t reappear.
GAV Flash tests
I’ve created a new project on SVN called GavFlashTests where I will try to add tests whenever I write new code for GAV Flash. We probably will never cover all of the current code with unit tests, but then again we probably won't use the current code forever.
No comments:
Post a Comment