You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by qu...@apache.org on 2014/03/20 04:55:03 UTC

svn commit: r1579527 [5/8] - in /flex/site/trunk: content/flexunit/ content/flexunit/tutorial/ content/flexunit/tutorial/css/ content/flexunit/tutorial/flexunit/ content/flexunit/tutorial/images/ content/flexunit/tutorial/images/Navigation/ content/fle...

Added: flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-6.html
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-6.html?rev=1579527&view=auto
==============================================================================
--- flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-6.html (added)
+++ flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-6.html Thu Mar 20 03:54:59 2014
@@ -0,0 +1,454 @@
+<!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 the Test Fixture</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/unit6.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 6 - Working with the Test Fixture</h1>
+
+<p>Much like any significant amount of code that you develop, your tests will eventually begin to show signs of duplicate code. Fortunately, repeat operations can be factored into discrete methods allowing you to create an understandable test fixture. Instantiating objects, running methods, destroying objects, and loading data are all operations that can be factored into methods and classes with the help of FlexUnit 4.x features.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Use [Before] and [After] metadata to set up and tear down your test fixture</li>
+	<li>Use [BeforeClass] and [AfterClass] metadata to set up and tear down portions of the fixture that persist across tests and cases</li>
+</ul>
+
+<h3>Topics</h3>
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Setting up a fixture</li>
+	<li>Refactoring tests to remove duplication</li>
+	<li>Understand Before as an indication of cohesion</li>
+	<li>The importance of cleaning up the fixture</li>
+</ul>
+
+<h2>Setting up the test fixture</h2>
+
+<p>In the last few lessons you have briefly learned about the concept of a test fixture, which is the collection of all of the state required to run a test repeatedly. So far you have created that state in each test by creating objects and setting properties. Unfortunately, this leads to a fair amount of duplication when many tests share the same setup requirements.</p> 
+<p>FlexUnit offers several ways to factor this repeated setup out into new methods that can be run to create your fixture.</p>
+
+<h3>Before methods</h3>
+
+<p>FlexUnit allows developers to mark any method inside of a test case with a special metadata tag named <code>[Before]</code>. Methods marked with <code>[Before]</code> metadata run before each test method in the test case class.</p>
+<ul>
+	<li>A class may contain any number of <code>[Before]</code> methods.</li>
+	<li>Unless an order is specified, the order of multiple methods marked with <code>[Before]</code> is indeterminate.</li>
+	<li>Methods must be public, accept no arguments and return void.</li>
+	<li>To use, simply decorate the method with <code>[Before]</code> metadata.</li>
+</ul>
+
+<code><pre>[Before]
+public function runMeBeforeEveryTest():void {
+}</pre></code>
+
+<h3>After methods</h3>
+
+<p>The logical opposite of the <code>[Before]</code> metadata is the <code>[After]</code> metadata. Methods marked with <code>[After]</code> run after each test method in the test case class.</p>
+<ul>
+	<li>A class may contain any number of <code>[After]</code> methods.</li>
+	<li>Unless an order is specified, the order of multiple methods marked with <code>[After]</code> is indeterminate.</li>
+	<li>Methods must be public, accept no arguments and return void.</li>
+	<li>To use, simply decorate the method with <code>[After]</code> metadata.</li>
+</ul>
+
+<code><pre>[After]
+public function runMeAfterEveryTest():void {
+}</pre></code>
+
+<h3>Order of Execution</h3>
+
+<p>As indicated above Before and After methods run before and after every test. Therefore, the execution of a method with three tests is indicated below:</p>
+
+<code><pre>	[Before]
+		[Test1]
+	[After] 
+	[Before]
+		[Test2]
+	[After] 
+	[Before]
+		[Test3]
+	[After]</pre></code>
+
+<p>The setup of your test fixture occurs before each test to ensure the test runs in isolation from others in the test case.</p>
+
+<h2>Refactoring to remove duplication</h2>
+
+<p>The methods decorated with <code>[Before]</code> and <code>[After]</code> can be used to remove duplicate code from tests. Once extracted to an independent method, this duplicated code no longer needs to be maintained in each test but rather it can be maintained once for all tests in the test case.</p>
+<p>Ideally, the majority of your test fixture is established through the use of the Before methods, and destroyed through the use of the After methods. This is particularly important. For a test to truly be a unit test it must be isolated. The use of the Before and After methods ensure that a new test fixture is built, tested against and destroyed for each test.</p>
+
+<h2>Walkthrough 1: Creating a Fixture for the Circle Tests</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create <code>setMeUp()</code> and <code>tearMeDown()</code> functions for the test case.</li>
+	<li>Remove circle instantiation from individual tests.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the BasicCircleTest.as file from 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_wt1.fxp project from the Unit 6/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />[Before] &#38; [After] metadata</h3>
+	
+	</li>
+	<li>
+		<p>Add a private variable with the name of <code>circle</code> and a data type of <code>Circle</code> to the class.</p>
+
+		<code><pre>public class BasicCircleTest {		
+	private static const TOLERANCE:Number = .0001;
+	private var circle:Circle;
+	...
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a public function named <code>setMeUp()</code> to the class. Mark the function with a <code>[Before]</code> metadata tag. This function will set the <code>circle</code> property to a new <code>Circle</code> instance with arguments <code>new Point( 0, 0 )</code> and <code>5</code>.</p>
+
+		<code><pre>[Before]
+public function setMeUp():void {
+	circle = new Circle( new Point( 0, 0 ), 5 );
+}		</pre></code>
+		
+		<p>Note, the name of the function is unimportant. It is only the Before metadata that makes this a Before method.</p>
+	</li>
+	<li>
+		<p>Similarly, add another public function named <code>tearMeDown()</code>. In this case you are going to mark the function with an <code>[After]</code> metadata tag. This function will set the class <code>circle</code> variable to null.</p> 
+
+		<code><pre>[After]
+public function tearMeDown():void {
+	circle = null;
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Remove the <code>circle</code> variable instantiations from each of the test methods. Using the first test as a model:</p>
+
+		<code><pre>[Test]
+public function shouldReturnProvidedRadius():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	assertEquals( 5, circle.radius );
+}		</pre></code>
+		
+		<p>Becomes:</p>
+		
+		<code><pre>[Test]
+public function shouldReturnProvidedRadius():void {
+	assertEquals( 5, circle.radius );
+}		</pre></code>
+		
+		<h3><br />Running the test case</h3>
+	
+	</li>
+	<li>
+		<p>After the instantiations have been removed, the test class should read as follows:</p>
+
+		<code><pre>public class BasicCircleTest {	
+	private static const TOLERANCE:Number = .0001;
+	private var circle:Circle;
+
+	[Before]
+	public function setMeUp():void {
+		circle = new Circle( new Point( 0, 0 ), 5 );
+	}
+
+	[After]
+	public function tearMeDown():void {
+		circle = null;
+	}
+
+	[Test]
+	public function shouldReturnProvidedRadius():void {
+		assertEquals( 5, circle.radius );
+	}
+
+	[Test]
+	public function shouldComputeCorrectDiameter():void {
+		assertEquals( 10, circle.diameter );
+	}
+
+	[Test]
+	public function shouldReturnProvidedOrigin():void {
+		assertEquals( 0, circle.origin.x );
+		assertEquals( 0, circle.origin.y );
+	}
+
+	[Test]
+	public function shouldReturnTrueForEqualCircle():void {
+		var circle2:Circle = new Circle( new Point( 0, 0 ), 5 );
+		
+		assertTrue( circle.equals( circle2 ) );
+	}
+
+	[Test]
+	public function shouldReturnFalseForUnequalOrigin():void {
+		var circle2:Circle = new Circle( new Point( 0, 5 ), 5);
+		
+		assertFalse( circle.equals( circle2 ) );
+	}
+
+	[Test]
+	public function shouldReturnFalseForUnequalRadius():void {
+		var circle2:Circle = new Circle( new Point( 0, 0 ), 7);
+		
+		assertFalse( circle.equals( circle2 ) );
+	}
+
+	[Test]
+	public function shouldGetTopPointOnCircle():void {
+		var point:Point = circle.getPointOnCircle( 0 );
+		
+		assertThat( point, new CloseToPointMatcher ( new Point( 5, 0 ), TOLERANCE ) );
+	}
+
+	[Test]
+	public function shouldGetBottomPointOnCircle():void {
+		var point:Point = circle.getPointOnCircle( Math.PI );
+		
+		assertThat( point, new CloseToPointMatcher ( new Point( -5, 0 ), TOLERANCE ) );
+	}
+
+	[Test]
+	public function shouldGetRightPointOnCircle():void {
+		var point:Point = circle.getPointOnCircle( Math.PI/2 );
+		
+		assertThat( point, new CloseToPointMatcher ( new Point( 0, 5 ), TOLERANCE ) );
+	}
+
+	[Test]
+	public function shouldGetLeftPointOnCircle():void {
+		var point:Point = circle.getPointOnCircle( (3*Math.PI)/2 );
+		
+		assertThat( point, new CloseToPointMatcher ( new Point( 0, -5 ), TOLERANCE ) );
+	}
+
+	[Test(expects="RangeError")]
+	public function shouldThrowRangeError():void {
+		var someCircle:Circle = new Circle( new Point( 10, 10 ), -5 );
+	}
+}		</pre></code>
+
+		<p>Other circles, such as <code>circle2</code> are still instantiated in its respective methods, because it is unique in each case.</p>
+	</li>
+	<li>
+		<p>Save BasicCircleTest.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/unit6/image1.png' />
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Understanding Before as an indication of cohesion</h2>
+
+<p>In general, it is a good practice to group similar tests together. One advantage gained by using Before and After methods is that it quickly becomes apparent when tests do not share the same test fixture.</p> 
+<p>If you find yourself with methods that need significantly different setup, or are not using much of the setup created in the Before methods, then it is likely that your tests are grouped in a way that is not particularly cohesive.</p> 
+<p>If your methods successfully share the test fixture, then each new method added to a case requires less duplicate code and hence less effort. Ideally, your tests become a line or two of code and an assertion.</p>
+
+<h2>The importance of cleaning up the fixture</h2>
+
+<p>Methods marked with <code>[After]</code> are generally intended to mirror the instantiations or creations of the <code>[Before]</code> method. They are responsible for destroying the test fixture to ensure open connections are closed, references and listeners are removed, and objects are made available for garbage collection.</p>
+<p>Destroying the fixture correctly lowers the overhead of the test run by ensuring memory leaks are resolved and objects are appropriately collected. Left uncollected during large test runs, this additional overhead can become significant quickly.</p>
+
+<h2>BeforeClass and AfterClass Metadata</h2>
+
+<p>In rare cases, you may wish to create a portion of the test fixture that remains constant or maintains desired state across all tests. For example, perhaps each of your tests needs to read data from the same large XML file. Rather than reload and reparse this file in each of your [Begin] methods, you might decide to do this once for all tests in a given test case or suite.</p>
+<p>FlexUnit allows you to specify static methods to run before the test case (or suite) is instantiated and after the execution is complete. These methods allow you to perform operations that should only occur once per case or suite execution, as opposed to the test by test manipulation that [Before] and [After] offer.</p>
+<p>These methods, marked with [BeforeClass] and [AfterClass] metadata, are often used to facilitate tests that connect to a live system, such as a database. However, it is important to note a few pitfalls of this approach.</p> 
+<p>First, as soon as you use BeforeClass or AfterClass, your tests are no longer completely independent of each other. A side effect of one test has the potential to manipulate the test fixture, creating a situation where the order of tests now influences their success or failure. Therefore, it is best to try to limit items created in BeforeClass to items that will be consumed or read and avoid items which will be manipulated in any way.</p>
+<p>Second, if you do find yourself heavily relying upon items created in this way, you may have moved into the territory of integration tests and away from unit tests. Remember, a unit is the smallest piece of testable code. The combination of your code, the network stack, an application server, a database connection, and a database server rarely qualifies.</p>
+<p>As items created in BeforeClass are created before the test case constructor is called, they must be static. Unlike items created in Before which have the possibility of being garbage collected, these static items will not. Therefore, the cleanup performed by the AfterClass methods is extremely important.</p>
+<p>Static functions marked with [BeforeClass] and [AfterClass] can exist on a test case or a test suite and are run once per execution. The method execution of a three-test hierarchy is illustrated below:</p>
+
+<code><pre>[BeforeClass]
+	[Before]
+		[Test]
+	[After] 
+	[Before]
+		[Test]
+	[After] 
+	[Before]
+		[Test]
+	[After] 
+[AfterClass]</pre></code>
+
+<h2>Walkthrough 2: Using BeforeClass and AfterClass</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Use <code>[BeforeClass]</code> and <code>[AfterClass]</code> to demonstrate test hierarchy.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the BasicCircleTest.as file from 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_wt2.fxp project from the Unit 6/start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Using [BeforeClass] &#38; [AfterClass] metadata</h3>
+		
+	</li>
+	<li>
+		<p>Declare a public static function named <code>setUpClass()</code>, mark it with <code>[BeforeClass]</code> metadata. In the function body, add a trace statement that merely states "Before Class."</p>
+
+		<code><pre>[BeforeClass]
+public static function setUpClass():void {
+	trace( "Before Class" );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Similarly, declare another public static function named <code>tearDownClass()</code>, mark it with <code>[AfterClass]</code> metadata.</p> 
+
+		<code><pre>[AfterClass]
+public static function tearDownClass():void {
+	trace( "After Class" );
+}		</pre></code>
+		
+		<h3><br />Visualizing test order</h3>
+		
+	</li>
+	<li>
+		<p>A similar trace statement should be added to the existing <code>setMeUp()</code> and <code>tearMeDown()</code> methods.</p>
+
+		<code><pre>[Before]
+public function setMeUp():void {
+	circle = new Circle( new Point( 0, 0 ), 5 );
+	trace( "Before Test" );
+}
+
+[After]
+public function tearMeDown():void {
+	circle = null;
+	trace( "After Test" );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Finally, add a trace statement to every test method on the first line.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnProvidedRadius():void {
+	trace( "Test" );
+	assertEquals( 5, circle.radius );
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Save BasicCircleTest.as</p>
+	</li>
+	<li>
+		<p>Run FlexUnit4Training.mxml file in Debug Mode.</p> 
+
+ 		<img alt='DebugMode' id='shift' src='../images/unit6/image2.png' />
+		<p class='caption' id='shift'>Figure 1: Running in Debug Mode</p>
+	</li>
+	<li>
+		<p>Nothing is going to change about how the tests display in the browser, in this walkthrough we are interested in Flash Builder's Console View, which is usually located at the bottom of the screen.</p>
+
+		<img alt='ConsoleTab' id='shift' src='../images/unit6/image3.png' />
+		<p class='caption' id='shift'>Figure 2: Console in the tab navigator</p>
+	</li>
+	<li>
+		<p>Take a look at the console view; if all the functions ran to completion, you should see the following show up in order.</p>
+		
+		<code><pre>
+Before Class
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+Before Test
+Test
+After Test
+After Class
+		</pre></code>
+		
+	</li>
+	<li>
+		<p>Based on the exhibited call hierarchy, you should be able to tell that the <code>setUpClass()</code> and <code>tearDownClass()</code> functions are being called before the first test method and after the last. Meanwhile, the <code>setMeUp()</code> and <code>tearMeDown()</code> methods are being called respectively before and after every test.</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>Test fixture metadata:</p></li>
+	<ul>
+		<li><p>[Before], marks a method that runs before each test.</p></li>
+		<li><p>[After], marks a method that runs after each test.</p></li>
+		<li><p>[BeforeClass], marks a method that is run before the test case or suite is created and run.</p></li>
+		<li><p>[AfterClass], marks a method that is run after the test case or suite has run completely.</p></li>
+	</ul>
+	<li><p>[Before] and [BeforeClass] methods can indicate test case cohesion, because tests should be grouped together based on their similarity.</p></li>
+	<li><p>[After] and [AfterClass] methods are useful for cleaning up the fixture and minimizing overhead.</p></li>
+	<li><p>These methods, when used correctly, allow you to factor duplicated code out of the test methods.</p></li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-7.html" class="next"></a>
+			<a href="Unit-5.html" class="prev"></a>
+			<a href="../flexunit.html" class="indexbutton"></a>
+		</div>
+				
+	</div>
+	
+
+</body>
+</html>
\ No newline at end of file

Added: flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-7.html
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-7.html?rev=1579527&view=auto
==============================================================================
--- flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-7.html (added)
+++ flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-7.html Thu Mar 20 03:54:59 2014
@@ -0,0 +1,337 @@
+<!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>Using Suites</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/unit7.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 7 - Using Suites</h1>
+
+<p>As you learned in the last unit, test cases are groups of tests which share a common test fixture. Inherently this means as the number of tests in any project grows, there will become a need for a significant number of test cases which needed to organized and executed.</p>
+<p>Suites are the organizational tool used to establish a reasonable scheme for organizing these test cases, allowing you to create a hierarchy of tests that can be executed as one object.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Create new test case files</li>
+	<li>Create new test suite files</li>
+	<li>Apply [RunWith] metadata in test suites</li>
+	<li>Refactor existing cases for better organization and hierarchy</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Writing test suites</li>
+	<li>Creating a suite</li>
+	<li>Refactoring test cases within suites</li>
+	<li>Understanding hierarchy and test result reporting</li>
+	<li>Discuss directory structure and approach for new projects</li>
+</ul>
+
+<h2>Writing test suites</h2>
+
+<p>In previous lessons, we have run several test methods, but they have always been contained within a single test case. Given the nature of test fixtures, almost any project is going to require more than a single test case. Many production applications run thousands of different tests, which may make up hundreds of different cases. Remembering the functions in each test case and knowing which to run in a given situation would be difficult, if not impossible.</p>
+<p>To keep all of our test cases organized, and to allow us to run these tests as a group, we use a special type of class called a Suite. A test suite is primarily a collection of test cases that will be executed together. To allow further organization and a hierarchical organization, a suite may also contain other suites.</p>
+<p>The suite runner is org.flexunit.runners.Suite. This runner interrogates a class looking for each public variable. It determines the type (Class) of the variable and attempts to run that class.</p>
+<p>While it is possible to sort the order of suites and test cases, by default the order in which they execute is indeterminate and not governed by the order of their definition in the suite class.</p>
+
+<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class SampleSuite {
+	public var testCase:TestCase;
+	public var anotherTestCase:AnotherTestCase;
+	public var yetAnotherTestCase:YetAnotherTestCase;
+	public var anotherSuite:AnotherSuite;
+}</pre></code>
+
+<h2>Walkthrough 1: Creating a new case for the Constructor Test</h2>
+
+<p>In this walkthrough you will reorganize your test cases and prepare to create a new suite. You will perform the following tasks:</p>
+<ul>
+	<li>Create a new case named CircleConstructorTest.</li>
+	<li>Move the <code>shouldThrowRangeError()</code> method out of the BasicCircleTest case into the CircleConstructorTest case.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the BasicCircleTest.as file from the previous exercise.</p>
+	</li>
+	<li>
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training_wt1.fxp project from the Unit 7/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+		
+		<h3><br />Creating the CircleConstructorTest.as file</h3>
+		
+	</li>
+	<li>
+		<p>In Flash Builder's Package Explorer, select the math.testcases package in which your BasicCircleTest.as file is located. Right click on the package and select New &#62; ActionScript Class as shown below:</p>
+
+		<img alt='PackageExplorer' id='shift' src='../images/unit7/image1.png' />
+		<p class='caption' id='shift'>Figure 1: Package Explorer, creating new objects</p>
+	</li>
+	<li>
+		<p>Set the Package to math.testcases and the Name to CircleConstructorTest, and leave all other fields with the defaults. Click Finish to create the file.</p>
+
+		<img alt='NewActionScriptClass' id='shift' src='../images/unit7/image2.png' /> 
+		<p class='caption' id='shift'>Figure 2: New ActionScript Class window</p>
+	</li>
+	<li>
+		<p>Remove the automatically created constructor from the new ActionScript class, so that it reads as shown.</p>
+
+		<code><pre>package math.testcases {
+	public class CircleConstructorTest {		
+	}
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Highlight and cut the <code>shouldThrowRangeError()</code> method from the BasicCircleTest.as file and paste it into the CircleConstructorTest class.</p>
+
+		<code><pre>public class CircleConstructorTest {		
+	[Test(expects="RangeError")]
+	public function shouldThrowRangeError():void {
+		trace("Test");
+		var someCircle:Circle = 
+			new Circle( new Point( 10, 10 ), -5 );
+	}
+}
+		</pre></code>
+		
+		<p>Because you cut and pasted the above function into a new class you will need to manually add the appropriate import statements.</p>
+	</li>
+	<li>
+		<p>Add the import statements for <code>flash.geom.Point</code> and <code>net.digitalprimates.math.Circle</code> to the class.</p>
+	</li>
+	<li>
+		<p>Remove the line that reads <code>trace("Test");</code> from the <code>shouldThrowRangeError()</code> method.</p>
+	</li>
+	<li>
+		<p>Save the CircleConstructorTest.as and the BasicCircleTest.as files.</p>
+
+		<code><pre>package flexUnitTests.cases {
+	import flash.geom.Point;
+	
+	import net.digitalprimates.math.Circle;
+
+	public class CircleConstructorTest {
+		[Test(expects="RangeError")]
+		public function shouldThrowRangeError():void {
+			var someCircle:Circle = 
+                          new Circle( new Point( 10, 10 ), -5 );
+		}
+	}
+}		</pre></code>
+
+	</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='FlexUnitTestsPassed' id='shift' src='../images/unit7/image3.png' /> 
+		<p class='caption' id='shift'>Figure 3: FlexUnit tests passed</p>
+		
+		<p>Notice that only ten tests were run. Although CircleConstructorTest case has been created, the test runner is unaware of the new test case, and therefore it does not run. In the FlexUnit4Training.mxml, which was generated by Flash Builder, the BasicCircleTest case is the only set of tests pushed into the <code>testsToRun</code> array.</p> 
+		<p>In Walkthrough 2, you will create a test suite in order to run both test cases as well as others you will create.</p>
+	</li>
+</ol>
+
+<h2>Creating a suite</h2>
+
+<p>Suites are simply ActionScript class files with public properties. The class is decorated with two very important pieces of metadata. First, the [Suite] tag, which tells Flash Builder and FlexUnit that this class is intended to be a test suite.</p> 
+<p>Second, the [RunWith] metadata tells FlexUnit to use the org.flexunit.runners.Suite class to execute this class. You will learn more about extensibility and the [RunWith] metadata later in this unit.</p>
+
+<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class mySuite</pre></code>
+
+<h3>Test cases within suites</h3>
+
+<p>Within a test suite, all the test cases and other suites are represented by public properties within the class. The sample suite below includes three test cases and additional suite.</p>
+
+<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class MySuite {
+	public var testCase:TestCase;
+	public var anotherTestCase:AnotherTestCase;
+	public var yetAnotherTestCase:YetAnotherTestCase;
+	public var anotherSuite:AnotherSuite;
+}</pre></code>
+
+<p>The <code>anotherSuite</code> variable is another suite that can contain any number of tests and suites. There is no limit to the hierarchy of test suites and each level of suite is only aware of its immediate children</p>	
+<p>An empty suite (one with no tests or no public tests or suites) will throw an <code>InitializationError</code>.</p>
+
+<h2>Understanding the RunWith metadata</h2>
+
+<p>A primary goal of FlexUnit was extensibility based on unknown future requirements. While FlexUnit 4 natively includes support for FlexUnit 4.x, FlexUnit .9 and Fluint 1.0 style tests, it was imperative to provide developers an easy way to accommodate new functionality without restricting their freedom to FlexUnit's concept of a test. The [RunWith] metadata is one of the primary means of accomplishing this goal.</p>
+<p>When the [RunWith] metadata is used on a class file, it overrides all internal logic that FlexUnit uses to determine the appropriate type of test. Instead it specifies a class that implements the IRunner interface which should be used to execute the contents of this file.</p>
+<p>FlexUnit simply instantiates the specified runner and hands over all control until the runner is complete. In this way new test runners can be developed that act and work in radically different ways than the standard components but will integrate cleanly and easily.</p>
+<p>The suite runner uses this technique to create test suites. As you have seen so far, the standard FlexUnit runner looks for methods marked with the [Test] metadata and executes each. However, suites are radically different. They are simply a class of properties wherein the type specifies the case or suite. In this case the [RunWith] metadata indicates that the Suite class understands how to execute the contents of this class, facilitating the concept of suites.</p>
+<p>At every level of test, FlexUnit re-performs this same logic. This means that different cases and suites can use different runners while all co-existing in the same project and top-level suite.</p>
+<p>Support for new testing environments can be added by creating new custom runners and using the [RunWith] metadata with the new runner. The suite runner is only one example of the provided runners with FlexUnit 4.x.</p>
+
+<h2>Walkthrough 2: Creating a Test Suite</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create a test suite to run the two test cases for the Circle class.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the testcases package from 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_wt2.fxp project from the Unit 7/ Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+		
+		<h3><br />Create a test suite</h3>
+		
+	</li>
+	<li>
+		<p>Create an ActionScript class named CircleSuite in the testcases package. Do not specify a superclass or interfaces.</p> 
+		<p>The Package Explorer should look like this after the suite has been created:</p>
+
+		<img alt='PackageDirectoryStructure' id='shift' src='../images/unit7/image4.png' />
+		<p class='caption' id='shift'>Figure 1: Package directory structure after the suite has been created</p>	
+	</li>
+	<li>
+		<p>Remove the automatically created constructor from the new ActionScript class. Mark the class with <code>[Suite]</code> and <code>[RunWith(" org.flexunit.runners.Suite")]</code> metadata tags, which should be placed above the class declaration.</p>
+
+		<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class CircleSuite {
+...
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a public variable named <code>test1</code> of type <code>BasicCircleTest</code> and another public variable named <code>test2</code> of type <code>CircleConstructorTest</code> to the class.</p>
+
+		<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class CircleSuite {
+	public var test1:BasicCircleTest;
+	public var test2:CircleConstructorTest;
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Open the FlexUnit4Training.mxml file.</p>
+	</li>
+	<li>
+		<p>Look under the <code>&#60;fx:Script&#62;</code> block.</p>
+		<p>Replace this line:</p>
+		<code><pre>testsToRun.push( BasicCircleTest );</pre></code>
+		<p>with this line:</p>
+		<code><pre>testsToRun.push( CircleSuite );</pre></code>
+		<p>If you did not use code completion, add the import for testcases.CircleSuite at this time.</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/unit7/image5.png' /> 
+		<p class='caption' id='shift'>Figure 2: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Understanding hierarchy</h2>
+
+<p>Suites allow for the creation of a hierarchy that can be extremely useful when dealing with large projects. The nature of suites or cases would allow you to execute a particular case in the hierarchy by itself, or execute it as a part of any of the suites where it is contained within. For example, you could execute Suite 1 to run the cases beneath it, or execute Suite 0 to run all of Suite 1 plus additional cases.</p>
+<img alt='Hierarchy' src='../images/unit7/hierarchy.png' />
+<p>Test results are not organized by suite inside of Flash Builder premium, which simply sees all of the cases as a flat list. However, it does allow you to see the full package name which still provides some understanding of hierarchy.</p>
+<img alt='FlexUnitResults' src='../images/unit7/image6.png' />
+
+<h2>Possible directory structures</h2>
+
+<p>The unit test package structure for a project should mirror the suite hierarchy, which, in a perfect world, should mirror the hierarchy of the classes being tested.</p> 
+<p>While there are no rules for how to organize your test cases, the following information can be helpful.</p>
+<ol>
+	<li>Think of the organization in terms of an outline. Each topic and subtopic in the outline gets a new package, recursively.</li>
+	<ol type='a'>
+		<li>Just like an outline shouldn't get a subtopic if there is only one item inside of it, do not create a package for just one case.</li>
+		<li>Do not be afraid of making the packages deep with fewer cases in each.</li>
+	</ol>
+	<li>Each time you create a new package, the package should automatically get a test suite to organize the child cases and suites.</li>
+	<li>Avoid reach down, meaning that a Suite should only include cases in its own package.</li>
+	<li>A suite may include other suites from any package one level below.</li>
+</ol>
+<p>Take the family structure presented, for example.</p>
+<img alt='TestStructure' src='../images/unit7/image7.png' />
+<p>The test structure creates test for a nuclear family. The top level package is testcases, which contains the FamilySuite.as file. Because this application objectifies the nuclear family, the FamilySuite.as file can be arranged accordingly.</p>
+
+<code><pre>import tests.children.ChildrenSuite;
+import tests.father.FatherSuite;
+import tests.mother.MotherSuite;
+
+[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class FamilySuite {		
+	public var fatherSuite:FatherSuite;
+	public var motherSuite:MotherSuite;
+	public var childrenSuite:ChildrenSuite;
+}</pre></code>
+
+<p>This is a valid suite despite the fact that it only contains other suites and does not directly contain any test cases.</p>
+<ul> 
+	<li><p>The <code>FatherSuite</code> may include a <code>FatherCase</code>, which is a case specifically for testing the Father object, as well as cases, or other suites, to test items within the <code>tests.father.parents</code> package and the <code>tests.father.siblings</code> package.</p></li>
+	<li><p>The <code>MotherSuite</code> includes the <code>MotherCase</code> as well as those cases within the <code>tests.mother.parents</code> package, because the Mother has only one sibling, TwinSisterCase is included in the mother package.</p></li>
+	<li><p>The <code>OldestSonSuite</code> includes the <code>OldestSonCase</code> as well as the <code>WifeCase</code> and an empty package named children.</p></li>
+	<li><p>Finally <code>MiddleDaughterCase</code> and <code>YoungestDaughterCase</code> do not require a separate package or suite, because all of their family members are represented in the available test cases.</p></li>
+</ul>
+<p>The important thing to note is that the model for organization is based on the actual entity being tested. We could have easily chosen a father-centric model for organization, one where all cases and suites extend in terms of their relationship to the father. In this case, the family is being tested, and the suites and cases are organized as such.</p>
+<p>The architecture allows for naming consistency within different packages. Many families have two sets of Grandparents. Fortunately, both the father's parents and the mother's parents can use the names Grandpa.as and Grandma.as for their class files, and ParentsSuite for their suite files.</p>
+<img alt='NamingConsistency' src='../images/unit7/image8.png' />
+<p>Also, this organization allows for extensibility. The oldestson package contains an empty package named children, which we can assume is eventually going to contain test cases. If we were to include cousins, for instance, we would want to make suites for the siblings and corresponding packages for them and their children.</p>
+<img alt='EmptyChildrenPackage' src='../images/unit7/image9.png' />
+<p>Although Flash Builder makes it fairly easy to reorganize class files and directory structure, it is ideal to plan out the application ahead of time, and use a structure that brings organization and consistency to your testing.</p>
+
+<h2>Summary</h2>
+<ul>
+	<li><p>Test suites are used to run multiple FlexUnit cases or suites.</p></li>
+	<li><p>Tests should be refactored into new cases when:</p></li>
+	<ul>
+		<li><p>They require different fixture</p></li>
+		<li><p>They require different inputs (i.e. valid vs. invalid)</p></li>
+	</ul>
+	<li><p><code>[RunWith= ""]</code> metadata can be used to run suites, FlexUnit .9 tests, Fluint 1.x tests and other developer-provided runners.</p></li> 
+	<li><p>Test package hierarchy should ideally reflect the package hierarchy of the project under test.</p></li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-8.html" class="next"></a>
+			<a href="Unit-6.html" class="prev"></a>
+			<a href="../flexunit.html" class="indexbutton"></a>
+		</div>
+				
+	</div>
+	
+
+</body>
+</html>
\ No newline at end of file

Added: flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-8.html
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-8.html?rev=1579527&view=auto
==============================================================================
--- flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-8.html (added)
+++ flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-8.html Thu Mar 20 03:54:59 2014
@@ -0,0 +1,606 @@
+<!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>FlexUnit Theories</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/unit8.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 8 - FlexUnit Theories</h1>
+
+<p>Theories are a tool for testing a class against a potentially infinite set of data points. While theories are a powerful concept, they must work in conjunction with static tests to ensure proper functionality.</p> 
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Create theories</li>
+	<li>Create theory data points</li>
+	<li>Use assumptions in your theories</li>
+	<li>Use complex objects with theories</li>
+	<li>Use complex objects as data points</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Understand the use for data points</li>
+	<li>Understanding triangulation of test cases</li>
+	<li>Creating a theory</li>
+	<li>Creating data points</li>
+	<li>Understanding assumptions</li>
+	<li>Understanding the theory success and failure model</li>
+	<li>Using complex objects with theories</li>
+	<li>Using the constructor of the TestCase</li>
+</ul>
+
+<h2>Understanding triangulation of test cases</h2>
+
+<p>When testing formulas, there are a potentially infinite number of values that may be given and return an expected result. It is impossible in these cases to test all possible values that could be passed to a test case.</p> 
+<p>Testing a single case is fairly weak, because any formula could return a hard-coded value. There is very little assurance in a single trial of anything. Likewise, a single test case is just slightly better than not testing at all.</p>
+<p>If a test succeeds in two cases with two different values, already it has exponentially more assurance. If a test succeeds three or more times with three or more values, for each trial added it becomes substantially easier to trust the functionality being tested.</p> 
+<p>A small range of values is acceptable. Granted, it does not cover every case, but it does give you a substantial degree of assurance. A small range of values can also include all the types of values that could be problematic. For instance:</p>
+
+<code><pre>public function absoluteValue( value:int ):int {
+	if ( value &#60; 0 ) {
+		return value * -1;
+	} else {
+		return value;
+	}
+}</pre></code>
+
+<p>A simple method like the one presented above should be tested with at least five values: Positive integers, negative integers, 0, NaN, Infinity. That kind of small combination is fairly standard for arithmetic functions, but sometimes it becomes more complicated, particularly when float types are involved in the calculation.</p> 
+<p>While you may not be able to test every case, the more potential values that can be passed through the method to more assurance you have that the method does indeed function directly. We call this concept triangulation.</p>
+
+<h2>Understanding Theories</h2>
+
+<p>A FlexUnit theory is a method marked with the [Theory] metadata. Unlike the test methods you have worked with so far, theory methods can have parameters. Theory methods will be called multiple times with different data points, however, much like a mathematical theory; they are either valid or invalid, there is no sometimes.</p> 
+<p>Any one case that fails disproves the whole theory. Therefore any one time the theory method is called when it fails marks the entire test as a failure.</p>
+<p>A simple theory method:</p>
+
+<code><pre>[Theory]
+public function testTheory( value1:Number, value2:Number ):void</pre></code>
+
+<h2>Understanding the use case for data points</h2>
+
+<p>A test like the one in the previous section relies upon good data points to effectively triangulate. The tests you have used so far in this course have been statically coded and passed values to test for functionality. While that works for a small number of tests, it becomes increasingly more difficult to write and maintain as the number of tests and data points grow.</p>
+<p>When attempting to triangulate a method, you need to be able to quickly create and add to a vast set of data points which will be provided to the test. In FlexUnit 4.x two special metadata tags named [DataPoint] and [DataPoints] can decorate data to indicate that it should be provided to the available tests as potential data points.</p>
+
+<h2>Creating data points</h2>
+
+<p>A data point is a single variable, or function that returns a value, which will be passed as an argument to a test for testing. A data point:</p>
+<ul>
+	<li>Must be defined as static</li>
+	<li>Can be coded statically or be the result of a static method call</li>
+</ul>
+<p>For Instance:</p>
+
+<code><pre>[DataPoint]
+public static var value1:int = 10;</pre></code>
+
+<p>Data points are an array of variables, or a function that returns an array, used as arguments to a theory. Data points allow you to quickly specify many values that will be passed to a single theory.</p>
+<ul>
+	<li>In addition to being decorated with the <code>[DataPoints]</code> metadata, must be decorated with <code>[ArrayElementType("TYPE")]</code> specifying the type of the array elements.</li>
+	<li>Must be static</li>
+	<li>Can be coded statically or be the result of a static method call</li>
+</ul>
+<p>For instance:</p>
+
+<code><pre>[DataPoints]
+[ArrayElementType("String")]
+public static var stringValues:Array = ["one","two","three" ];</pre></code>
+
+<p>The ArrayElementType metadata describes the type of data in the Array to the theories in this class.</p>
+
+<h2>Creating theories</h2>
+
+<p>Theories are written to test a small function or calculation over a potentially large set of data. Using theories with a range of data, you build assurance that the theory is actually performing the calculation as opposed to just returning the expected result.</p>
+<p>Some notes on theories:</p>
+<ul>
+	<li>They are decorated with the <code>[Theory]</code> metadata</li>
+	<li>They can take parameters</li>
+	<li>Accepts parameters marked with <code>[DataPoint]</code> and <code>[DataPoints]</code> metadata</li>
+	<li>They run with a special Theory runner</li>
+</ul>
+
+<code><pre>[RunWith("org.flexunit.experimental.theories.Theories")]
+public class MyTheoryTest {
+}</pre></code>
+
+<p>Theories run with all matching data points. If any combination of <code>Datapoints</code> fail, the theory fails.</p> 
+
+<code><pre>[DataPoints]
+[ArrayElementType("Number")]
+public static var radii:Array = [ 1, 2, 3, 4 ];
+
+[Theory]
+public function testTheory( value1:Number, value2:Number ):void</pre></code>
+
+<p>This theory takes two parameters. All <code>Datapoints</code> referenced with the data type integer will be passed into each of these values for every possible combination.</p> 
+<p>Test process:</p>
+
+<code><pre>testTheory( 1, 1 )
+testTheory( 1, 2 )
+testTheory( 1, 3 )
+...
+testTheory( 4, 3 )
+testTheory( 4, 4 )</pre></code>
+
+<h2>Discussion on data typing and conversion</h2>
+
+<p>Marking data points with the <code>[ArrayElementType("Type")]</code> metadata ensures that only the desired input type is contained within the collection. Additionally, it makes sure that these values are passed in wherever a parameter of the specified type is used in a theory.</p>
+<p>The following theory takes two number inputs and a string, but there is only a single collection of numbers and a single collection of strings within the class.</p>
+
+<code><pre>[DataPoints]
+[ArrayElementType("Number")]
+public static var numbers:Array = [ 1, 2, 3, 4, 5 ];
+
+[DataPoints]
+[ArrayElementType("String")]
+public static var strings:Array = [ "Mike", "Tom", "Bob", "Cindy" ];
+
+[Theory]
+public function testNamesAndNumbers( name:String, numberOne:Number, numberTwo:Number ):void {
+	assertTrue( name.length > 0 );
+	assertTrue( numberOne > 0 );
+	assertTrue( numberTwo > 0 );
+	assertTrue( numberOne + numberTwo > 0 );
+	assertTrue( numberOne + numberTwo + name.length > 0 );
+}</pre></code>
+
+<p>Numbers from the number array are used in the numberOne and numberTwo parameters, and the array of strings is used for the name parameter. The theory runs with all possible input combinations.</p>
+
+<code><pre>testNamesAndNumbers( "Mike", 1, 1 )
+testNamesAndNumbers( "Mike", 1, 2 ) 
+testNamesAndNumbers( "Mike", 1, 3 ) 
+...
+testNamesAndNumbers( "Cindy", 5, 4 ) 
+testNamesAndNumbers( "Cindy", 5, 5 )</pre></code>
+
+<h2>Walkthrough 1: Creating a Circle Theory</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create a new theory case for the Circle class.</li>
+	<li>Create a new theory to test Circle radii.</li>
+	<li>Create an array of parameterized data.</li>
+	<li>Add the CircleTheory case to the CircleSuite.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Select the math.testcases package from the previous exercise. Create a new class in the math.testcases package named CircleTheory.as. This class has no superclass or interfaces.</p>
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training_wt1.fxp project from the Unit 8/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Create the CircleTheory class</h3>
+		
+		<p>After the class has been created, the package directory should appear as follows:</p>
+
+		<img alt='PackageDeliveryStructure' id='shift' src='../images/unit8/image1.png' />
+		<p class='caption' id='shift'>Figure 1: Package directory structure</p>
+	</li>
+	<li>
+		<p>Mark the new class with <code>[RunWith("org.flexunit.experimental.theories.Theories")]</code> metadata, which should be placed just above the class definition.</p>
+
+		<code><pre>[RunWith("org.flexunit.experimental.theories.Theories")]
+public class CircleTheory {
+...
+}		</pre></code>
+		
+		<h3><br />Creating theories</h3>
+		
+	</li>
+	<li>
+		<p>Create a new public function named <code>shouldShowAllRadiiEqual()</code> with a parameter named <code>radius</code> of data type <code>Number</code>. Mark the function with <code>[Theory]</code> metadata:</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllRadiiEqual( radius:Number ):void {
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a variable named <code>circle</code> of type <code>Circle</code> to the <code>shouldShowAllRadiiEqual()</code> method. Instantiate circle with an origin at <code>(0, 0)</code> and the <code>radius</code> parameter passed in as its radius.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllRadiiEqual( radius:Number ):void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), radius );
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the imports for net.digitalprimates.math.Circle and flash.geom.Point at this time.</p> 
+	</li>
+	<li>
+		<p>Add a call to the <code>assertEquals()</code> method. Assert that the <code>circle.radius</code> is equal to the <code>radius</code> parameter.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllRadiiEqual( radius:Number ):void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), radius );
+	assertEquals( radius, circle.radius );
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add an import for org.flexunit.asserts.assertEquals at this time.</p>
+	</li>
+	<li>
+		<p>Add a public static array to the class. Fill it with a variety of positive integer values. Here is an example:</p>
+
+		<code><pre>public static var radii:Array = [ 1,2,3,4,5,6,7,8,9,10 ];</pre></code>
+		
+	</li>
+	<li>
+		<p>Mark the array with two lines of metadata, <code>[DataPoints]</code> and <code>[ArrayElementType("Number")]</code>.</p>
+
+		<code><pre>[DataPoints]
+[ArrayElementType("Number")]
+public static var radii:Array = [ 1,2,3,4,5,6,7,8,9,10 ];</pre></code>
+
+	</li>
+	<li>
+		<p>Save CircleTheory.as.</p>
+		
+		<h3><br />Adding theories to your test suite</h3>
+			
+	</li>
+	<li>
+		<p>Open the CircleSuite.as file within the math.testcases package. Add a new public variable named <code>test3</code> with a type of <code>CircleTheory</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;
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the import for math.testcases.CircleTheory at this time.</p>
+	</li>
+	<li>
+		<p>Save the CircleSuite.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='12UnitsPassed' id='shift' src='../images/unit8/image2.png' /> 
+		<p class='caption' id='shift'>Figure 2: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Understanding Assumptions</h2>
+
+<p>Assumptions are used in conjunction with theories to limit acceptable data points. Assumptions allow theories to setup basic constraints and limitations for the methods and formulae being tested.</p> 
+<p>Some notes on assumptions:</p>
+<ul>
+	<li>Assumptions use Hamcrest matchers</li>
+	<li>If an assumption fails, the theory will advance to the next set of data points</li>
+	<li>If no <code>Datapoint</code> sets pass the assumptions the test is marked as a failure</li>
+	<li>Assumptions still require an assert or expectation that tests the result</li>
+	<li>For instance</li>
+</ul>
+
+<code><pre>assumeThat( value, greaterThan(0) );</pre></code>
+
+<p>If the parameter is greater than 0, the assumption passes and the test moves onto its next line. If the parameter value is not greater than 0 the assumption fails and the runner will move on to the next data point without running any other lines of this test. Even though the assumption fails for values under 0, the test does not fail or throw an error, because those data points have been essentially marked as invalid for the test theory.</p>
+
+<h2>Walkthrough 2: Adding an assumption</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Add invalid data to theory parameters.</li>
+	<li>Create an assumption that handles invalid data.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the CircleTheory.as file from 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_wt2.fxp project from the Unit8/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Adding invalid values to your data points</h3>	
+		
+	</li>
+	<li>
+		<p>Add a single negative value to the beginning of the class's radii array. Here is an example:</p>
+		
+		<code><pre>public static var radii:Array = [ -5,1,2,3,4,5,6,7,8,9,10 ];</pre></code>
+				
+	</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='SingleFailure' id='shift' src='../images/unit8/image3.png' /> 
+		<p class='caption' id='shift'>Figure 1: A single test failure</p>
+		
+		<p>The theory failed because -5 is an invalid radius for a Circle object. If one of the theories assertions fails, the entire theory fails.</p> 
+
+		<h3><br />Adding an assumption</h3>
+		
+	</li>
+	<li>
+		<p>Add a new line to the <code>shouldShowAllRadiiEqual()</code> method. On the line, add an assumption indicating that this test only works for positive radii. The method should read as follows:</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllRadiiEqual( radius:Number ):void {
+	assumeThat( radius, greaterThan( 0 ) );
+	var circle:Circle = new Circle( new Point( 0, 0 ), radius );
+	assertEquals( radius, circle.radius );
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the import statements for org.flexunit.assumeThat and org.hamcrest.number.greaterThan at this time.</p>
+	</li>
+	<li>
+		<p>Save the CircleTheory.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/unit8/image4.png' />
+		<p class='caption' id='shift'>Figure 2: FlexUnit tests passed</p>
+		
+		<p>The <code>assumeThat( radius, greaterThan( 0 ) )</code> statement assures that the theory is only testing radii that are valid, or in this case, positive. The theory ignores the -5 input and all negative inputs thanks to this statement.</p>
+	</li>
+</ol>
+
+<h2>Using complex objects with theories</h2>
+
+<p>FlexUnit 4 theories include support for complex objects as data points. Because ActionScript uses so many complex objects, it's not uncommon to have them passed as arguments in tests and theories. Theories are much more useful given the ability to deal with complex data points.</p> 
+<p>Some notes on complex data points:</p>
+<ul>
+	<li>To use a complex object as data, simply specify it as the <code>ArrayElementType</code> in the <code>DataPoints</code></li>
+	<li>The <code>ArrayElementType</code> requires the full class path for the type, such as <code>flash.geom.Point</code> or <code>mx.collections.ArrayCollection</code>.</li>
+</ul>
+<p>For Instance:</p>
+
+<code><pre>[DataPoints]
+[ArrayElementType("flash.geom.Point")]
+Public static var points:Array = [ new Point( 0, 0 ) ];</pre></code>
+
+<h2>Using the constructor of the Theory Case</h2>
+
+<p>Theory case constructors can be used like the constructors of many classes. In test cases and theories, constructors can be passed initial data for use by all or some of the methods within the class. For instance:</p>
+
+<code><pre>public class TestCase {
+
+	[DataPoints]
+	[ArrayElementType("flash.geom.Point")]
+	public static var points:Array = [ new Point( 0, 0 ),
+					new Point( 10, 10 ),
+					new Point( -5, 5 ) ];
+
+	[DataPoints]
+	[ArrayElementType("Number")]
+	public static var radii:Array = [ 0, 5, 10 ];
+
+	public static var circle:Circle;
+
+	public function TestCase( origin:Point, radius:Number ):void {
+		circle = new Circle( origin, radius );
+	}
+	...
+}</pre></code>
+
+<p>This method can help to reduce the complexity of the created complex objects, or it can serve to convert existing sets of data points into use within other complex objects.</p> 
+<p>If the complex objects are passed to the class constructor, they no longer need to be passed in as arguments to the theories. The constructor will be run before each test or theory in the case. Each test method can then use the newly instantiated class variables, which will be re-instantiated before each test is run.</p> 
+<p>In this way, the class tends to be more cohesive and about a specific set of data rather than a free for all of unrelated theories working on data points.</p>
+
+<h2>Walkthrough 3: Using Complex Objects as DataPoints</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create a new theory for testing point distance.</li>
+	<li>Pass Point objects into CircleTheory as DataPoints.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the CircleTheory.as file from 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 Unit8/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Create a method for testing points on the circle</h3>
+	</li>
+	<li>
+		<p>Add a private static constant named <code>TOLERANCE</code> of data type <code>Number</code> to the CircleTheory class.</p>
+		<code><pre>private static const TOLERANCE:Number = .0001;</pre></code>
+	</li>
+	<li>
+		<p>Add a new method named <code>shouldShowAllPointsEqual()</code> to the class.</p> 
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual(origin:Point):void {
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Create a new circle with the function's origin argument and a radius of 10.</p> 
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual(origin:Point):void {
+	var circle:Circle = new Circle(origin, 10);
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Call the <code>circle.getPointOnCircle()</code> method with argument <code>Math.PI</code>.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual( origin:Point ):void {
+	var circle:Circle = new Circle( origin, 10 );
+	var pointOnCircle:Point = circle.getPointOnCircle( Math.PI );
+}		</pre></code>
+	
+	</li>
+	<li>
+		<p>Declare a variable named <code>distance</code> of data type <code>Number</code> within the <code>shouldShowAllPointsEqual()</code> method. Instantiate it to <code>Point.distance( origin, pointOnCircle )</code>.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual( origin:Point ):void {
+	var circle:Circle = new Circle( origin, 10 );
+	var pointOnCircle:Point = circle.getPointOnCircle( Math.PI );
+	var distance:Number = Point.distance( origin, pointOnCircle );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a call to the <code>assertThat()</code> method. It should assert that <code>distance</code> variable is <code>closeTo( circle.radius, TOLERANCE )</code>.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual( origin:Point ):void {
+	var circle:Circle = new Circle( origin, 10 );
+	var pointOnCircle:Point = circle.getPointOnCircle( Math.PI );
+	var distance:Number = Point.distance( origin, pointOnCircle );
+
+	assertThat( distance, closeTo( circle.radius, TOLERANCE ) );
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the imports for org.flexunit.assertThat and org.hamcrest.number.closeTo at this time.</p>
+	</li>
+	<li>
+		<p>Add a new public static array named <code>points</code> to the class. Initialize the array with six point values, representing a gamut of potential points.</p> 
+
+		<code><pre>public static var points:Array = [ new Point( 0, 0 ),
+					new Point( 10, 10 ),
+					new Point( -5, 5 ),
+					new Point( 20, -20 ),
+					new Point( -17, -16 ),
+					new Point( 5.2, -11.3 ) ];</pre></code>
+		
+	</li>
+	<li>
+		<p>Mark the array with <code>[DataPoints]</code> and <code>[ArrayElementType("flash.geom.Point")]</code> metadata. Place these tags on the two lines above the array:</p>
+
+		<code><pre>[DataPoints]
+[ArrayElementType("flash.geom.Point")]
+public static var points:Array = [ new Point( 0, 0 ),
+					new Point( 10, 10 ),
+					new Point( -5, 5 ),
+					new Point( 20, -20 ),
+					new Point( -17, -16 ),
+					new Point( 5.2, -11.3 ) ];</pre></code>
+					
+	</li>
+	<li>
+		<p>Save CircleTheory.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/unit8/image5.png' /> 
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+
+		<h3><br />Adding multiple parameters to a theory</h3>
+		
+	</li>
+	<li>
+		<p>Alter the <code>shouldShowAllPointsEqual()</code> method to accept a second parameter named <code>radius</code> of data type <code>Number</code>. The <code>radius</code> parameter will be passed to the circle constructor. You will need to add an <code>assumeThat( radius, greaterThan(0) );</code> statement to the first line of the <code>shouldShowAllPointsEqual()</code> method.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual( origin:Point, radius:Number ):void {
+	assumeThat( radius, greaterThan( 0 ) );
+	var circle:Circle = new Circle( origin, radius );
+	var pointOnCircle:Point = circle.getPointOnCircle( Math.PI );
+
+	var distance:Number = Point.distance( origin, pointOnCircle );
+
+	assertThat( distance, closeTo( circle.radius, TOLERANCE ) );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save CircleTheory.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/unit8/image5.png' />
+		<p class='caption' id='shift'>Figure 2: FlexUnit tests passed</p>
+		
+		<p>Because the <code>shouldShowAllRadiiEqual()</code> theory passes by constructing valid Circle objects with radius parameters from the radii array, it should be no surprise that the <code>shouldShowAllPointsEqual()</code> method passes using those data points.</p>
+		<p>Valid data points should be consistent for all theories.</p> 
+
+		<h3><br />Add a radians parameter to the test method</h3>
+	</li>
+	<li>
+		<p>Re-Open to the CircleTheory.as file.</p>
+	</li>
+	<li>
+		<p>Add a parameter to the <code>shouldShowAllPointsEqual()</code> method named <code>radians</code> of data type <code>Number</code>. Alter the <code>circle.getPointOnCircle()</code> method so that it takes <code>radians</code> as its arguments.</p>
+
+		<code><pre>[Theory]
+public function shouldShowAllPointsEqual( origin:Point, radius:Number, radians:Number ):void {
+	assumeThat( radius, greaterThan( 0 ) );
+	var circle:Circle = new Circle( origin, radius );
+	var pointOnCircle:Point = circle.getPointOnCircle( radians );
+
+	var distance:Number = Point.distance( origin, pointOnCircle );
+
+	assertThat( distance, closeTo( circle.radius, TOLERANCE ) );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save CircleTheory.as</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+	</li>
+	<li>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit8/image5.png' />
+		<p class='caption' id='shift'>Figure 3: FlexUnit tests passed</p>
+		
+		<p>The <code>circle.getPointOnCircle()</code> method should return a valid point on the circle regardless of the value of the radians field. Any number within the radii array should be a valid radians argument, and therefore the theory passes with these data points.</p> 
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>Data points and theories allow many values to be tested without a great deal of complexity.</p></li>
+	<li><p>Metadata:</p></li>
+	<ul>
+		<li><p>Theory classes are marked with <code>[RunWith("org.flexunit.experimental.theories.Theories")]</code> metadata.</p></li>
+		<li><p>Single data points are marked with <code>[DataPoint]</code> metadata.</p></li>
+		<li><p>Arrays of data points are marked with <code>[DataPoints]</code> and <code>[ArrayElementType("TYPE")]</code> metadata.</p></li>
+		<li><p>Theories are marked with <code>[Theory]</code> metadata.</p></li>
+	</ul> 
+	<li><p>Theories can create a test fixture using the class constructor.</p></li>
+	<li><p>Complex objects can be passed as data points.</p></li>
+</ul>
+
+			</div>
+		
+			<div id="footnav">
+				<a href="Unit-9.html" class="next"></a>
+				<a href="Unit-7.html" class="prev"></a>
+				<a href="../flexunit.html" class="indexbutton"></a>
+			</div>
+		</div>
+	</div>
+
+</body>
+</html>
\ No newline at end of file

Added: flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-9.html
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-9.html?rev=1579527&view=auto
==============================================================================
--- flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-9.html (added)
+++ flex/site/trunk/content/flexunit/tutorial/flexunit/Unit-9.html Thu Mar 20 03:54:59 2014
@@ -0,0 +1,259 @@
+<!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>External Data</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/unit9.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 9 - External Data</h1>
+
+<p>For the sake of optimization or integration, large or complicated sets of data are often easier to manage within external files. FlexUnit 4.x provides support for external data in Theories as well as Parameterized tests, which you will learn to use in Unit 11.</p>
+ 
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Load external data points from an XML file into the FlexUnit testing environment</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Understanding asynchronous loading</li>
+	<li>Loading external data</li>
+	<li>Discussion on data typing and conversion</li>
+</ul>
+
+<h2>Understanding asynchronous loading</h2>
+
+<p>The large collections of data points that accompany theories can become increasingly difficult to maintain as the number of tests in your system grows. Additionally, in some circumstances, you may want to generate the data used for your data points in a different application or system.</p>
+<p>In these cases, you will want to switch to external data. External data has the advantage of being maintained external to the tests, making maintenance easier and increasing the legibility of test cases.</p> 
+<p>However, external data presents a particular problem in Flash-based testing. Flash is a single-threaded machine that uses asynchronous communication for all remote data access. It does not have the ability to access data synchronously nor the ability to suspend a process until data arrives.</p>
+<p>This means the test runners will need to wait for a server response before parsing the returned data into datapoints before beginning the test process.</p>  
+<p>While you could load all of the data for your system external to the testing framework before testing ever begins, you now lose some of the flexibility, or at least the performance, inherent in the ability to pick and choose test cases or suites and only load the data that is required.</p>
+<p>To resolve these issues, FlexUnit 4 offers the concept of External Dependency Loaders. An External Dependency Loader allows the loading of external data in a test.</p>
+
+<h2>Loading external data</h2>
+
+<p>As every source of data for every user of FlexUnit is slightly different, you are required to write a simple class that understands how to load and parse your test data. This class implements the IExternalDependencyLoader interface and is used to load all data into FlexUnit.</p> 
+<p>This interface has one required method: retrieveDependency(). This method returns an ExternalDependencyToken. During startup of the testing process, FlexUnit looks for IExternalDependencyLoaders and invokes this method.</p> 
+<p>Internal to this method, you are responsible for making any server calls and loading any data. Once the operation has been completed, in either a result or fault, you are responsible for notifying the framework that it is now safe to begin testing.</p>
+<p>Here is an example of the retreiveDependency function and the associated result and fault handlers that uses an HTTPService to retrieve data:</p>
+
+<code><pre>public function RadiiDataHelper( url:String ) {
+	service = new HTTPService();
+	service.url = url;
+	service.resultFormat = "e4x";
+
+	dToken = new ExternalDependencyToken();
+}
+
+public function retrieveDependency( testClass:Class ):ExternalDependencyToken {
+	var asyncToken:AsyncToken = service.send();
+	asyncToken.addResponder( this );
+
+	return dToken;
+}
+
+public function result( data:Object ):void {
+	var ar:Array = new Array();
+			
+	var list:XMLList = data.result..node;
+	var node:XML;
+			
+	for ( var i:int = 0; i &#60; list.length(); i++ ) {
+		node = list[ i ][ 0 ];
+		ar.push( Number( node.text() ) );
+	}
+			
+	dToken.notifyResult( ar );
+}
+
+public function fault(info:Object):void {
+	dToken.notifyFault( "Totally broken" );
+}</pre></code>
+
+<p>In this loader:</p>
+<ol>
+	<li><p>Loader is instantiated with a new HTTPService.</p></li>
+	<li><p>retrieveDependency() makes the external HTTP call, returning the loaders ExternalDependencyToken.</p></li>
+	<li><p>If the call is successful, the result function parses the data into an array (datapoints expect an array) and calls notifyResult() on the ExternalDependencyToken passing the datapoint array.</p></li>
+	<li><p>If the call fails, the fault function calls notifyFault() on the token, passing a useful error message.</p></li>
+	<li><p>If neither notifyResult() nor notifyFault() are called on the token the runner will stall indefinitely as it is impossible for the testing framework to identify a reasonable delay for your situation. This makes it extremely important to handle both cases.</p></li>
+</ol>
+
+<p>To use an external loader you must instantiate the loader and assign it to a public static variable in the test case. Constructor args are used to provide any additional configuration information to the loader.</p>
+<code><pre>public static var testLoader:IExternalDependencyLoader = new MyLoader(" myData.xml" );</pre></code>
+<p>You then need to create the datapoints array. However, instead of instantiating the array, as you had in previous lessons, you will specify a loader argument on the DataPoints metadata tag. The runner knows how to handle this attribute and ensure your loader is invoked.</p>
+
+<code><pre>[DataPoints(loader="testLoader")]
+[ArrayElementType("Number")]
+public static var radii:Array;</pre></code>
+
+<p>Once the data points are loaded, your test case will use them as if they were statically coded into the test case.</p>
+
+<h2>Walkthrough 1: Moving Theory Data to an External Source</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Load radii data points from an external source.</li>
+</ul>
+
+<h3>Load the external data</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnit4Training_wt1.fxp project from the Unit 9/Start folder. If you completed the previous walkthrough, choose the option to Overwrite your existing project. If this is your first Flex Unit 4 Training walkthrough, import it as a new project.  Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+		<p>The new FlexUnit4Training_wt1 project contains everything that all the walkthroughs up until this point have taken you through.It also includes several new files and additional dependencies to help you through the current walkthrough.</p>
+	</li>
+	<li>
+		<p>Open the CircleTheory.as file in the math.testcases package within the tests directory.</p>
+	</li>
+	<li>
+		<p>Add a public static variable named <code>radiiLoader</code> of type <code>RadiiDataHelper</code> to the CircleTheory class. It should instantiate a <code>RadiiDataHelper</code> object with the argument <code>"xml/radii.xml"</code>.</p>
+
+		<code><pre>public static var radiiLoader:RadiiDataHelper 
+	= new  RadiiDataHelper( "xml/radii.xml" );</pre></code>
+		
+		<p>If you did not use code-completion, add the import for helper.RadiiDataHelper at this time. RadiiDataHelper is the external loader and already has the logic for loading the data.</p>
+
+		<h3><br />Alter the array to use the external data</h3>
+		
+		<p>Now that you are loading the radii data from an external source the <code>radii</code> variable no longer requires the static values. The <code>radii</code> variable must also be marked with <code>[DataPoints(loader="radiiLoader")] metadata</code>.</p>
+	</li>
+	<li>
+		<p>Modify the radii array so that it has <code>[DataPoints(loader="radiiLoader")]</code> metadata.</p>
+
+		<code><pre>[DataPoints]
+[ArrayElementType("Number")]
+public static var radii:Array = [ -5, 1,2,3,4,5,6,7,8,9,10 ];</pre></code>
+		
+		<p>Becomes:</p>
+		
+		<code><pre>[DataPoints(loader="radiiLoader")]
+[ArrayElementType("Number")]
+public static var radii:Array;</pre></code>
+		
+	</li>
+	<li>
+		<p>Save CircleTheory.as.</p>
+		
+		<h3><br />Examing the loader class</h3>
+	</li>
+	<li>
+		<p>Open the RadiiDataHelper.as file in the helper package within the tests directory.</p>
+		<p>To get an idea of how the loader class retrieves the data, you are going to setup breakpoints in the RadiiDataHelper class. As a result, you will get a chance to examine the data before it is parsed into the theory.</p>
+	</li>
+	<li>
+		<p>In Flash Builder add a breakpoint within the RadiiDataHelper constructor at the line that reads: <code>dToken = new ExternalDependencyToken();</code></p>
+
+		<img alt='AddingBreakpoint' id='shift' src='../images/unit9/image1.png' /> 
+		<p class='caption' id='shift'>Figure 1: Adding a breakpoint to the constructor</p>
+	</li>
+	<li>
+		<p>Add another breakpoint within the <code>retrieveDependency()</code> method at the line that reads <code>var asyncToken:AsyncToken = service.send();</code></p>
+
+		<img alt='AddingBreakpoint' id='shift' src='../images/unit9/image2.png' /> 
+		<p class='caption' id='shift'>Figure 2: Adding a breakpoint to the retrieveDependency() method</p>
+	</li>
+	<li>
+		<p>Add a breakpoint within the <code>fault()</code> method at the line that reads: <code>dToken.notifyFault( "Totally Broken" );</code></p>
+
+		<img alt='AddingBreakpoint' id='shift' src='../images/unit9/image3.png' />
+		<p class='caption' id='shift'>Figure 3: Adding a breakpoint to the fault() method,</p>
+
+		<p>Ideally, you shouldn't hit the breakpoint within the <code>fault()</code> method, but if the loader has a problem retrieving the data, you will know before the tests are even run.</p>
+	</li>
+	<li>
+		<p>Finally, add a breakpoint within the <code>result()</code> method at the line that reads: <code>dToken.notifyResult( ar );</code></p>
+
+		<img alt='AddingBreakpoint' id='shift' src='../images/unit9/image4.png' /> 
+		<p class='caption' id='shift'>Figure 4: Adding a breakpoint within the <code>result()</code> method</p>
+	</li>
+	<li>
+		<p>Switch Flash Builder over to debug view using the selector in the upper-right-hand corner.</p>
+
+		<img alt='FlashDegub' id='shift' src='../images/unit9/image5.png' />
+		<p class='caption' id='shift'>Figure 5: Flash Debug view</p>
+	</li>
+	<li>
+		<p>In the expressions tab, which should appear in the upper-right-hand corner by default, add a new watch expression by right-clicking on the whitespace.</p>
+
+		<img alt='WatchExpression' id='shift' src='../images/unit9/image6.png' />
+		<p class='caption' id='shift'>Figure 6: Adding a watch expression</p>
+	</li>
+	<li>
+		<p>The expression being watched should be list, which is the returned data converted to an XMLList object.</p>
+
+		<img alt='NewWatch' id='shift' src='../images/unit9/image7.png' />
+		<p class='caption' id='shift'>Figure 7: New watch expression</p>
+	</li>
+	<li>
+		<p>Add another watch expression for the <code>ar</code> variable, which is the parsed array that the <code>RadiiDataHelper</code> returns as data points.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file in debug mode.</p>
+	</li>
+</ol>
+
+<p>If the FlexUnit4Training.mxml file runs successfully, it should take you through each breakpoint except for the one placed in the <code>fault()</code> method.</p>
+<p>When you reach a breakpoint, press F8 or the play button to move on.</p>
+<p>The first breakpoint illustrates the instantiation of the ExternalDependencyToken, which is responsible for notifying FlexUnit whether the data is return or there is a fault.</p>
+<p>The next breakpoint illustrates the sending of the HTTPService.</p> 
+<p>When you reach the third breakpoint, on the <code>dToken.notifyResult( ar );</code> line, the list watch expression should show that list is equal to an XMLList whose values can be expanded and evaluated in the Expressions tab.</p>
+
+<img alt='ExpressionList' src='../images/unit9/image8.png' />
+<p class='caption'>Figure 8: The list expression in the Expressions tab</p>
+
+<p>The ar expression is the parsed array created in the <code>result()</code> method from the <code>XMLList</code>.</p>
+
+<img alt='ArExpression' src='../images/unit9/image9.png' />
+<p class='caption'>Figure 9: The ar expression in the Expressions tab</p>
+
+<p>After running through the last breakpoint, you should see the following in your browser window.</p>
+
+<img alt='TestsPassed' src='../images/unit9/image10.png' /> 
+<p class='caption'>Figure 10: FlexUnit tests passed</p>
+
+<p>The radii.xml file contains the same values previously declared within the radii array. There is no change in operation, because the externally loaded values are interacting with the test in the same way, but having the data externalized makes it easy to modify the tests to run with different values, without having to re-compile the tests.</p>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>Loading external data is an inherently asynchronous process.</p></li>
+	<li><p>For external data to be passed in as DataPoints, the data must be loaded with a loader class.</p></li> 
+	<li><p>Loader methods, datapoints, and datapoint collections must be declared as static variables.</p></li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-10.html" class="next"></a>
+			<a href="Unit-8.html" class="prev"></a>
+			<a href="../flexunit.html" class="indexbutton"></a>
+		</div>
+				
+	</div>
+	
+
+</body>
+</html>
\ No newline at end of file

Added: flex/site/trunk/content/flexunit/tutorial/flexunit/index_1.html
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/flexunit/index_1.html?rev=1579527&view=auto
==============================================================================
--- flex/site/trunk/content/flexunit/tutorial/flexunit/index_1.html (added)
+++ flex/site/trunk/content/flexunit/tutorial/flexunit/index_1.html Thu Mar 20 03:54:59 2014
@@ -0,0 +1 @@
+You have reached this page in error.
\ No newline at end of file

Added: flex/site/trunk/content/flexunit/tutorial/images/Chapter_index.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Chapter_index.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Chapter_index.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/DownloadIcon.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/DownloadIcon.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/DownloadIcon.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/Thumbs.db
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/Thumbs.db?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/Thumbs.db
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/main_default.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/main_default.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/main_default.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/main_rllvr.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/main_rllvr.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/main_rllvr.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/training_default.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/training_default.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/training_default.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/training_rllvr.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/training_rllvr.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/training_rllvr.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/tutorials_default.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/tutorials_default.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/tutorials_default.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/Navigation/tutorials_rllvr.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/Navigation/tutorials_rllvr.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/Navigation/tutorials_rllvr.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: flex/site/trunk/content/flexunit/tutorial/images/back_default.png
URL: http://svn.apache.org/viewvc/flex/site/trunk/content/flexunit/tutorial/images/back_default.png?rev=1579527&view=auto
==============================================================================
Binary file - no diff available.

Propchange: flex/site/trunk/content/flexunit/tutorial/images/back_default.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream