flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r902467 [4/10] - in /websites/staging/flex/trunk: cgi-bin/ content/ content/flexunit/ content/flexunit/tutorial/ content/flexunit/tutorial/css/ content/flexunit/tutorial/flexunit/ content/flexunit/tutorial/images/ content/flexunit/tutorial/...
Date Thu, 20 Mar 2014 03:56:22 GMT
Added: websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-11.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-11.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-11.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,521 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+	
+	<title>Parameterized Tests</title>
+
+	<script language="JavaScript" src="../scripts/jquery-1.5.min.js" ></script>
+	<link href="../css/style.css" rel="stylesheet" type="text/css" />
+
+</head>
+<body>
+	
+	<div id="container">
+		
+		<div id="contentborder">
+			<div id="unitdownload">
+				
+					<a href="../code/unit11.zip"><img style="vertical-align:middle;border-style:none;" src="../images/DownloadIcon.png" alt="Download" /></a>
+					<span style="font-size:24px;font-weight:bold;color:#666666;margin-left:10px;">Project Files</span>
+				
+			</div>
+			<div id="content">
+
+<h1>Unit 11 - Parameterized Tests</h1>
+
+<p>Much like theories, parameterized tests take a number of possible values and apply them to methods in the test case. Unlike theories, however, parameterized tests pass or fail individually, meaning that one specific data point can fail while the others pass. While Theories are best used for reversible or mathematical concepts, parameterized testing allows for passing a series of arguments and expected results to every test in a case, some tests in a case, or each to a unique test in the case.</p>
+ 
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Create TestNG style parameterized tests</li>
+	<li>Create JUnit style parameterized tests</li>
+	<li>Use complex objects in parameterized tests</li>
+	<li>Use external data to load simple and complex objects for parameterized testing</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Use case differences from theories</li>
+	<li>Declaring simple data for parameterization</li>
+	<li>Types of Parameterized Tests</li>
+	<li>Working with complex objects</li>
+	<li>Using external data</li>
+</ul>
+
+<h2>Use case differences from theories</h2>
+
+<p>Theories are best used for reversible operations that must succeed in every single situation. For example, a great use of a Theory might be testing a date conversion utility. Perhaps you have a class that converts dates from Gregorian calendar dates to dates on the Buddhist calendar.</p>
+<p>Using a theory, you would supply hundreds or thousands of Gregorian dates as data points. For each data point, you might convert the date to the equivalent Buddhist date. You would then convert each Buddhist date back to the Gregorian date and ensure it matched the original.</p>
+<p>With the following pseudocode:</p>
+
+<code><pre>[DataPoints]
+[ArrayElementType("Date")]
+public static var dates:Array = [ 1/1/2009, 
+			2/2/2010, 
+			3/3/2011, 
+			1/8/1970,
+			11/12/2090 ];</pre></code>
+
+<p>Tested under this situation</p> 
+
+<code><pre>[Theory]
+public function shouldConvertSuccessfully( date:Date ):void {
+	var convert:Converter = new Converter();
+	var bDate:BDate = converter.convertToBuddhistDate( date );
+	var gDate:Date = converter.convertToGregorianDate( bDate );
+	assertEquals( date, gDate );
+}</pre></code>
+
+<p>This type of reversibility is the hallmark of a good theory case.</p>
+<p>Also, remember that Theories are about using combinations of data. Given the following pseudocode:</p>
+
+<code><pre>[DataPoints]
+[ArrayElementType("String")]
+public static var dates:Array = [ "Trevor", "Joe", "Rob", "Steve" ];
+
+[Theory]
+public function traceNames( name1:String, name2:String ):void {
+  trace( name1 + " - " + name2 );
+}</pre></code>
+
+<p>The expected output is:</p>
+
+<code><pre>Trevor - Trevor
+Trevor - Joe
+Trevor - Rob
+Trevor - Steve
+Joe - Trevor
+Joe - Joe
+Joe - Rob
+Joe - Steve
+Rob - Trevor
+Rob - Joe
+Rob - Rob
+Rob - Steve
+Steve - Trevor
+Steve - Joe
+Steve - Rob
+Steve - Steve</pre></code>
+
+<p>This use of data point combinations starkly contrasts the use case for Parameterized testing that you will learn in the remainder of the lesson.</p>
+
+<h2>Declaring simple data for parameterization</h2>
+
+<p>Parameterized test cases, like Theories, have methods that accept parameters. However, that is where the comparison ends. Parameterized testing gives us a way to create tests that will use a multitude of known parameters and results.  The intention of the Parameterized test is to eliminate the need to copy and paste the same test multiple times, simply changing the input values.</p>
+<p>Parameterized tests require the Parameterized runner included with FlexUnit 4.1 and later.  To use the parameterized test runner, add the RunWith metadata to the class definition.</p>
+
+<code><pre>[RunWith("org.flexunit.runners.Parameterized")]</pre></code>
+
+<p>Parameter data is provided as an array. Inside of the array, there is an array for each argument set to be passed for each test case.  For example:</p>
+
+<code><pre>public static var names:Array = [ 
+	[ "Stevens", "Mary", "Mary Stevens" ], 
+	[ "Doe", "John", "John Doe" ] ];
+
+[Test]
+public function nameCombinerTest( lastName:String, firstName:String, 
+					expectedResult:String ):void {
+	assertEquals( expectedResult, ( firstName + " " + lastName ) );
+}</pre></code>
+
+<p>There are actually two types of Parameterized tests supported by FlexUnit 4.x, which you will learn to use next.</p>
+
+<h2>Types of parameterized test</h2>
+
+<p>To use any form of parameterized tests requires a custom runner.  FlexUnit 4.1 includes the ParameterizedRunner which can run TestNG and JUnit style parameterized tests.</p>
+
+<h3>TestNG</h3>
+
+<ul>
+	<li>Allows specification of different data for each test method</li>
+	<li>Uses the dataProvider annotation to specify the data source</li>
+	<li>Tests have expected parameters specified as part of the test</li>
+	<li>Test methods will follow the order of the data provider array</li>
+	<li>Each test can take only one data provider</li>
+</ul>
+<p>Example</p>
+
+<code><pre>public static var data:Array = [ [ 0, 0 ], [ 1, 2 ], [ 2, 4 ] ];
+
+[Test( dataProvider="data")]
+public function doubleTest( value1:int, value2:int ):void {
+	assertEquals( value1, value2 * 2 );
+}</pre></code>
+
+<h3>JUnit</h3>
+
+<ul>
+	<li>Best for data that is needed by multiple test methods</li>
+	<li>All tests will use the same data</li>
+	<li>Data must be decorated with [Parameters] metadata</li>
+	<li>Values are assigned in the constructor</li>
+	<li>Instance variables are used to store each value</li>
+	<li>Test methods take no arguments</li>
+</ul>
+<p>Example</p>
+
+<code><pre>[Parameters]
+public static var data:Array = [ [ 0, 0 ], [ 1, 2 ], [ 2, 4 ] ];
+
+[Test]
+public function doubleTest():void {
+	assertEquals( value1, value2 * 2 );
+}
+
+private var _value1:int;
+private var _value2:int;
+
+public function JUnitStyleTest( value1:int, value2:int ) {
+	_value1 = value1;
+	_value2 = value2;
+}</pre></code>
+
+<h2>Working with complex objects</h2>
+
+<p>Any type of data can be used in parameterized testing. In fact, some of the most effective testing can occur when you begin using entire objects as the parameters to methods. The following examples are all valid and intended to make you consider how polymorphism and complex types can enhance your testing capabilities.</p>
+
+<code><pre>public static var data:Array = [ [ new DataGrid(), 50, 70 ],
+				[ new Label(), 40, 30 ],
+				[ new Button(), 80, 50 ] ];
+
+[Test(dataProvider="data")]
+public function positionTest( component:UIComponent, x:Number, y:Number ):void {
+	position( component );
+	assertEquals( x, component.x );
+	assertEquals( y, component.y );
+}
+
+public static var data:Array = [ [ new DollarFormatter(), 50, "$50" ],
+			[ new EuroFormatter(), 50, "&euro;50" ],
+			[ new PoundFormatter(), 50, "&pound;50" ] ];
+
+[Test(dataProvider="data")]
+public function positionTest( formatter:IFormatter, value:Number, result:String ):void {
+	assertEquals( result, formatter.format( value ) );
+}</pre></code>
+
+<h2>Walkthrough 1: Creating a TestNG Style Parameterized Test</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create a new class to run tests with parameterized data.</li>
+	<li>Apply the TestNG style of parameterized testing.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnit4Training_wt1.fxp project from the Unit 11/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+	</li>
+	<li>
+		<p>Create a new ActionScript class named GetPointsTest.as in the math.testcases package within the tests folder.</p>
+		 
+		<h3><br />Parameterized Testing Setup</h3>
+		
+	</li>
+	<li>
+		<p>Mark the GetPointsTest class definition with <code>[RunWith("org.flexunit.runners.Parameterized")]</code> metadata.</p>
+
+<code><pre>[RunWith("org.flexunit.runners.Parameterized")]
+public class GetPointsTest {
+...
+}</pre></code>
+
+	</li>
+	<li>
+		<p>Add a private static constant named <code>TOLERANCE</code> of data type <code>Number</code> to the class. Set <code>TOLERANCE</code> to <code>.0001</code>.</p>
+
+		<code><pre>private static const TOLERANCE:Number = .0001;</pre></code>
+		
+	</li>
+	<li>
+		<p>Declare a public static array named data within the <code>GetPointsTest</code> class. The array should contain a sub array with point values as shown.</p>
+
+<code><pre>public static var data:Array = [
+		[ new Circle( new Point( 0, 0 ), 5 ), new Point( 5, 0 ), 0 ],
+		[ new Circle( new Point( 0, 0 ), 5 ), new Point( -5, 0 ), Math.PI ] 
+];</pre></code>
+
+<p>If you did not use code-completion, add the import for net.digitalprimates.math.Circle and flash.geom.Point at this time.</p>
+<p>The data array contains two arrays. Each is passed as a set of parameters, and each represents one run cycle for the tests that take the data. Soon, you will write a method which takes 3 parameters, a circle, a point and a number of radians.  That test will run twice, one run using the first array and another using the second.</p>
+	</li>
+	<li>
+		<p>Add a public method named <code>shouldGetPointsOnCircle()</code> to the class. Mark the method with the <code>[Test(dataProvider="data")]</code> metadata.</p>
+
+<code><pre>[Test(dataProvider="data")]
+public function shouldGetPointsOnCircle():void {
+}</pre></code>
+
+		<p>Add a <code>circle</code> parameter of type <code>Circle</code>, a point parameter of type <code>Point</code>, and a <code>radians</code> parameter of type <code>Number</code> to the <code>shouldGetPointsOnCircle()</code> method.</p>
+		<p>The <code>[Test(dataProvider="data")]</code> metadata over the test method will ensure that the data array's values get passed in as the test method's arguments. This is known as TestNG style parameterized testing, because the data is passed into specific test methods via the metadata. TestNG is a testing framework for Java, it pioneered this annotations-based approach.</p>
+
+<code><pre>[Test(dataProvider="data")]
+public function shouldGetPointsOnCircle( circle:Circle, point:Point, radians:Number ):void {
+}</pre></code>
+
+	</li>
+	<li>
+		<p>Add a call to the <code>assertThat()</code> method. Pass <code>circle.getPointOnCircle( radians )</code> and <code>new CloseToPointMatcher( point, TOLERANCE )</code> as its arguments.</p>
+
+<code><pre>[Test(dataProvider="data")]
+public function shouldGetPointsOnCircle( circle:Circle, point:Point, radians:Number ):void {
+	assertThat( circle.getPointOnCircle( radians ), new CloseToPointMatcher( point, TOLERANCE ) );
+}</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.flexunit.assertThat and matcher.CloseToPointMatcher at this time.</p>
+		<p>The <code>shouldGetPointsOnCircle()</code> method uses the <code>assertThat()</code> statement with the <code>CloseToPointMatcher</code> to create the same kind of test coverage presented in BasicCircleTest class through the <code>shouldGetTopPointOnCircle()</code> and <code>shouldGetBottomPointOnCircle()</code> methods.</p>
+	</li>
+	<li>
+		<p>Save the GetPointsTest.as file.</p>
+
+		<h3><br />Add the new case to the CircleSuite</h3>
+		
+	</li>
+	<li>
+		<p>Open the CircleSuite.as file in the math.testcases package.</p>
+	</li>
+	<li>
+		<p>Add a public variable named <code>test6</code> of type <code>GetPointsTest</code>.</p>
+
+<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class CircleSuite{
+	public var test1:BasicCircleTest;
+	public var test2:CircleConstructorTest;
+	public var test3:CircleTheory;
+	public var test4:CircleMockTest;
+	public var test5:DistanceTest;
+	public var test6:GetPointsTest;
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Save CircleSuite.as.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit11/image1.png' />
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Walkthrough 2: Creating a JUnit Style Parameterized Test</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Add another parameterized test to the GetPointsTest class.</li>
+	<li>Apply the JUnit style of parameterized testing.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the GetPointsTest.as file located in the math.testcases package within the tests folder.</p>
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training_wt2.fxp project from the Unit11/ start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Add Instance variables</h3>
+		
+	</li>
+	<li>
+		<p>Add three private variables to the <code>GetPointsTest</code> class. One named <code>circle</code> of type <code>Circle</code>, another named <code>point</code> of type <code>Point</code>, and another named <code>radians</code> of type <code>Number</code>.</p>
+
+<code><pre>private var circle:Circle;
+private var point:Point;
+private var radians:Number;</pre></code>
+		
+	</li>
+	<li>
+		<p>Remove the <code>(dataProvider="data")</code> portion of the metadata from the <code>shouldGetPointsOnCircle()</code> test method. Also remove the parameters, as they will be replaced by the instance variables just created.</p> 
+
+<code><pre>[Test(dataProvider="data")]
+public function shouldGetPointsOnCircle( circle:Circle, point:Point, radians:Number ):void {
+...
+}</pre></code>
+
+		<p>Becomes</p>
+		
+<code><pre>[Test]
+public function shouldGetPointsOnCircle():void {
+...
+}</pre></code>
+
+		<h3><br />Add a method to test point distance</h3>
+		
+	</li>
+	<li>
+		<p>Add a public function named <code>shouldReturnDistanceEqualToRadius()</code> to the class.</p>
+
+<code><pre>[Test]
+public function shouldReturnDistanceEqualToRadius():void {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Within the new method, declare a variable named <code>distance</code> of data type <code>Number</code>. Set it equal to <code>Point.distance( circle.getPointOnCircle( radians ), circle.origin )</code>.</p>
+
+<code><pre>[Test]
+public function shouldReturnDistanceEqualToRadius():void {
+	var distance:Number = Point.distance( circle.getPointOnCircle( radians ), circle.origin );
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>assertThat()</code> method. Pass in <code>distance</code> and <code>equalTo( circle.radius )</code> as its arguments.</p>
+
+<code><pre>[Test]
+public function shouldReturnDistanceEqualToRadius():void {
+	var distance:Number = Point.distance( circle.getPointOnCircle( radians ), circle.origin );
+
+	assertThat( distance, equalTo( circle.radius ) );
+}</pre></code>
+
+		<p>If you did not use code-completion, add the import for org.hamcrest.object.equalTo at this time.</p>
+	</li>
+	<li>
+		<p>Now you will need to create a class constructor function that assigns the parameters to the variables declared above. It will take in a circle , point, and radians parameters and assign it to the instance variable for each.</p>
+
+<code><pre>public function GetPointsTest( circle:Circle, point:Point, radians:Number ) {
+	this.circle = circle;
+	this.point = point;
+	this.radians = radians;
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Mark the data array with <code>[Parameters]</code> metadata.</p>
+
+<code><pre>[Parameters]
+public static var data:Array = 
+[ [ new Circle( new Point( 0, 0 ), 5 ), new Point( 5, 0 ), 0 ],
+  [ new Circle( new Point( 0, 0 ), 5 ), new Point( -5, 0 ), Math.PI ] ];</pre></code>
+
+		<p>In the previous walkthrough, parameters were passed in using the <code>dataProvider="data"</code> metadata. In this case, parameters are marked with <code>[Parameters]</code> metadata, which passes them into the constructor before each test method is run. This is the parameterized testing approach used in JUnit, a popular Java Unit testing framework on which FlexUnit bases much of its syntax.</p>
+	</li>
+	<li>
+		<p>Save GetPointsTest.as.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit11/image2.png' /> 
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Using external data</h2>
+
+<p>External data for parameterized testing is similar to external data in theories. All external data sources use a dataloader, which must implement the IExternalDependancyLoader interface.</p>
+
+<code><pre>public static var dataRetriever:IExternalDependencyLoader = new ParamDataHelper( "myUrl" );</pre></code>
+
+<p>Depending on the style, the loading method for data is different:</p>
+
+<h3>TestNG</h3>
+
+<ul>
+	<li>Similar to theories</li>
+	<li>Set a DataPoints variable and annotate it with the loader property</li>
+</ul>
+
+<code><pre>[DataPoints(loader="dataRetriever")]
+public static var data:Array;</pre></code>
+
+<h3>JUnit</h3>
+
+<ul>
+	<li>Loader is added as an annotation to the [Parameters]</li>
+</ul>
+
+<code><pre>[Parameters(loader="dataRetriever")]
+public static var data:Array;</pre></code>
+
+<p>For more info on loading external data, see Unit 9: External Data.</p>
+
+<h2>Walkthrough 3: Loading External Parameters</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Load parameterized data from an external XML file.</li>
+	<li>Apply externally loaded parameters for greater test coverage.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the GetPointsTest.as file you created in the previous exercise.</p> 
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training_wt3.fxp project from the Unit 11/Start folder. Please refer to Unit 2: Walkthrough 1Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Add the external data loader</h3>
+		
+	</li>
+	<li>
+		<p>Add a public static variable named <code>getDataPointsLoader</code> of type <code>GetPointsDataHelper</code> to the <code>GetPointsTest</code> class. Instantiate the <code>GetPointsDataHelper</code> passing it a the argument <code>"xml/circlePoints.xml"</code></p>
+		
+		<code><pre>public static var getDataPointsLoader:GetPointsDataHelper =
+ new GetPointsDataHelper( "xml/circlePoints.xml" );</pre></code>
+
+		<p>If you did not use code-completion, add the import for helper.GetPointsDataHelper at this time.</p>
+		<p>The GetPointsDataHelper class implements IExternalDependencyLoader and IResponder interfaces. It is able to send and receive a data request in test case preparation. The loader itself references a data provider. In a parameterized test case, a static array uses these test parameters.</p>
+	</li>
+	<li>
+		<p>Remove the static values from the data Array and modify the <code>[Parameters]</code> metadata to include a loader <code>[Parameters(loader="getDataPointsLoader")]</code> metadata. It should read as follows:</p>
+
+<code><pre>[Parameters(loader="getDataPointsLoader")]
+public static var data:Array</pre></code>
+		
+	</li>
+	<li>
+		<p>Save the GetPointsTest.as file.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit11/image3.png' /> 
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+		
+		<p>The reason that the number of tests rose significantly in this Walkthrough is because FlexUnit logs a test for each parameter set being tested. As a result, four tests have been added to the reporting window, and each represents a parameter in the circlePoints.xml file</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+<ul>
+	<li><p>The use case of Parameterized testing and Theories is different.</p></li>
+	<li><p>Parameterized tests pass entire sets of arguments to a method. Theories define possible combinations.</p></li>
+	<li><p>Parameterized require the RunWith metadata <code>[RunWith("org.flexunit.runners.Parameterized")]</code>.</p></li>
+	<li><p>Public static arrays containing arrays of arguments feed data into test methods and constructors depending on the style.</p></li>
+	<li><p>Two types of Parameterized testing: TestNG and JUnit.</p></li>
+	<li><p>TestNG Style - Declares a dataProvider per test method, therefore allowing different tests to use different data.</p></li>
+	<li><p>JUnit Style - Instantiates parameterized data to instance variables within the class constructor.</p></li>
+	<li><p>Complex objects can be passed as parameterized data. </p></li>
+	<li><p>External data can be loaded for parameterized testing with a custom loader.</p></li>
+	<ul> 
+		<li><p>The loader classes used for parameterized testing are created in exact same way as those used for theories.</p></li>
+	</ul>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-12.html" class="next"></a>
+			<a href="Unit-10.html" class="prev"></a>
+			<a href="../flexunit.html" class="indexbutton"></a>
+		</div>
+				
+	</div>
+	
+
+</body>
+</html>
\ No newline at end of file

Added: websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-12.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-12.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-12.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,196 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+	
+	<title>Running Tests from Different Versions</title>
+
+	<script language="JavaScript" src="../scripts/jquery-1.5.min.js" ></script>
+	<link href="../css/style.css" rel="stylesheet" type="text/css" />
+
+</head>
+<body>
+	
+	<div id="container">
+		
+		<div id="contentborder">
+			<div id="unitdownload">
+				
+					<a href="../code/unit12.zip"><img style="vertical-align:middle;border-style:none;" src="../images/DownloadIcon.png" alt="Download" /></a>
+					<span style="font-size:24px;font-weight:bold;color:#666666;margin-left:10px;">Project Files</span>
+				
+			</div>
+			<div id="content">
+
+<h1>Unit 12 - Running Tests from Different Versions</h1>
+
+<p>Throughout this course you have been introduced to new types of runners for FlexUnit 4. The first runner you used ran basic FlexUnit tests. The proper name for that runner is the BlockFlexUnit4Runner. Next you learned about the Suite runner and more recently the Theories and Parameterized runner.</p>
+<p>This lesson introduces two additional runners, the runner for FlexUnit .9 tests and the runner for Fluint 1.x tests.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Create a mixed suite of FlexUnit .9 tests, Fluint 1 tests, and FlexUnit 4.x tests</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Running a FlexUnit .9 test</li>
+	<li>Running a Fluint 1 test</li>
+	<li>Understanding a runner</li>
+	<li>Understanding how FlexUnit 4.x can work with multiple runners</li>
+</ul>
+
+<h2>Running a FlexUnit .9 test</h2>
+
+<ul>
+	<li>FlexUnit 4 includes the entire FlexUnit .9 framework</li>
+	<li>You may not mix FlexUnit .9 and FlexUnit 4 style tests in the same test case,</li> 
+	<li>FlexUnit .9 and FlexUnit 4 tests can exist in the same FlexUnit 4 suite</li>
+</ul>
+
+<h2>Running a Fluint 1 test</h2>
+
+<ul>
+	<li>FlexUnit 4 also includes the entire Fluint 1 framework</li>
+	<li>Like FlexUnit .9, you may not mix Fluint 1 tests with FlexUnit 4 tests in the same test case</li>
+	<li>Fluint 1 and FlexUnit 4 tests can exist in the same FlexUnit 4 suite</li>
+</ul>
+
+<h2>Understanding a runner</h2>
+
+<p>Runners are a major component of the extensibility layer of FlexUnit 4. They facilitate creating entirely new test types that can gain the benefit of FlexUnit 4.x integration without rewriting the entire code base.</p>
+<p>A runner is just a class that implements an interface that FlexUnit 4 can understand.  FlexUnit 4 includes runners for FlexUnit .9, Fluint 1, FlexUnit 4, Suites, Theories, and Parameterized tests.</p>
+<p>Runners operate through a token system. At the start of a test run, a runner is provided a token. To simplify things a bit, you can think of the token like the silver baton used in a relay race.  The system asks each runner in turn if it can handle the tests contained within an individual class. If the runner can, it passes a token to that runner which now becomes the active runner.</p> 
+<p>That runner in turn hands the token to any sub-runners as needed (think Suite which just contains classes to be run by other runners). Once the test completes it passes the token and result back to whomever provided it with the token. In this way, tests are recursively executed until the token makes it all the way back to the framework itself.</p>
+
+<h2>Understanding how FlexUnit 4.x can work with multiple runners</h2>
+
+<p>The token system within FlexUnit 4 allows the framework to understand different runners without knowing the actual implementation of the runners. As long a runner notifies FlexUnit 4 through the token that a test finished and what the result was the framework does not care how the runner made that decision.</p>  
+<p>The metadata decoration "RunWith" notifies FlexUnit 4 which runner to use for the tests contained in the class.  If no runner is specified FlexUnit 4 will attempt to derive the correct runner from a series of possibilities.</p> 
+<p>You can create new runners from scratch or extend existing runners to add functionality. The parameterized runner is an excellent example of adding additional functionality to the base runners used by FlexUnit.</p>
+
+<h2>Walkthrough 1: Creating a mixed Suite of Tests</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Run a FlexUnit 1 test case alongside FlexUnit 4 test cases and suites.</li> 
+</ul>
+
+<h3>Import a new test</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnit4Training_wt1.fxp project from the Unit 12/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Examining the FlexUnit .9 tests</h3>
+		
+	</li>
+	<li>
+		<p>Open the TestAssert.as file in the fu1 package in the tests folder.</p>
+		<p>As you examine the class file you will notice a few differences about these test methods. The <code>TestAssert</code> class extends from the <code>TestCase</code> class.  The TestCase class was the base class for all tests in FlexUnit .9.</p>
+
+<code><pre>public class TestAssert extends TestCase {      
+      public function TestAssert( name : String = null ) {
+         super( name );
+      }
+
+      ...
+}</pre></code>
+
+<p>The class constructor in FlexUnit .9 can be used to provide a name for this test in certain circumstances. In this test it does nothing more than call its <code>super()</code> method. FlexUnit 4.x tests do not descend from any particular class.</p> 
+<p>Metadata is not used to distinguish tests and fixture from normal methods. Every method in this case prefixes the word <i>test</i> to its name. Take a look at the <code>testMatch()</code> method:</p>
+
+<code><pre>public function testMatch() : void {
+	Assert.assertMatch(
+	     /fr.*gt/,
+	     "feeefrbgbgbggt" );
+
+	Assert.assertMatch(
+	     /.*@adobe\.com/,
+	     "xagnetti@adobe.com" );
+
+	Assert.assertMatch(
+	     /.*@adobe.?com/,
+	     "xagnetti@adobevcom" );
+
+	try {
+	   Assert.assertMatch(
+	     /.*@adobe\.com/,
+	     "xagnetti@adobevcom" );             
+	}
+	catch ( e : AssertionFailedError ) {
+	   assertAssertionsHaveBeenMade( 4 );
+
+	   return;
+	}
+	fail();
+}</pre></code>
+
+		<p>There are separate Assert classes in FlexUnit 4 and FlexUnit .9.  Both have static methods for making assertions. When running tests in FlexUnit 4 you can use either of these classes, to help maintain backwards compatibility.</p> 
+		<p>FlexUnit 4.x Assert: <code>org.flexunit.Assert</code></p>
+		<p>FlexUnit 1 Assert: <code>flexunit.framework.Assert</code></p>
+		<p>For catching errors, FlexUnit 1 uses <code>try, catch</code> statements. FlexUnit 4.x uses <code>expects=""</code> metadata for the same kind of test.</p>
+
+		<h3><br />Run FlexUnit 1 tests</h3>
+		
+	</li>
+	<li>
+		<p>Open the FlexUnit4Training.mxml file.</p>
+	</li>
+	<li>
+		<p>Within the <code>&#60;fx:Script&#62;</code> block there is a function named <code>currentRunTestSuite()</code>. Add a line that calls the <code>testsToRun.push()</code> method with the argument <code>TestAssert</code>.</p> 
+
+<code><pre>import fu1.TestAssert;
+
+import math.testcases.CircleSuite;
+
+public function currentRunTestSuite():Array {
+	var testsToRun:Array = new Array();
+	testsToRun.push( CircleSuite );
+	testsToRun.push( TestAssert );
+	return testsToRun;
+}</pre></code>
+
+		<p>If you did not use code-completion, add the import statement for fu1.TestAssert at this point.</p>
+	</li>
+	<li>
+		<p>Save and Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit12/image1.png' /> 
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+
+		<p>And in the FlexUnit Results tab, you will see the results of all tests:</p>
+
+		<img alt='ResultsWindow' id='shift' src='../images/unit12/image2.png' /> 
+		<p class='caption' id='shift'>Figure 2: FlexUnit results window</p>
+		
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>FlexUnit 4.x can run test cases from FlexUnit .9 and Fluint 1.x.</p></li>
+	<li><p>Tests from legacy frameworks must be isolated to their own cases, because they must be run with their own runner.</p></li>
+	<li><p>The results of tests from all cases are available in the Flash Builder FlexUnit Results tab.</p></li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-13.html" class="next"></a>
+			<a href="Unit-11.html" class="prev"></a>
+			<a href="../flexunit.html" class="indexbutton"></a>
+		</div>
+				
+	</div>
+	
+
+</body>
+</html>
\ No newline at end of file

Added: websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-13.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-13.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-13.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,869 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+	
+	<title>Working with Asynchronous Operations</title>
+
+	<script language="JavaScript" src="../scripts/jquery-1.5.min.js" ></script>
+	<link href="../css/style.css" rel="stylesheet" type="text/css" />
+
+</head>
+<body>
+	
+	<div id="container">
+		
+		<div id="contentborder">
+			<div id="unitdownload">
+				
+					<a href="../code/unit13.zip"><img style="vertical-align:middle;border-style:none;" src="../images/DownloadIcon.png" alt="Download" /></a>
+					<span style="font-size:24px;font-weight:bold;color:#666666;margin-left:10px;">Project Files</span>
+				
+			</div>
+			<div id="content">
+
+<h1>Unit 13 - Working with Asynchronous Operations</h1>
+
+<p>FlexUnit 4.x takes advantage of a variety of inherently asynchronous operations. Test Fixture, Test Theories, Loading External Data, and Parameterized testing take advantage of asynchronous setup. Some tests require a span of time in order to verify expected results. FlexUnit 4.x provides tools to validate asynchronous functionality.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Use asynchronous handling in test cases</li> 
+	<li>Handle errors and timeouts in asynchronous style tests</li>
+	<li>Write a chain of operations using sequences</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Understanding the need for async</li>
+	<li>Introduction to the available async methods</li>
+	<li>Understanding error handling with async</li>
+	<li>Event based synchronous versus asynchronous</li>
+	<li>Chaining async operations</li>
+</ul>
+
+<h2>Understanding the need for async</h2>
+
+<p>Up until now, all tests in this text have been synchronous in nature. Tests run and assertions are made line by line. However, ActionScript 3.0 and Flex are asynchronous by nature. You may have to wait for an event, a database retrieval, or a timer to complete. Currently, any of these operations would be marked as a pass or failure immediately without waiting for the actual event to be received.</p>
+<p>Consider the external data loading you have used so far in theories and parameter tests. Loading from an XML file is asynchronous, depending on the amount of data the load time of that file can change.</p>
+<p>Without asynchronous support, a large portion of systems would remain untested creating an easy location for bugs to hide. Race conditions can potentially be the origin of huge bugs that, without asynchronous testing, can cause countless hours of debugging.</p>
+
+<h2>Introduction to the available async methods</h2>
+
+<p>FlexUnit 4 contains extensive support for asynchronous tests. All asynchronous tests are decorated with the annotation <code>async</code> which notifies the runner this test is not complete once the method has reached the closing brace.</p>
+
+<code><pre>[Test( async )]</pre></code>
+
+<p>Decorating a test with async causes the runner to hold that test in memory. The test runner relies on an async handler to notify when the test is complete. Omitting an async handler will cause the test to hang indefinitely. To prevent the test from hanging, we may also decorate the test with the timeout annotation.</p>
+
+<code><pre>[Test( async, timeout="1000" )]</pre></code>
+
+<p>The Async class in FlexUnit 4 contains numerous static methods for handling async testing.</p>
+<ul>
+	<li><p><code>Async.asyncHandler</code> - Most common asynchronous test. Returns a handler when the async test succeeds or fails from which additional testing can occur.</p></li>
+	<li><p><code>Async.proceedOnEvent</code> - Used when you are concerned if an event is thrown, but not the condition under which it is thrown. If the event is received, the test will continue, otherwise the test will be marked as a failure.</p></li>
+	<li><p><code>Async.failOnEvent</code> - Registers an event as an automatic failure. This handler will cause the test runner to wait a timeout period for the condition under test to fire the failure event. If no failure is received, test execution will complete under the timeout handler. If no handler is specified, the test will be marked as a success once the timeout has expired.</p></li>
+	<li><p><code>Async.registerFailureEvent</code> - Used when a certain event can cause a test to fail, but the event itself is not under test. If the event is received anytime during test execution the test will immediately be marked as a failure.</p></li>
+	<li><p><code>Async.handleEvent</code> - Used when the event is part of success of the test, but the throwing of the event itself does not indicate a success. Unlike <code>proceedOnEvent</code>, this handler will call a complete handler if the event is received within the timeout period.</p></li>
+	<li><p><code>Async.asyncResponder</code> - Used in a similar fashion as <code>Async.handleEvent</code>, however works with AsyncTokens and Responders. Not usable in ActionScript only projects.</p></li>
+	<li><p><code>Async.asyncNativeResponder</code> - Similar to <code>Async.asyncResponder</code> and used in a similar format. Used in ActionScript projects.</p></li>
+</ul>
+
+<h2>Walkthrough 1: Creating a Simple Async Test with Timers</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create an async test method using a timer.</li>
+	<li>Create a new suite for async tests.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnit4Training_wt1.fxp project from the Unit13/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+	</li>
+	<li>
+		<p>Create a new package named async.testcases in the tests directory.</p>
+		
+		<h3><br />Create a basic async test</h3>
+		
+	</li>
+	<li>
+		<p>In the async.testcases package create a new ActionScript class named <code>BasicTimerTest</code>.</p>
+	</li>
+	<li>
+		<p>Remove the automatically created constructor from the class.</p>
+
+<code><pre>package async.testcases {
+	public class BasicTimerTest {
+	}
+}</pre></code>
+		
+		<h3><br />Create an async test case</h3>
+		
+	</li>
+	<li>
+		<p>Declare a new private property named <code>timer</code> of type <code>Timer</code> within the class.</p>
+
+		<code><pre>private var timer:Timer;</pre></code>
+
+		<p>If you did not use code-completion, add the import for flash.utils.Timer at this time.</p>
+	</li>
+	<li>
+		<p>Declare setup and teardown methods for the class, each marked with <code>[Before]</code> and <code>[After]</code> metadata. The setup method will instantiate <code>timer</code> with a delay of <code>100</code> and a repeat count of <code>1</code>. The teardown method will check if <code>timer</code> is running, stop it if necessary, and destroy the instance.</p>
+
+<code><pre>[Before]
+public function setUp():void {
+	timer = new Timer( 100, 1 );
+}
+
+[After]
+public function tearDown():void {
+	if( timer &#38;&#38; timer.running ) {
+		timer.stop();
+	}
+
+	timer = null;
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Write a test method named <code>shouldCompleteTimer()</code>. It will add an event listener for the <code>TimerEvent.TIMER_COMPLETE</code> event which will call an <code>AsyncHandler()</code> method. This asynchronous test must be marked with <code>[Test( async )]</code> metadata in order to be run asynchronously.</p>
+
+<code><pre>[Test( async )]
+public function shouldCompleteTimer():void {
+	timer.addEventListener( TimerEvent.TIMER_COMPLETE,
+		Async.asyncHandler( this, handleWin, 100, timer, handleTimeout ),
+		false, 0, true );
+}</pre></code>
+
+<p><code>asyncHandler()</code> calls a success handler or timeout handler depending on whether the <code>TimerEvent.TIMER_COMPLETE</code> event is dispatched before the <code>timeOut</code> limit.</p>
+<p>If you did not use code-completion, add the import statements for org.flexunit.async.Async and flash.events.TimerEvent at this time.</p>
+<p>Take a look at the <code>Async.asyncHandler()</code> method used within the <code>addEventListener()</code> method in the <code>testTimerComplete()</code> test.</p>
+
+<code><pre>Async.asyncHandler( this, handleWin, 100, timer, handleTimeout )</pre></code>
+
+<p>The prototype of this method is:</p>
+
+<code><pre>Async.asyncHandler(testCase:Object, eventHandler:Function, timeout:int, passThroughData:Object=null,
+ timeoutHandler:Function=null):Function</pre></code>
+
+<p>This method references two functions: <code>handleWin()</code> and <code>handleTimeout()</code>. The method <code>handleWin()</code> is called if the <code>TimerEvent.TIMER_COMPLETE</code> occurs before the <code>timeout</code>, which is set at 100.  <code>handleTimeout()</code> is the function called if the event is not dispatched before the timeout. <code>handleWin()</code> will receive both the <code>event</code> and <code>passThroughData</code> objects as arguments. The method <code>handleTimeout()</code> will only receives the <code>passThroughData</code>.</p>
+	</li>
+	<li>
+		<p>Add a call to the <code>timer.start()</code> method on the last line of the <code>shouldCompleteTimer()</code> test method.</p>
+
+<code><pre>[Test( async )]
+public function shouldCompleteTimer():void {
+	timer.addEventListener( TimerEvent.TIMER_COMPLETE,
+		Async.asyncHandler( this, handleWin, 100, timer, handleTimeout ),
+		false, 0, true );
+	timer.start();
+}</pre></code>
+
+		<p>You will need to declare both the <code>handleWin()</code> and <code>handleTimeout()</code> functions. They can be specified as protected because they are only run within the specific test case and not by the runner itself.</p>
+	</li>
+	<li>
+		<p>Declare the <code>handleWin()</code> function as protected. It should accept two parameters, one named <code>event</code> of type <code>Event</code>, and the other named <code>passThroughData</code> of type <code>Object</code>.</p>
+	</li>
+	<li>
+		<p>The <code>handleTimeout()</code> method should also be declared as protected and accept a single parameter named <code>passThroughData</code> of type <code>Object</code>.</p>
+
+<code><pre>protected function handleWin( event:Event, passThroughData:Object ):void {
+}
+
+protected function handleTimeout( passThroughData:Object ):void {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>Assert.assertEquals()</code> method in the <code>handleWin()</code> method. It should take <code>( event.target as Timer ).currentCount</code> and <code>passThroughData.repeatCount</code> as its arguments.</p>
+
+<code><pre>protected function handleWin( event:Event, passThroughData:Object ):void {
+	Assert.assertEquals( ( event.target as Timer ).currentCount, passThroughData.repeatCount );
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>Assert.fail()</code> method in the <code>handleTimeout()</code> method. It should take the string <code>"Pending event timed out"</code> as its argument.</p>
+
+<code><pre>protected function handleTimeout( passThroughData:Object ):void {
+	Assert.fail("Pending event timed out");
+}</pre></code>
+
+<p>If you did not use code-completion, add the import statements for flash.events.Event and org.flexunit.Assert at this time.</p>
+	</li>
+	<li>
+		<p>Save BasicTimerTest.as.</p>
+
+		<h3><br />Create an async suite</h3>
+		
+	</li>
+	<li>
+		<p>In the async.testcases package create a new ActionScript class named AsyncSuite. The package directory should appear as follows:</p>
+
+		<img alt='PackageDirectory' id='shift' src='../images/unit13/image1.png' /> 
+		<p class='caption' id='shift'>Figure 1: Package directory structure</p>
+
+		<p>The AsyncSuite class will behave similar to the CircleSuite, running with the suite runner and calling tests within the flexUnitTests.cases.async package.</p> 
+	</li>
+	<li>
+		<p>Remove the automatically created constructor from AsyncSuite.as.</p>
+
+<code><pre>package async.testcases {
+	public class AsyncSuite {	
+	}
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Mark the AsyncSuite class definition with <code>[Suite]</code> and <code>[RunWith("org.flexunit.runners.Suite")]</code> metadata.</p>
+
+<code><pre>package async.testcases {
+	[Suite]
+	[RunWith("org.flexunit.runners.Suite")]
+	public class AsyncSuite {
+	}
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a public variable named <code>test1</code> of type <code>BasicTimerTest</code>.</p>
+
+		<code><pre>public var test1:BasicTimerTest;</pre></code>
+		
+	</li>
+	<li>
+		<p>Save AsyncSuite.as.</p>
+		<p>Normally, a suite is not created to contain a single test case. In this case, we know ahead of time that the <code>Async</code> class will eventually contain more test files.</p> 
+
+		<h3><br />Create a new top-level suite</h3>
+		
+		<p>At this point, your testing environment includes test cases for the <code>Circle</code> class as well as a new one in the async.testcases package. Take this opportunity to create a new top-level suite that will run all the suites from the various packages.</p>
+	</li>
+	<li>
+		<p>In the tests directory, create a new package named testcases.</p>
+	</li>
+	<li>
+		<p>In the new testcases package, create an ActionScript class named <code>AllSuites</code>. This class has no superclass or interfaces.</p>
+	</li>
+	<li>
+		<p>Remove the automatically created constructor from the new class and mark it with <code>[Suite]</code> and <code>[RunWith("org.flexunit.runners.Suite")]</code> metadata.</p>
+
+<code><pre>package testcases {
+	[Suite]
+	[RunWith("org.flexunit.runners.Suite")]
+	public class AllSuites {
+	}
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a public variable named <code>circleSuite</code> of type <code>CircleSuite</code> to the new class.</p>
+	</li>
+	<li>
+		<p>Add another public varibale named <code>asyncSuite</code> of type <code>AsyncSuite</code> to the class.</p>
+
+<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class AllSuites {
+	public var circleSuite:CircleSuite;
+	public var asyncSuite:AsyncSuite;	
+}</pre></code>
+
+		<p>If you did not use code-completion, add the imports for math.testcases.CircleSuite and async.testcases.AsynSuite at this time.</p>
+	</li>
+	<li>
+		<p>Save AllSuites.as.</p>
+		
+		<h3><br />Run the new suite from the application</h3>
+		
+	</li>
+	<li>
+		<p>Open the FlexUnit4Training.mxml file.</p>
+	</li>
+	<li>
+		<p>Replace <code>CircleSuite</code> with <code>AllSuites</code> in the <code>testsToRun.push()</code> statement.</p>
+
+		<code><pre>testsToRun.push( CircleSuite );</pre></code>
+
+		<p>Becomes:</p>
+		
+		<code><pre>testsToRun.push( AllSuites );</pre></code>
+
+		<p>If you did not use code-completion, add the import for the testcases.AllSuites at this time.</p>
+	</li>
+	<li>
+		<p>Remove the import statement for math.testcases.CircleSuite from the FlexUnit4Training.mxml file.</p>
+	</li>
+	<li>
+		<p>Save FlexUnit4Training.mxml.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit13/image2.png' />
+		<p class='caption' id='shift'>Figure 2: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+
+<h2>Understanding error handling with async</h2>
+
+<p>In Unit 5 you learned how to handle errors using the <code>[Test(expects="ErrorType")]</code> metadata. Asynchronous methods can handle errors in the same way. Errors thrown in the handler are still dealt with in the test method.</p>
+
+<code><pre>[Test( async, expects="Error" )]
+public function testTimerComplete():void {
+	timer.addEventListener( TimerEvent.TIMER_COMPLETE,
+		Async.asyncHandler( this, handleWin, 100, timer, handleTimeout ),
+		false, 0, true );
+	timer.start();
+}
+
+protected function handleWin( event:Event, passThroughData:Object ):void {
+	throw new Error();
+}</pre></code>
+
+<p>As you can see, the <code>Async.asyncHandler</code> is called upon the <code>TIMER_COMPLETE</code> event, just as in the previous walkthrough. The resulting handler is simplistic, but clearly illustrates how the error is then handled through the test, where the metadata reads <code>[Test( async, expects="Error" )]</code>. There are several situations in which you need the message or the resulting handler to utilize <code>passThroughData</code> or additional custom information within the error thrown. In these cases, the <code>expects</code> annotation is insufficient. Here, the handler can be outfitted with a <code>try-catch</code> statement that handles a specific error and data potentially carried with that error.</p>
+
+<code><pre>[Test( async )]
+public function testTimerComplete():void {
+	timer.addEventListener( TimerEvent.TIMER_COMPLETE,
+		Async.asyncHandler( this, handleWin, 100, timer, handleTimeout ),
+		false, 0, true );
+	timer.start();
+}
+
+protected function handleWin( event:Event, passThroughData:Object ):void {
+	try {
+		throw new TypeError();
+	}
+	catch ( e:TypeError ) {
+		assertThat( passThroughData, equalTo( timer ) );
+		return;
+	}
+	Assert.fail( "Incorrect error thrown" );
+}</pre></code>
+
+<p>The <code>try-catch</code> statement is looking for a <code>typeError</code>, and then it continues to evaluate with an <code>assertThat</code> statement, expecting the equality of the <code>timer</code> and <code>passThroughData</code>. In these cases, the <code>expects</code> annotation will weaken the test. The test will only expect the kind of error specified, and it will not assert equality, such as is shown through the <code>catch</code> above.</p>
+
+
+<h2>Event based synchronous versus asynchronous</h2>
+
+<p>FlexUnit testing is based on the idea of synchronous tests occurring in order. These tests can throw events, errors, and deliver results, but they don't wait around for anything to happen, they just run.</p>
+<p>Asynchronous tests are set apart through their metadata, and the asynchronous handlers are the only thing that can bring the test to completion. There are three primary kinds:</p>
+
+<h3>Normal asynchronous completion</h3>
+
+<p>When the test dispatches the expected event within the time limit, the <code>eventHandler</code> method is then called. Even though the desired event has been dispatched, the test does not automatically pass.</p>
+
+<code><pre>Async.asyncHandler(testCase:Object, <b>eventHandler:Function</b>, timeout:int, passThroughData:Object=null,
+ timeoutHandler:Function=null)</pre></code>
+
+<h3>Asynchronous timeout</h3>
+
+<p>Most Async methods are created with timeout variables. If the desired event is not dispatched within the time limit, the <code>timeoutHandler</code> is called.</p>
+<p>When a <code>timeoutHandler</code> is specified, a timeout does not mark a test as a failure. If a timeout indicates failure you need to assert as such in the timeout method.</p>
+<p>If a <code>timeoutHandler</code> is not passed in, the test merely completes with a generic timeout failure.</p>
+
+<code><pre>Async.asyncHandler(testCase:Object, eventHandler:Function, timeout:int, passThroughData:Object=null,
+ <b>timeoutHandler:Function=null</b>)</pre></code>
+
+<h3>Failure events</h3>
+
+<p>When using the Async.failOnEvent or Async.registerFailureOnEvent methods, specific events can be registered as an instantaneous failure.</p>
+
+<h2>Walkthrough 2: Handling an Event</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Load external data for a parameterized test.</li>
+	<li>Create a test fixture using asynchronous startup.</li>
+	<li>Setup a test to proceed on completion of a simulated prime calculation.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Create a new ActionScript class named PrimeNumberGeneratorTest.as in the async.testcases package within the tests directory.</p>
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training_wt2.fxp project from the Unit13/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Create the fixture</h3>
+		
+	</li>
+	<li>
+		<p>Mark the <code>PrimeNumberGeneratorTest</code> class with <code>[RunWith("org.flexunit.runners.Parameterized")]</code> metadata.</p> 
+
+<code><pre>[RunWith("org.flexunit.runners.Parameterized")]
+public class PrimeNumberGeneratorTest {
+	public function PrimeNumberGeneratorTest() {
+	}
+}</pre></code>
+
+		<p>You will be using JUnit style paramterized loading for this test. Because this style requires parameters to be set in the constructor, leave the constructor in place.</p>
+	</li>
+	<li>
+		<p>Add a private variable named <code>primeGenerator</code> of type <code>PrimeNumberGenerator</code> to the class.</p>
+
+		<code><pre>private var primeNumberGenerator:PrimeNumberGenerator;</pre></code>
+
+		<p>If you did not use code-completion, add the import for net.digitalprimates.math.PrimeNumberGenerator at this time.</p>
+	</li>
+	<li>
+		<p>Add a private static constant named <code>TIMEOUT</code> of data type <code>int</code> and set it to <code>500</code>.</p>
+
+		<code><pre>private static const TIMEOUT:int = 500;</pre></code>
+		
+	</li>
+	<li>
+		<p>Add another public static variable named <code>numberLoader</code> of type <code>NumberDataHelper</code>. Instantiate the variable with a URL string: "<code>xml/numberList.xml</code>"</p>
+
+		<code><pre>public static var numberLoader:NumberDataHelper = new NumberDataHelper( "xml/numberList.xml" );</pre></code>
+
+		<p>If you did not use code-completion, add the import for helper.NumberDataHelper at this time.</p>
+	</li>
+	<li>
+		<p>Create a new static variable named <code>data</code>. Decorate it with the <code>Parameters</code> metadata and pass it a <code>loader</code> of <code>numberLoader</code></p>
+
+<code><pre>[Parameters(loader="numberLoader")]
+public static var data:Array;</pre></code>
+		
+	</li>
+	<li>
+		<p>Add two private instance variables of type <code>Number</code> named <code>value</code> and <code>length</code>. In typical JUnit style, make the constructor take values for each as arguments, and set the instance variables when the constructor is run.</p> 
+
+<code><pre>private var value:Number;
+private var length:Number;
+
+public function PrimeNumberGeneratorTest( value:Number, length:Number ) {
+	this.value = value;
+	this.length = length;
+}</pre></code>
+
+<p>All instance variables for the class should now be declared.</p>		
+	</li>
+	<li>
+		<p>Create a new method named <code>setup()</code> and a method named <code>teardown()</code>. Decorate them with the <code>[Before( async )]</code> and <code>[After( async )]</code> metadata, respectively.</p>
+
+<code><pre>[Before( async )]
+public function setup():void {
+}
+
+[After( async )]
+public function teardown():void {
+}</pre></code>
+
+<p>The <code>async</code> annotation notifies the test runner the <code>setup()</code> and <code>teardown()</code> methods are not complete when the end brace is reached. The <code>PrimeNumberGenerator</code> simulates this event through the use of a timer. You will need to specify a complete condition just as you would for an asynchronous test or the startup will hang indefinitely.</p> 
+	</li>
+	<li>
+		<p>Within the <code>setup()</code> method, create a new instance of <code>primeNumberGenerator</code>.  On the next line, add a call to the method <code>Async.proceedOnEvent()</code> passing the arguments <code>this</code>, <code>primeNumberGenerator</code> and <code>TIMEOUT</code>.</p>
+
+<code><pre>[Before( async )]
+public function setup():void {
+	primeNumberGenerator = new PrimeNumberGenerator();
+	Async.proceedOnEvent( this, primeNumberGenerator, PrimeGeneratorEvent.GENERATOR_READY,
+	 TIMEOUT );
+}</pre></code>
+
+		<p><code>Async.proceedOnEvent()</code> causes the test runner to wait for the parameter <code>IEventDispatcher</code> to dispatch an event before proceeding.  In this case the event is named: <code>PrimeGeneratorEvent.GENERATOR_READY</code>.</p>
+		<p>If you did not use code completion, add the imports for org.flexunit.async.Async and net.digitalprimates.event.PrimeGeneratorEvent at this time.</p>
+	</li>
+	<li>
+		<p>In the <code>teardown()</code> method, remove the instance of <code>primeNumberGenerator</code>.</p>
+
+<code><pre>[After( async )]
+public function tearDown():void {
+	primeNumberGenerator = null;
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Your completed asynchrounous startup should now appear as:</p>
+
+<code><pre>[RunWith("org.flexunit.runners.Parameterized")]
+public class PrimeNumberGeneratorTest {
+	private var primeNumberGenerator:PrimeNumberGenerator;
+
+	public static const TIMEOUT : int = 500;
+
+	public static var numberLoader:NumberDataHelper =
+	 new NumberDataHelper( "xml/numberList.xml" );
+
+	[Before( async )]
+	public function setup():void {
+		primeNumberGenerator = new PrimeNumberGenerator();
+		Async.proceedOnEvent( this, primeNumberGenerator, PrimeGeneratorEvent.GENERATOR_READY,
+		 TIMEOUT );
+	}
+
+	[After( async )]
+	public function teardown():void {
+		primeNumberGenerator = null;
+	}
+
+	private var value:Number;
+	private var length:Number;
+
+	public function PrimeNumberGeneratorTest( value:Number, length:Number ) {
+		this.value = value;
+		this.length = length;
+	}
+}</pre></code>
+
+<h3><br />Create the generator test</h3>
+		
+	</li>
+	<li>
+		<p>Add a new test method named <code>shouldCreatePrimeArray()</code> to the class, mark it with <code>[Test(async)]</code> metadata.  This method creates a new async handler to the <code>handleEvent()</code> method, passing in the arguments <code>this</code>, <code>primeNumberGenerator</code>, <code>PrimeNumberGenerator.GENERATION_COMPLETE</code>, <code>handleComplete</code> and <code>TIMEOUT</code>.</p>
+
+<code><pre>[Test(async)]
+public function shouldCreatePrimeArray():void {
+	Async.handleEvent( this, primeNumberGenerator, PrimeGeneratorEvent.GENERATION_COMPLETE,
+	 handleComplete, TIMEOUT );
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to <code>primeNumberGenerator.generatePrimes()</code> method, passing in the instance variable <code>value</code> as its argument.</p>
+
+<code><pre>[Test(async)]
+public function shouldCreatePrimeArray():void {
+	Async.handleEvent( this, primeNumberGenerator, PrimeGeneratorEvent.GENERATION_COMPLETE,
+	 handleComplete, TIMEOUT );
+	
+	primeNumberGenerator.generatePrimes( value );
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Create the <code>handleComplete()</code> method referenced in the <code>Async.handleEvent()</code> method from the previous step. It needs to accept two parameters, one named <code>event</code> of type <code>PrimeGeneratorEvent</code>, and another named <code>passThroughData</code> of type Object.</p>
+
+<code><pre>protected function handleComplete( event:PrimeGeneratorEvent, passThroughData:Object ):void {
+}</pre></code>
+
+		<p>The <code>Async.handleEvent()</code> method above declares no <code>timeoutHandler()</code>, so it will just use the default message. This will suffice for this walkthrough, however it can be added as the last argument of the <code>Async.handleEvent()</code> method if necessary.</p>
+	</li>
+	<li>
+		<p>Add a call to the <code>assertThat()</code> method within the <code>handleComplete</code> method. It should assert that <code>event.primeList.length</code> is equal to <code>length</code>.</p>
+
+<code><pre>protected function handleComplete( event:PrimeGeneratorEvent, passThroughData:Object ):void {
+	assertThat( event.primeList.length, equalTo( length ) );
+}</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.flexunit.assertThat and org.hamcrest.object.equalTo at this time.</p>
+	</li>
+	<li>
+		<p>Save PrimeNumberGeneratorTest.as.</p>
+
+		<h3><br />Add NumberGeneratorTest to the AsyncSuite</h3>
+		
+	</li>
+	<li>
+		<p>Open AsyncSuite.as in the async.testcases package. Add a public variable named <code>test2</code> of type <code>PrimeNumberGeneratorTest</code>.</p>
+
+<code><pre>package async.testcases {
+	[Suite]
+	[RunWith("org.flexunit.runners.Suite")]
+	public class AsyncSuite {
+		public var test1:BasicTimerTest;
+		public var test2:PrimeNumberGeneratorTest;
+	}
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully, you should see the following in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit13/image3.png' />
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Chaining async operations</h2>
+
+<p>Frequently, integration tests require a sequence of events before the actual test can be performed. In simple event sequences, chaining async handlers is an effective way to test component behaviors.</p>
+<p>Consider the case of an alarm clock that cycles a series of pictures on expiration:</p>
+<ol>
+	<li>A user sets an alarm.</li>
+	<li>When the alarm expires, the system displays a series of pictures on an interval.</li>
+</ol>
+<p>Now consider all the steps that occur when testing this scenario:</p>
+<ol>
+	<li>The test would need to set an alarm.</li>
+	<li>The system would need to wait for alarm expiration.</li>
+	<li>The system would display a picture.</li>
+	<li>The test would have to wait for the picture display time to expire.</li>
+	<li>Repeat steps 3 and 4.</li>
+	<li>The test would have to wait for the system to complete displaying all the pictures.</li>
+</ol>
+<p>This is a testable use case. The testing concern is whether the component fires the events and system displays all the pictures. You could use a chain of async handlers.</p> 
+
+<code><pre>[Test( async, ui )]
+public void shouldSubmitForm():void {
+	//Create a new alarm clock
+	//Set an alarm time
+	//Proceed on event: "alarmExpired"
+	//Wait for the picture
+	//Proceed on event: "pictureLoaded"
+	//Display the picture
+	//Proceed on event: "pictureDisplayExpired"
+	//Load and display other pictures
+	//Proceed on event: "allPicturesDisplayed"
+	//Verify expected number of pictures displayed
+}</pre></code>
+
+<p>As you can see, this can rapidly become very complex as we wait for event after event. Each of these asynchronous operations could require its own async handler leading to a very large test class. This is a simple example, but many UI components, which we will cover in the next unit, can rapidly devolve into a massive integration test. In addition, some components, especially higher level components, require user interaction that cannot be easily simulated through the use of async chains.</p>
+<p>FlexUnit 4 contains a special tool for handling these types of use cases called sequences.</p>
+
+<h2>Understanding sequences</h2>
+
+<p>Sequences are methods by which a developer can create a series of tests, execute the steps and handle the resulting sequence completion. Sequences control the flow of a components execution.</p> 
+<p>Sequences have the ability to:</p>
+<ol>
+	<li>Call methods</li>
+	<li>Set properties</li>
+	<li>Wait for events</li>
+	<li>Dispatch events</li>
+	<li>Wait for binding</li>
+</ol>
+<p>Sequences require the test case to use the custom runner named SequenceRunner. Each sequence is created by instantiating a sequence with the current test case, adding a series of tests, adding an optional assert handler and finally running the sequence.</p> 
+<p>A simple sequence for a timer would appear as follows:</p>
+
+<code><pre>[Test( async )]
+public function shouldCompleteTimerSequence():void {
+	var timer:Timer = new Timer( TIMEOUT );
+	var sequence:SequenceRunner = new SequenceRunner( this );
+
+	sequence.addStep( new SequenceCaller( timer, timer.start ) );
+	sequence.addStep( new SequenceWaiter( timer, TimerEvent.TIMER, TIMEOUT2 ) );
+	sequence.addStep( new SequenceWaiter( timer, TimerEvent.TIMER, TIMEOUT2 ) );
+	sequence.addStep( new SequenceWaiter( timer, TimerEvent.TIMER, TIMEOUT2 ) );
+	sequence.addStep( new SequenceCaller( timer, timer.stop );
+	
+	sequence.addAssertHandler( handleSequenceComplete, null );
+			
+	sequence.run();
+}</pre></code>
+
+<p>In this example, the sequence will: start a timer, wait for the timer to cycle three times, stop the timer and make an assertion. The advantage to this setup is if the timer needed to cycle two more times you would just need to add two more sequence waiters.</p>
+<p>In the next walkthrough, you will create your own sequence.</p>
+
+<h2>Walkthrough 3: Creating a chain of events with Sequences</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Write a sequence to test a fake database retrieval connection.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Create a new ActionScript class named ServiceSequenceTest.as in the async.testcases package within the tests directory.</p>
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training_wt3.fxp project from the Unit13/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Create the fixture</h3>
+		
+	</li>
+	<li>
+		<p>Remove the automatically generated constructor.  You will not need it for this test.</p>
+	</li>
+	<li>
+		<p>Add a new private static const named <code>TIMEOUT</code> of type <code>Number</code> and set it to the value <code>500</code>.</p>
+
+		<code><pre>private static const TIMEOUT:Number = 500;</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a private variable named <code>service</code> of type <code>ServiceStub</code> to the class.</p>
+
+		<code><pre>private var service:ServiceStub;</pre></code>
+
+		<p>If you did not use code-completion, add the import for net.digitalprimates.stub.ServiceStub at this time.</p>
+	</li>
+	<li>
+		<p>Create the methods <code>setup()</code> and <code>teardown()</code> and decorate them with the <code>[Before]</code> and <code>[After]</code> metadata respectively. Inside the <code>setup()</code> method create a new instance of <code>service</code> variable. In the <code>teardown()</code> method, set it to null so that it may be garbage collected.</p>
+
+<code><pre>[Before]
+public function setup():void {
+	service = new ServiceStub();
+}
+
+[After]
+public function teardown():void {
+	service = null;
+}</pre></code>
+
+		<h3><br />Prepare the test case</h3>
+		
+	</li>
+	<li>
+		<p>Create a new test called <code>shouldCompleteRequest()</code>. Mark it with <code>[Test(async)]</code> metadata.</p>
+
+<code><pre>[Test( async )]
+public function shouldCompleteRequest():void {
+}</pre></code>
+
+		<p>A request is considered complete when a call to the service instance's <code>shouldCompleteRequest()</code> method has created a connection, sent the request and shutdown the connection. To create a test that listens for all of these events you may either create an asynchrounous chain of handlers or use a sequence. For this test, you will be using a sequence.</p>
+	</li>
+	<li>
+		<p>Inside the body of <code>shouldCompleteRequest()</code>, declare a new variable <code>sequence</code> of the type <code>org.fluint.sequence.SequenceRunner</code>. Make sure you are using the correct <code>SequenceRunner</code> class.</p>
+
+<code><pre>[Test( async )]
+public function shouldCompleteRequest():void {
+	var sequence:SequenceRunner = new SequenceRunner( this );
+}</pre></code>
+
+		<p>If you did not use code-completion, add the import for org.fluint.sequence.SequenceRunner at this time.</p>
+
+		<h3><br />Create the Sequence</h3>
+
+		<p>The next block will setup all the <code>SequenceCallers</code> and <code>SequenceWaiters</code> for the <code>SequenceRunner</code>. In this step you will want to test that when <code>sendRefreshRequest()</code> is called service creates a connection to the server, sends a refresh request and closes the connection.  It is phrased politely because the server may take longer to complete this request depending on various factors such as connection speed, number of requests, etc.</p>
+		<p>To add these steps, you will use the sequence's <code>addStep()</code> method. This method has a single parameter, which must be of type <code>org.fluint.sequence.ISequenceStep</code>. A sequence does not execute until its <code>run()</code> method is called.</p>
+	</li>
+	<li>
+		<p>Add a call to <code>sequence.addStep()</code> passing as an argument <code>new SequenceCaller()</code>. Pass the <code>SequenceCaller</code> constructor the arguments <code>service</code> and <code>service.sendRefreshRequest</code>.</p>
+
+		<code><pre>sequence.addStep( new SequenceCaller( service, service.sendRefreshRequest ) );</pre></code>
+
+		<p>If you did not use code-completion, add the import for org.fluint.sequence.SequenceCaller at this time.</p>
+		<p><code>SequenceCaller</code> sets up an asynchronous delay for the method call. Instead of calling it now, the method will be called when the sequence runs.</p>
+	</li>
+	<li>
+		<p>Next, add a step to the sequence passing as an argument a new instance of the <code>SequenceWaiter</code> class. Pass it <code>service</code>, <code>StubServiceEvent.CONNECTION_CREATED</code>, and <code>TIMEOUT</code> as its arguments.</p>
+
+		<code><pre>sequence.addStep( new SequenceWaiter( service, StubServiceEvent.CONNECTION_CREATED, TIMEOUT ) );</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.fluint.sequence.SequenceWaiter and net.digitalprimates.event.StubServiceEvent at this time.</p>
+		<p>A <code>SequenceWaiter</code> creates an asynchronous handler for the parameter event. When this event is dispatched, the sequence will continue. If the event is not dispatched before the timeout, the timeout handler is called. In this case you are using the default timeout handler which will throw an error. When dealing with a long sequence it is generally best practice to create a custom handler for each <code>SequenceWaiter</code> to avoid confusion.</p>
+	</li>
+	<li>
+		<p>On the next line add a call to the <code>addStep()</code> method that instantiates a <code>new SequenceWaiter</code> with arguments <code>service</code>, <code>StubServiceEvent.RECEIVED_REQUEST</code>, and <code>TIMEOUT</code>.</p>
+
+		<code><pre>sequence.addStep( new SequenceWaiter( service, StubServiceEvent.RECEIVED_REQUEST, TIMEOUT ) );</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a final SequenceWaiter with arguments <code>service</code>, <code>StubServiceEvent.SHUTDOWN_RECEIVED</code>, and <code>TIMEOUT</code>.</p>
+
+		<code><pre>sequence.addStep( new SequenceWaiter( service, StubServiceEvent.SHUTDOWN_RECEIVED, TIMEOUT ) );</pre></code>
+
+		<p>The expected sequence is now set. However, there is no assert set for the completion of the sequence. Currently, as long as all the events are received in order the test is a success. If any of the events are not received within the specified timeout limit, the test fails.</p>
+	</li>
+	<li>
+		<p>Add a call to <code>service.addAssertHandler()</code> passing <code>handleCompleteRequest</code> and <code>null</code>.</p>
+
+		<code><pre>sequence.addAssertHandler( handleCompleteRequest, null );</pre></code>
+
+		<p>The <code>addAssertHandler</code> adds an async handler for when the sequence completes successfully and will call the method specified. In this case, it will call <code>handleCompleteRequest()</code>.</p>
+	</li>
+	<li>
+		<p>To complete the sequence, call <code>sequence.run()</code> within the <code>shouldCompleteRequest()</code> method.</p>
+
+		<code><pre>sequence.run();</pre></code>
+
+		<p>Your complete <code>shouldCompleteRequest()</code> method should now appear as follows:</p>
+
+<code><pre>[Test( async )]
+public function shouldCompleteRequest():void {
+	var sequence:SequenceRunner = new SequenceRunner( this );
+			
+	sequence.addStep( new SequenceCaller( service, service.sendRefreshRequest ) );
+	sequence.addStep( new SequenceWaiter( service, StubServiceEvent.CONNECTION_CREATED,
+	 TIMEOUT ) );
+	sequence.addStep( new SequenceWaiter( service, StubServiceEvent.RECEIVED_REQUEST,
+	 TIMEOUT ) );
+	sequence.addStep( new SequenceWaiter( service, StubServiceEvent.SHUTDOWN_RECEIVED,
+	 TIMEOUT ) );
+			
+	sequence.addAssertHandler( handleCompleteRequest, null );
+			
+	sequence.run();
+}</pre></code>
+
+		<p>If you did not use code-completion, add import statements for, org.fluint.sequence package.SequenceCaller and org.fluint.sequence package .SequenceWaiter at this time.</p>
+	</li>
+	<li>
+		<p>Create the <code>handleCompleteRequest()</code> function.  This function takes two paramters; one named <code>event</code> of type <code>Event</code> and another named <code>passThroughData</code> of type <code>Object</code>.</p>
+
+<code><pre>protected function handleCompleteRequest( event:Event, passThroughData:Object ):void {
+}</pre></code>
+
+		<p>If you did not use code-completion, add the import for flash.events.Event at this time.</p>
+	</li>
+	<li>
+		<p>Add a call to <code>assertFalse()</code> within the <code>handleCompleteRequest()</code> method, asserting that service connection has been terminated.</p>
+
+<code><pre>protected function handleCompleteRequest( event:Event, passThroughData:Object ):void {
+	assertFalse( service.connected );
+}</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.flexunit.assertThat at this time.</p>
+	</li>
+	<li>
+		<p>Save ServiceSequenceTest.as.</p>
+
+		<h3><br />Add the new case to AsyncSuite</h3>
+		
+	</li>
+	<li>
+		<p>Open the AsyncSuite.as file in the async.testcases package.</p>
+	</li>
+	<li>
+		<p>Add a new public variable named <code>test3</code> of type <code>ServiceSequenceTest</code> to the class.</p>
+
+<code><pre>package async.testcases {
+	[Suite]
+	[RunWith("org.flexunit.runners.Suite")]
+	public class AsyncSuite {
+		public var test1:BasicTimerTest;
+		public var test2:PrimeNumberGeneratorTest;
+		public var test3:ServiceSequenceTest;
+	}
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Save the AsyncSuite.as file.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit13/image4.png' />
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed.</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>Fully testing the behavior of a class often involves calling methods, waiting for asynchronous events and verifying the response.</p></li>
+	<li><p>Decorating the <code>[Test]</code> metadata with the <code>async</code> annotation notifies the runner that the test is not complete once the method has reached its closing brace.</p></li>
+	<li><p>The <code>Async</code> class is used to set up completion and timeout handlers for the test.</p></li>
+	<li><p>Annotating the <code>[Test]</code> metadata with <code>expects</code> allows for asynchronous error handling.</p></li>
+	<li><p>Sequences can be used to test a series of asynchronous operations.</p></li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-14.html" class="next"></a>
+			<a href="Unit-12.html" class="prev"></a>
+			<a href="../flexunit.html" class="indexbutton"></a>
+		</div>
+				
+	</div>
+	
+
+</body>
+</html>
\ No newline at end of file



Mime
View raw message