flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r902467 [5/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-14.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-14.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-14.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,506 @@
+<!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>UIComponents</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/unit14.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 14 - UIComponents</h1>
+
+<p>All user interface components in Flex extend the UIComponet class. When a UIComponent is added to the display list, the component must go through a complicated process before it appears on the screen and is ready to be tested. User interaction must also be simulated. Because of this, testing UIComponents is an inherently asynchronous process.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Handle the asynchronous functionality of component creation in the UI</li>
+	<li>Test a component off the display list</li>
+	<li>Create integration tests for components</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Understanding how the display list interacts with UIComponents</li>
+	<li>Understanding inherent asynchronous behavior</li>
+	<li>Understanding the UI Facade</li>
+	<li>Waiting for a component to reach its ready state before testing</li>
+</ul>
+
+<h2>Walkthrough 1: Trying to Test a Component Off DisplayList</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Use the UIImpersonator to test UI components.</li>
+	<li>Create an Async handler to test a component after its addition to the UIComponent.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>In the tests directory, create a new package named login.testcases.</p>
+		<p>Alternatively, if you didn't complete the previous lesson or your code is not functioning properly, you can import the FlexUnit4Training.fxp project from the Unit14/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Create the LoginStartupTest class</h3>
+		
+	</li>
+	<li>
+		<p>In the package <code>login.testcases</code>, create a new ActionScript class file named LoginStartupTest.as.</p>
+		<p>Do not delete the automatically generated constructor. You will need it in the next section.</p>
+	</li>
+	<li>
+		<p>Add a private static constant named <code>LONG_TIME</code> of data type <code>int</code>. Set the constant to <code>500</code>.</p>
+
+		<code><pre>private static const LONG_TIME:int = 500;</pre></code>
+		
+	</li>
+	<li>
+		<p>Just below add a private variable named <code>loginComponent</code> of type <code>LoginComponent</code>.</p>
+
+		<code><pre>private var loginComponent:LoginComponent;</pre></code>
+
+		<p>If you did not use code-completion, add the import for net.digitalprimates.components.login.LoginComponent at this time.</p>
+	</li>
+	<li>
+		<p>Create a new public method named <code>setup()</code> and a new public method named <code>teardown()</code>. Decorate them with <code>[Before(async, ui)]</code> and <code>[After(async, ui)]</code>.</p>
+
+<code><pre>[Before(async, ui)]
+public function setup():void {
+}
+
+[After(async, ui)]
+public function teardown() {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>In the <code>setup()</code> method, create a new instance of <code>loginComponent</code>. On the line immediately following, add a call to <code>Async.proceedOnEvent()</code> passing it the values <code>this</code>, <code>loginComponent</code>, and <code>FlexEvent.CREATION_COMPLETE</code>.</p>
+
+<code><pre>[Before(async, ui)]
+public function setup():void {
+	loginComponent = new LoginComponent();
+	Async.proceedOnEvent( this, loginComponent, FlexEvent.CREATION_COMPLETE );
+}</pre></code>
+
+		<p>If you did not use code completion, add the imports for org.flexunit.async.Async.</p>
+	</li>
+	<li>
+		<p>Immediately after the async handler add the loginComponent to the UIImpersonator</p>
+
+		<code><pre>UIImpersonator.addChild( loginComponent )</pre></code>
+
+		<p>If you did not use code completion, add the import for org.fluint.uiImpersonation.UIImpersonator.</p>
+		<p>The UIImpersonator acts as a facade for the UI allowing visual components to be created without being added to the display list. You will learn more about the UIImpersonator and UI facades in the next section.</p>
+	</li>
+	<li>
+		<p>In the <code>teardown()</code> method, remove the loginComponent from the UIImpersonator and cleanup the instance of loginComponent.</p>
+
+<code><pre>[After(async, ui)]
+public function teardown():void {
+	UIImpersonator.removeChild( loginComponent );
+	loginComponent = null;
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a public function named <code>shouldReturnEmptyFieldsOnStartup()</code>, mark it with <code>[Test(ui)]</code> metadata.</p>  
+
+<code><pre>[Test(ui)]
+public function shouldReturnEmptyFieldsOnStartup():void {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add two calls to the <code>assertThat()</code> method in the <code>shouldReturnEmptyFieldsOnStartup()</code> function. The first should check that <code>loginComponent.usernameTI.text</code> is empty and the other should check that <code>loginComponent.passwordTI.text</code> is empty.</p>
+
+<code><pre>[Test(ui)]
+public function shouldReturnEmptyFieldsOnStartup():void {
+	assertThat( loginComponent.usernameTI.text == '' );
+	assertThat( loginComponent.passwordTI.text == '' ); 
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Save LoginStartupTest.as.</p>
+
+		<h3><br />Add LoginStartupTest to the Suite</h3>
+		
+	</li>
+	<li>
+		<p>Add a new ActionScript class named LoginSuite to the login.testcases package within the tests directory. It should have no Superclass or interfaces.</p>
+	</li>
+	<li>
+		<p>Remove the automatically created constructor from the class.</p>
+	</li>
+	<li>
+		<p>Mark the class with <code>[Suite]</code> and <code>[RunWith("org.flexunit.runners.Suite")]</code> metadata.</p>
+
+		<code><pre>package login {
+	[Suite]
+	[RunWith("org.flexunit.runners.Suite")]
+	public class LoginSuite {
+	}
+}</pre></code>
+
+	</li>
+	<li>
+		<p>Add a public variable named <code>test1</code> of type <code>LoginStartupTest</code> to the class.</p>
+
+		<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class LoginSuite {
+	public var test1:LoginStartupTest;
+}</pre></code>
+
+		<p>If you did not use code-completion, add the imports for login.testcases.LoginSequenceTest at this time.</p>
+	</li>
+	<li>
+		<p>Save the LoginSuite.as file.</p>
+	</li>
+	<li>
+		<p>Open the AllSuites.as file in the testcases package within the tests directory.</p>
+	</li>
+	<li>
+		<p>Remove the loginSequenceTest variable.</p>
+	</li>
+	<li>
+		<p>Add a public variable named <code>loginSuite</code> of type <code>LoginSuite</code> to the class.</p>
+
+		<code><pre>[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class AllSuites {
+	public var circleSuite:CircleSuite;
+	public var layoutTest:LayoutTest;
+	public var loginSuite:LoginSuite;
+}</pre></code>
+
+	</li>
+	<li>
+		<p>Save the AllSuites.as file.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If your MXML file ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit14/image1.png' />
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+		
+	</li>
+</ol>
+
+<h2>Understanding how the display list interacts with UIComponents</h2>
+
+<p>In AS3, UIComponents may be instantiated off the display list. When a component is instantiated, basic setup of the component is performed. However, styles, size, and children are not set or created. This means that when testing a component, merely instantiating the component is not enough to put it in a testable state. Creation of the component has only just begun.</p>
+<p>When the component is added to the display list, the component creation continues. Once this cycle is complete, the component is in a testable state. Due to the asynchronous nature of all UIComponents, these components require a special way of testing.</p>
+
+<h2>Understanding inherent asynchronous behavior</h2>
+
+<p>UIComponent creation is broken down into a series of four stages: construction, configuration, attachment and initialization. The time it takes to fully create a component depends on the nature of the component and any children it may have.</p>
+
+<h3>Construction Stage</h3>
+
+<p>During this stage the component constructor is called. Frequently we add listeners to the component, set properties or initialize other non-display objects.</p>
+
+<h3>Configuration Stage</h3>
+
+<p>In this stage, properties set by setters are set internally for later configuration.</p>
+
+<h3>Attachment Stage</h3>
+
+<p>This stage is triggered by a UIComponent being added to the display list.  During this stage the parent property is set on the component. Once complete, the component begins initialization.</p>
+
+<h3>Initialization Stage</h3>
+
+<p>This stage comprises the largest portion of the components creation. During this stage children are created, the component is sized, and styles are set. A component with many children has to wait for each child component to complete creation before its initialization can be considered complete. If those children have children they will in turn need to wait for their children's creation complete event, and so on. During this stage the component goes through the following steps:</p>
+<ol>
+	<li>The <i>preinitialize</i> event is dispatched.</li>
+	<li>The children of the component are created in the <code>createChildren()</code> method.</li>
+	<li>The <i>initialize</i> event is dispatched.</li>
+	<li>The state of the component is invalidated.</li>
+	<li>The <code>commitProperties()</code>,  <code>measure()</code> and <code>updateDisplayList()</code> methods are called.</li>
+	<li>The <i>creationComplete</i> event is dispatched.</li>
+</ol>
+
+<h2>Understanding the UI Facade</h2>
+
+<p>The UI facade acts as a buffer between the actual UI and the main application. Through the use of a facade the UI can change without affecting the way the rest of the system interacts. In this way, the application needs to know only how to interact with the facade. As long as both the UI and business logic follow the facade's interface, both can change at will without a change from one requiring a change in the other.</p>
+<p>The UI facade allows the testing of UIComponents without the display list. However, adding components to the facade will still cause them to go through their entire creation process. There is no need for a component to be visible for it to be tested.</p>
+<p>In FlexUnit 4, the UIImpersonator acts as a facade for UI based components. The UIImpersonator contains addChild, removeChild, getChildAt and can be interacted with in the same way as the display list without the extra overhead.</p>
+
+<h2>Waiting for a component to reach its ready state before testing</h2>
+
+<p>Attempting to test a UIComponent before it reaches its ready state may cause the test to fail. The component may not be properly measured, sized, or positioned and its children may not be fully created. Its properties may have unexpected values.</p>
+<p>Fortunately, UIComponents notify us when they have reached their ready state by dispatching the <i>creationComplete</i> event. At this point, we can be reasonably sure all children are created and the component is ready for testing.</p>
+
+<h3>Asynchronous Startup</h3>
+
+<p>To use asynchronous startup, decorate the <code>Before</code> method with the <code>async</code> annotation. If the startup is due to UI, you will also want to decorate it with <code>ui</code>, as in:</p>
+
+<code><pre>[Before(async, ui)]
+public function setup():void {}</pre></code>
+
+<p>The main body of the setup method has to instantiate the component, add the async handler and add it to the facade. The UIImpersonator is a static class that mimics a component on the display list. It contains several static functions that may be used in place of the real functions. To add a UIComponent to the facade, use the UIImpersonator's <code>addChild()</code> method, passing the component as the parameter:</p>
+
+<code><pre>component = new UIComponent();
+Async.proceedOnEvent( this, component, "creationComplete", TIMEOUT, timeoutHandler );
+UIImpersonator.addChild( component );</pre></code>
+
+<p>Once the <i>creationComplete</i> is dispatched, tests will continue. Be sure to remove the component from the UIImpersonator at the end of the test. Otherwise, the component will remain in memory.</p>
+
+<h3>Using async startup chains</h3>
+
+<p>In some cases, such as when using the ParameterizedRunner, async startup may not be possible. In this case, we will have to create an async startup chain at the beginning of the test. In this instance we create the component as we would in the setup of the asynchronous startup; however we do it at the beginning of the test. We then wait for the creationComplete call before proceeding with the test.</p>
+
+<code><pre>[Test(async, ui)]
+public function componentShouldDoSomething():void {
+	Component = new UIComponent();
+	Async.proceedOnEvent( this, component, "creationComplete", TIMEOUT, timeoutHandler );
+	UIImpersonator.addChild( component );
+
+	// rest of the test
+}</pre></code>
+
+<p>With this type of test, you will need to clean up the test by removing the component from the UIImpersonator in all async handlers.</p>
+
+<h2>Walkthrough 2: Creating integration tests for a component</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Test that a login component dispatches an event with the entered login information when the user attempts to log in.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the file LoginIntegrationTest.as in the login.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 Unit 14/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+		
+		<h3><br />Setup the Parameterized Test</h3>
+	
+	</li>
+	<li>
+		<p>Immediately before the class declaration, add the <code>RunWith</code> metadata for the Parameterized runner.</p>
+
+		<code><pre>[RunWith("org.flexunit.runners.Parameterized")]</pre></code>
+		
+		<p>Declare two private variables of type <code>String</code> named <code>username</code> and <code>password</code>. Also, declare a protected variable named <code>loginComponent</code> of type <code>LoginComponent</code>.</p>
+
+<code><pre>private var username:String;
+private var password:String; 
+protected var loginComponent:LoginComponent;</pre></code>
+
+		<p>If you did not use code-completion, add the import for net.digitalprimates.components.login at this time.</p>
+	</li>
+	<li>
+		<p>Add the data loader for the login data points.</p>
+
+<code><pre>public static var userAndPasswordDataLoader:UserAndPasswordDataHelper = 
+	new UserAndPasswordDataHelper("xml/usersAndPasswords.xml" );</pre></code>
+
+		<p>If you did not use code-completion, add the import for helper.UserAndPasswordDataHelper at this time.</p>
+
+		<h3><br />Create the login sequence test</h3>
+		
+	</li>
+	<li>
+		<p>Create a new test named <code>shouldLoginWithProvidedCredentials</code> that takes two arguments, a username of type <code>String</code> and a password of type <code>String</code>. Decorate it with the metadata <code>[Test( async, ui, id="userAndPasswordDataLoader" )]</code>.</p>
+
+<code><pre>[Test(async, ui, id="userAndPasswordDataLoader")]
+public function shouldLoginWithProvidedCredentials( username:String, password:String ):void {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a variable named <code>sequence</code> of type <code>SequenceRunner</code> to the <code>shouldLoginWithProvidedCredentials()</code> method. Instantiate it with <code>this</code> as its argument.</p>
+
+<code><pre>protected function handleComponentReady(event:FlexEvent, passThroughData:Object ):void {
+	var sequence:SequenceRunner = new SequenceRunner( this );
+}</pre></code>
+
+		<p>If you did not use auto complete, add the import for org.fluint.sequence.SequenceRunner.</p>
+	</li>
+	<li>
+		<p>Create a new Object called <code>passThroughData</code>. Assign it the <code>username</code> and <code>password</code> constructor arguments.</p>
+
+<code><pre>var passThroughData:Object = new Object();
+passThroughData.username = username;
+passThroughData.password = password;</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>sequence.addStep()</code> method, pass in <code>new SequenceSetter( loginComponent.usernameTI, {text:username} )</code> as its argument.</p>
+
+		<code><pre>sequence.addStep( new SequenceSetter( loginComponent.usernameTI, {text:username} ) );</pre></code>
+		
+		<p>SequenceSetter simulates a call to the setter during sequence execution.</p>
+		<p>If you did not use auto complete, add the import for org.fluint.sequence.SequenceSetter.</p>
+	</li>
+	<li>
+		<p>Add another call to the <code>sequence.addStep()</code> method just below the last; pass in <code>new SequenceWaiter( loginComponent.usernameTI, FlexEvent.VALUE_COMMIT, LONG_TIME )</code> as its argument.</p>
+
+<code><pre>sequence.addStep( new SequenceSetter( loginComponent.usernameTI, {text:username} ) );
+sequence.addStep( new SequenceWaiter( loginComponent.usernameTI, FlexEvent.VALUE_COMMIT,
+ LONG_TIME ) );</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.fluint.sequence.SequenceSetter and org.fluint.sequence.SequenceWaiter at this time.</p>
+	</li>
+	<li>
+		<p>Add a call to the <code>sequence.addStep()</code> method; pass in <code>new SequenceSetter(  loginComponent.passwordTI, {text:password} )</code> as its argument.</p>
+	</li>
+	<li>
+		<p>Add another call to the <code>sequence.addStep()</code> method just below the last; pass in  <code>new SequenceWaiter( loginComponent.passwordTI, FlexEvent.VALUE_COMMIT, LONG_TIME )</code> as its argument.</p>
+
+<code><pre>sequence.addStep( new SequenceSetter( loginComponent.passwordTI, {text:password} ) );
+sequence.addStep( new SequenceWaiter( loginComponent.passwordTI, FlexEvent.VALUE_COMMIT,
+ LONG_TIME ) );</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>sequence.addStep()</code> method, pass in <code>new SequenceEventDispatcher( loginComponent.loginBtn, new MouseEvent( MouseEvent.CLICK, true, false ) )</code> as its argument.</p>
+	</li>
+	<li>
+		<p>Add another call to the <code>sequence.addStep()</code> method, pass in <code>new SequenceWaiter( loginComponent, 'loginSuccess', LONG_TIME, handleSuccessTimeout ) )</code> as its argument.</p>
+
+<code><pre>sequence.addStep( new SequenceEventDispatcher( loginComponent.loginBtn,
+ new MouseEvent( MouseEvent.CLICK, true, false ) ) );
+sequence.addStep( new SequenceWaiter( loginComponent, 'loginRequested', LONG_TIME,
+ handleSuccessTimeout ) );</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.fluint.sequence.SequenceEventDispatcher and flash.events.MouseEvent at this time.</p>
+	</li>
+	<li>
+		<p>Add a call to the <code>sequence.addAssertHandler()</code> method, pass in <code>handleLoginSuccess</code> and <code>passThroughData</code> as its arguments.</p>
+	</li>
+	<li>
+		<p>Add a call to the run() method, which is required for the sequence to run.</p>
+
+		<code><pre>sequence.addAssertHandler( handleLoginRequested, passThroughData );	
+sequence.run();</pre></code>
+
+		<p>With this setup, if the login is requested the event will be handled. If the login request is not fired, control will pass to the timeout handler.  The completed method should read as:</p>
+
+<code><pre>[Test(async, ui, dataProver="userData")]
+public function shouldLoginWithProvidedCredentials( username:String, password:String ):void {
+	var sequence:SequenceRunner = new SequenceRunner( this );
+	
+	var passThroughData:Object = new Object();
+	passThroughData.username = username;
+	passThroughData.password = password;
+	
+	sequence.addStep( new SequenceSetter( loginComponent.usernameTI, {text:username} ) );
+	sequence.addStep( new SequenceWaiter( loginComponent.usernameTI, FlexEvent.VALUE_COMMIT,
+	 LONG_TIME ) );
+	sequence.addStep( new SequenceSetter( loginComponent.passwordTI, {text:password} ) );
+	sequence.addStep( new SequenceWaiter( loginComponent.passwordTI, FlexEvent.VALUE_COMMIT,
+	 LONG_TIME ) );
+
+	sequence.addStep( new SequenceEventDispatcher( loginComponent.loginBtn,
+	 new MouseEvent( MouseEvent.CLICK, true, false ) ) );
+	sequence.addStep( new SequenceWaiter( loginComponent, 'loginRequested', LONG_TIME,
+	 handleSuccessTimeout ) );
+	
+	sequence.addAssertHandler( handleLoginRequested, passThroughData );	
+			
+	sequence.run();
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a protected function named <code>handleLoginRequested()</code>. It should take a parameter named <code>event</code> of type <code>Event</code> and a parameter named <code>passThroughData</code> of data type <code>Object</code>.</p>  
+
+<code><pre>protected function handleLoginRequested( event:Event, passThroughData:Object ):void {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>assertThat()</code>. It should assert that the <code>passThroughData.username</code> variable is <code>equalTo( loginComponent.usernameTI.text.)</code>.</p>
+	</li>
+	<li>
+		<p>Add a call to the <code>assertThat()</code>. It should assert that the <code>passThroughData.password</code> instance variable is equalTo( loginComponent.passwordTI.text ).</p>
+
+<code><pre>protected function handleLoginRequested( event:Event, passThroughData:Object ):void {
+	assertThat( passThroughData.username, equalTo( loginComponent.usernameTI.text ) );
+	assertThat( passThroughData.password, equalTo( loginComponent.passwordTI.text ) );
+}</pre></code>
+
+		<p>If you did not use code-completion, add the imports for org.flexunit.assertThat and org.hamcrest.object.equalTo.</p>
+	</li>
+	<li>
+		<p>Add a protected function named <code>handleSuccessTimeout()</code> in the class. It should take a parameter named <code>passThroughData</code> of type <code>Object</code>.</p>
+
+<code><pre>protected function handleSuccessTimeout(passThroughData:Object):void{
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>In the timeout handler, add a call to <code>fail()</code>, passing it the message "Login request was not received as expected".</p>
+	</li>
+	<li>
+		<p>Add another call to the <code>assertThat()</code> method. It should assert that the instance variable <code>password</code> is <code>not( equalTo( LoginComponent.PASSWORD ) )</code>.</p>
+
+<code><pre>protected function handleSuccessTimeout(passThroughData:Object):void {
+	fail( "Login request was not received as expected" );
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Save LoginStartupTest.as.</p>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+		<p>If your mxml file ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='TestsPassed' id='shift' src='../images/unit14/image2.png' />
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>Adding components to the display list is an inherently asynchronous process.</p></li>
+	<li><p>UIImpersonator</p></li>
+	<ul>
+		<li><p>UI facade for testing components UI components off the display list.</p></li>
+		<li><p>Uses the addChild() method to add components.</p></li>
+	</ul>
+	<li><p>Uses the removeChild() method to remove components. UI components must reach a ready state before testing.</p></li>
+	<li><p>UI integration testing</p></li>
+	<ul>
+		<li><p>Tests properties and methods of components present in the UI.</p></li>
+		<li><p>May require sequential operation</p></li>
+	</ul>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-15.html" class="next"></a>
+			<a href="Unit-13.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-15.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-15.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-15.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,394 @@
+<!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>Creating Testable Code</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/unit15.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 15 - Creating Testable Code</h1>
+
+<p>The ability to thoroughly test a class or component is an indication of good design. In situations where a component has unexposed functionality, it can be very difficult to write tests that ensure the component functions as expected. Refactoring a class for better unit testing is therefore great for quality assurance as well as coding practice.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Identify characteristics in your code that may necessitate refactoring for better unit testing</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Why highly cohesive code tends to test more easily</li>
+	<li>Why loosely coupled code can be tested less painfully</li>
+	<li>Refactoring an un-testable piece of code to something testable</li>
+	<li>Creating tests for legacy code</li>
+</ul>
+
+<h2>Why highly cohesive code tends to test more easily</h2>
+
+<p>Highly cohesive code creates strong test fixtures and short, simple tests. A class with low cohesion will frequently have us begging the question, "does this belong in the fixture?" If there is a section of code that <i>should</i> be in the fixture but doing so will create unnecessary overhead for some of the tests we are likely looking at a case of low cohesion. Always remember that a class with high cohesion tends to create tests with high cohesion.</p>  
+<p>Consider the following database example:</p>
+
+<code><pre>public class ContactDatabaseConnection {
+	public function ContactDatabaseConnection () {
+	}
+
+	public function connect():void {
+		//code to connect
+	}
+
+	public function getContact( itemName:String ):Contact {
+		//code to retrieve contact
+	}
+
+	public function formatContact( contact:Contact ):FormattedContact {
+		//code to format contact
+	}
+}</pre></code>
+
+<p>Try to imagine the fixture for this interface. The test fixture would need to create a new database connection. It would also need to create a new contact for testing.</p> 
+
+<code><pre>private var testContact:Contact;
+private var connection:ContactDatabaseConnection;
+	
+	[Before]
+	public function setup():void {
+		connection = new ContactDatabaseConnection();
+		connection.connect();
+		testContact = new Contact();
+}</pre></code>
+
+<p>However, the <code>formatContact()</code> method does not need a database connection. In fact, what does formatting a contact have to do with a <code>ContactDatabaseConnection</code>? These methods do not have a unified test fixture. In one section we would be testing the connect and retrieval functions. The other requires a contact be ready made. Clearly, <code>formatContact()</code> does not belong.</p>
+<p>If you find yourself needing a unique fixture for each test in a class it is highly likely you are dealing with a class that contains low cohesion or only temporal cohesion at best. In this situation, you might want to return to the code and find a way to split the class to increase the cohesion.</p> 
+<p>Here is an improved version of the <code>ContactDatabaseConnection</code> class that should be much easier to test and maintain:</p>
+
+<code><pre>public class ContactDatabaseConnection {
+	public function ContactDatabaseConnection () {
+	}
+
+	public function connect():void {
+		//code to connect
+	}
+
+	public function getContact( itemName:String ):IContact {
+		//code to retrieve contact
+	}
+}</pre></code>
+
+<p>And moving the <code>formatContact</code> method into the specific <code>Contact</code> implementation:</p>
+
+<code><pre>public class Contact implements IContact {
+	//contact code
+
+	public function formatContact():void {
+		//format code
+	}
+}</pre></code>
+
+<h2>Why loosely coupled code can be tested less painfully</h2>
+
+<p>By creating loosely coupled code, we create classes that can more easily be tested in isolation. Tightly coupled code creates a dependency on outside resources that frequently do not belong in the class with which they are coupled.</p>
+<p>Consider the following:</p>
+
+<code><pre>public class BoxOfCrayons() {
+	private var crayons:Array = new Array();
+
+	public function addCrayon( color:String ):void {
+		var crayon = new WaxCrayon();
+		crayon.color = color;
+		crayon.wrapper.color = color;
+	}
+}</pre></code>
+
+<p>Think of the tests you would need to write for the <code>addCrayon()</code> method:</p>
+<ul>
+	<li>Test that a crayon is added to the box of crayons</li>
+	<li>Test that the crayon is the color you are trying to add</li>
+	<li>Test that the wrapper has the correct color</li>
+</ul>
+<p>This section of code is tightly coupled for a few reasons. First, BoxOfCrayons is making its own crayons. What if BoxOfCrayons can also contain ShortCrayon or ClayCrayon? Even worse, why is BoxOfCrayons modifying crayon wrappers at all? <code>addCrayon()</code> is now tightly coupled to this exact implementation of WaxCrayon. What if we decide that WaxCrayons do not have wrappers? You would also need to change the implementation of <code>addCrayon()</code>.</p>
+<p>Tightly coupled code:</p>
+<ul>
+	<li>Creates a dependency on a specific implementation.</li>
+	<li>Requires pulling potentially untested code into the test.</li>
+	<li>Has more room for errors. When a test fails it is difficult to definitively tell which portion of the code failed.</li>
+	<li>Requires the unit tests to be rewritten each time a coupled component is changed.</li>
+	<li>Defeats the basic purpose of unit testing. If you have to rewrite the unit tests each time you change an unrelated class the unit tests are not effectively doing their job.</li>
+</ul>
+
+<h2>Refactoring an un-testable piece of code to something testable</h2>
+
+<p>There is no simple answer on the best way to refactor an untestable object. For some, it may be as simple as using a getter to expose a previously hidden property. For others, where objects are tightly coupled, may require a complete rewrite. The testability of a piece of code depends entirely on its available seams.  In code without seams, one must rely on any "magic" performed behind the scenes. If what you put in does not yield what you expected you have no way of knowing where everything went wrong.</p>
+<p>When refactoring, ask yourself these questions:</p>
+<ul>
+	<li>Is my code loosely coupled?</li> 
+	<li>Is my code cohesive?</li> 
+	<li>Are my properties inspectable?</li>
+	<li>Do my methods return values?</li>
+	<li>Am I using dependency injection where appropriate?</li>
+</ul>
+<p>If you answer "no" to any of these questions, that might be a good place to start refactoring</p>
+
+<h2>Creating tests for legacy code</h2>
+
+<p>Legacy code tests tend to be the most difficult to test. Frequently the original code is not written with any testing in mind and may require significant refactoring. Refactoring the code to support functionality can potentially break other sections of code creating a veritable cornucopia of bugs.</p>
+<p>When refactoring legacy code, keep the following in mind:</p>
+<ul>
+	<li><p>Refactor slowly. Make changes, create and run tests, then move on to the next change.</p></li>
+	<li><p>Never refactor without tests to back up the refactor.</p></li>
+	<li><p>Watch for constructors doing a lot of work. Use dependency injection to replace that work. This has the added benefit of creating a seam for testing in addition to reducing the coupling of the code.</p></li>
+	<li><p>Focus on test coverage. It's not always possible to test certain code areas without significant alterations of the code base. Always question if refactoring is worth the possibility of completely breaking the rest of the build.</p></li>
+	<li><p>Focus on critical functionality. Ensure that the most important parts work. Writing tests for code built on untested code is no guarantee since we do not even know if the core functions as expected.</p></li>
+</ul>
+
+<h2>Walkthrough 1: Refactoring an object to become testable</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Examine a class with missing seams</li>
+	<li>Refactor the class to allow for isolated testing</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnit4Training_wt1.fxp project from the Unit 15/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+	</li>
+	<li>
+		<p>Open CircleLayout.as in the net.digitalprimates.components.layout package.</p>
+	</li>
+	<li>
+		<p>Examine the <code>updateDisplayList()</code> method in this class.</p>
+
+<code><pre>override public function updateDisplayList( contentWidth:Number, contentHeight:Number ):void {
+
+	...							
+	super.updateDisplayList( contentWidth, contentHeight );
+		
+	var circle:Circle = new Circle( new Point( contentWidth/2, contentHeight/2 ),
+	 getLayoutRadius( contentWidth, contentHeight ) );
+	
+	for ( i = 0; i &#60; target.numElements; i++ ) {
+		element = target.getElementAt(i);
+					
+		elementLayoutPoint = circle.getPointOnCircle( elementAngleInRadians );
+		...			
+		//Used to be move()
+		element.setLayoutBoundsPosition( elementLayoutPoint.x-elementWidth,
+		 elementLayoutPoint.y-elementHeight );
+					
+	}
+}</pre></code>
+
+		<p>This method creates a <code>circle</code> object of type <code>Circle</code> with dimensions based on the <code>contentWidth</code> and <code>contentHeight</code> arguments. The elements of the layout are positioned to points on the circle.</p>
+		<p>Suppose you wanted to test the functionality of this method. It would be impossible to isolate because the method is dependent on the <code>Circle</code> class.</p>
+		<p>The circle object could be mocked if the <code>CircleLayout</code> class had its own <code>circle</code> property instead.</p>
+	</li>
+	<li>
+		<p>At the top of the class, create a private circle property.</p>
+
+		<code><pre>private var circle:Circle;</pre></code>
+		
+	</li>
+	<li>
+		<p>Generate a public getter and setter for the property. Right-click the property, select Source &#62; Generate Getter/Setter, and click OK.</p>
+
+<code><pre>public function get circle():Circle {
+	return _circle;
+}
+		
+public function set circle(value:Circle):void {
+	_circle = value;
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a call to the <code>invalidateDisplayList()</code> method on the <code>target</code> property within the setter of the <code>circle</code>.</p>
+
+<code><pre>public function set circle(value:Circle):void {
+	circle = value;
+	target.invalidateDisplayList();
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Remove the line that instantiates the <code>circle</code> object within the <code>updateDisplayList()</code> method.</p>
+
+		<code>var circle:Circle = new Circle( new Point( contentWidth/2, contentHeight/2 ), getLayoutRadius( contentWidth, contentHeight ) );</code>
+		
+	</li>
+	<li>
+		<p>Remove the <code>getLayoutRadius()</code> method from the class.</p>
+	</li>
+	<li>
+		<p>Perform a null check for the <code>circle</code> within <code>updateDisplayList()</code> method.</p>
+
+<code><pre>super.updateDisplayList( contentWidth, contentHeight );
+
+if(circle) {
+	for ( i = 0; i &#60; target.numElements; i++ ) {
+		...
+	}
+}</pre></code>
+
+		<p>The <code>CircleLayout</code> class can now be better tested as it is not dependent on another class.</p>
+	</li>
+</ol>
+
+<h2>Walkthrough 2: Refactoring an object to become testable</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Add a new method named <code>distanceFrom()</code> to the <code>Circle</code> class.</li> 
+	<li>Modify the <code>Circle</code> classes' <code>equals()</code> method to apply the <code>distanceFrom()</code> method.</li> 
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the Circle.as file from the net.digitalprimates.math package.</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 15/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Add the distanceFrom() method</h3>
+		
+	</li>
+	<li>
+		<p>Just below the <code>equals()</code> method, add a new public method named <code>distanceFrom()</code>. It should return a value of data type <code>Number</code>. It should take a parameter named <code>circle</code> of type <code>Circle</code>.</p>
+
+<code><pre>public function distanceFrom( circle:Circle ):Number {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>The new method should return <code>Point.distance( this.origin, circle.origin )</code>, which calculates the distance between the <code>Circles</code>' origin points.</p>
+
+<code><pre>public function distanceFrom( circle:Circle ):Number {
+	return Point.distance( this.origin, circle.origin );
+}</pre></code>
+
+<h3><br />Modify the equals() method</h3>
+
+<p>The <code>equals()</code> method in <code>Circle</code> may appear simple enough, but can be difficult to test. This comparison is based on radius and origin. Although the radius comparison is about as simple as it could be, the point comparison is based on the accessing the <code>origin.x</code> and <code>origin.y</code> and asserting their equality separately. If you were to isolate and mock the circle for testing, you would have to mock the <code>Point</code> object as well.</p> 
+
+<code><pre>public function equals( circle:Circle ):Boolean {
+	var equal:Boolean = false;
+
+	if ( ( circle ) &#38;&#38; ( this.radius == circle.radius ) &#38;&#38; ( this.origin ) &#38;&#38;
+	 ( circle.origin ) ) {
+		if ( ( this.origin.x == circle.origin.x ) &#38;&#38; ( this.origin.y == circle.origin.y ) ) {
+			equal = true;
+		}
+	}
+
+	return equal;
+}</pre></code>
+
+<p>Creating an isolated object for testing will ultimately reduce these interdependencies. Mocks should be able to work without the required input of additional mocks. Creating code of this kind will add seams, loosen coupling, and improve quality over all.</p>
+	</li>
+	<li>
+		<p>In the <code>equals()</code> method, replace the line of the second if statement, which checks the equality of this and the comparison circle's origin's x and y values, with a line that checks that <code>this.distanceFrom( circle )</code> is equal to <code>0</code>.</p> 
+
+<code><pre>if ( ( this.origin.x == circle.origin.x ) &#38;&#38;
+( this.origin.y == circle.origin.y ) ) {
+	equal = true;
+}</pre></code>
+
+		<p>Becomes:</p>
+
+<code><pre>if ( this.distanceFrom( circle ) == 0 ) {
+	equal = true;
+}</pre></code>
+
+		<p>The <code>Circle</code> class's new <code>equals()</code> method should read as follows:</p>
+
+<code><pre>public function equals( circle:Circle ):Boolean {
+	var equal:Boolean = false;
+
+	if ( ( circle ) &#38;&#38; ( this.radius == circle.radius ) &#38;&#38; 
+	( this.origin ) &#38;&#38; ( circle.origin ) ) 	{
+		if ( this.distanceFrom( circle ) == 0 ) {
+			equal = true;
+		}
+	}
+
+	return equal;
+}</pre></code>
+
+	<p>At this point, if you were to mock a <code>Circle</code>, you would only need to mock and create expectations for a <code>circle</code> object. A mock for the <code>Point</code> class is not needed here.</p>
+		
+	</li>
+	<li>
+		<p>Save the Circle.as file</p>
+		
+		<h3><br />Run the unit tests</h3>
+		
+		<p>This is a great example of why automated unit testing is so beneficial in the development life cycle. In your modifications of the Circle.as class, it's very possible that you could have broken some functionality in the class and elsewhere. Fortunately, there are a wealth of unit test cases, many of them dealing with the <code>Circle</code> class and even the <code>equals()</code> method.</p>
+	</li>
+	<li>
+		<p>Open the FlexUnit4Training.mxml file.</p> 
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file.</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>Code that tests easily is</p></li>
+	<ul>
+		<li><p>Highly cohesive</p></li>
+		<li><p>Loosely coupled</p></li>
+	</ul>
+	<li><p>Refactoring code to become testable</p></li>
+	<ul>
+		<li><p>Generally, creates better code</p></li>
+		<li><p>Adds necessary seams in the code</p></li>
+		<li><p>Favors simplicity</p></li>
+	</ul>
+	<li><p>Testing legacy code should be approached with caution.</p></li>
+	<ul>
+		<li><p>Do not refactor without tests in place to backup</p></li>
+	</ul>
+	<li><p>Black box classes need to make their properties and methods available for testing.</p></li>
+	<ul>
+		<li><p>Minimal inter method/class/property dependencies</p></li>
+		<li><p>Public getter and setter functions</p></li>
+	</ul>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-16.html" class="next"></a>
+			<a href="Unit-14.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-16.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-16.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-16.html Thu Mar 20 03:56:18 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>Allowing Your Tests to Function with Continuous Integration</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/unit16.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 16 - Allowing Your Tests to Function with Continuous Integration</h1>
+
+<p>Continuous integration testing is another necessity of the complex application development environment. Generally, when many people and external forces interact with a deployed or actively developed application, quality control measures must be in place for the application's full functionality. Continuous integration systems should run application tests automatically, and some can be configured to do so.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Setup FlexUnit project builds with Apache Ant</li>
+	<li>Run FlexUnit tests within the Hudson continuous integration environment</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Understanding continuous integration</li>
+	<li>Examining a build script</li>
+	<li>Hudson</li>
+	<li>Understanding listeners</li>
+	<li>Failure and Success reporting options</li>
+</ul>
+
+<h2>Understanding continuous integration</h2>
+
+<p>Continuous Integration is a software development practice where members of a development team integrate their source code changes frequently; typically each developer integrates their changes at least once per day. This practice leads to multiple integrations throughout the day and with every integration the changes are verified by an automated build (which includes testing) to detect integration errors as quickly as possible.</p> 
+<p>Many tools exist to support a CI environment and make the process automated. Some of the common ones include:</p>
+<ul>
+	<li>Hudson</li>
+	<li>Cruise Control</li>
+	<li>Continuum</li>
+</ul>
+<p>CI systems generally include a source repository, an automated build including build script, self testing code, joint commit by developers, an integration machine and, frequently, automated deployment.</p>
+<p>CI builds commonly use the following process:</p>
+<ul>
+	<li>Developers run local builds and tests on code changes.</li>
+	<li>Developers check in code into the main repository.</li>
+	<li>An automated build server monitors the repository.</li>
+	<li>New code is checked into a project build and continuously integrated and tested.</li>
+	<li>Test results are available to all developers on the project and reported in real time.</li>
+</ul>
+
+<h2>Understanding listeners</h2>
+
+<p>Listeners act as a communication between the test runners and a reporting device. If a runner acts as the worker, the listener acts as the foreman, reporting the results of the workers labors.</p>
+<p>All listeners implement the IRunListener interface. FlexUnit 4 may use any number of listeners, each will be called as a test completes. It is also possibly to write custom listeners further extending the framework.</p>
+<p>There are several base listeners included in FlexUnit.</p>
+
+<h3>UIListener</h3>
+
+<ul>
+	<li>A separate library which allows visual reporting of results</li>
+	<li>Accepts user interaction</li>
+	<li>Gives detailed information about test run times, passing, failing, ignores and failure messages</li>
+</ul>
+
+<h3>CIListener</h3>
+
+<ul>
+	<li>Separate library listener project</li>
+	<li>Creates a socket connection to communicate results over a connection</li>
+	<li>As part of CI, communicates and reports results to the FlexUnit Ant task</li>
+</ul>
+
+<h3>XMLListener</h3>
+
+<ul> 
+	<li>Creates an XML report for tests</li>
+	<li>Primarily used by the Flashbuilder FlexUnit plugin</li>
+	<li>Can be customized to report XML across different sockets</li>
+</ul>
+
+<h2>Walkthrough 1: Using the CIListener</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Edit the application to use the CIListener</li>
+</ul>
+
+<h3>Adding the CIListener</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnit4Training.fxp project from the Unit 16/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+	</li>
+	<li>
+		<p>Open the FlexUnit4Training.mxml file.</p>
+	</li>
+	<li>
+		<p>Find and remove the <code>FlexUnitTestRunnerUI</code> component with id <code>testRunner</code> from the application file.</p>  
+		<p>You are removing this section of code as you will no longer be using the UIRunner.</p>
+
+		<s>&#60;flexui:FlexUnitTestRunnerUI id="testRunner"/&#62;</s>
+
+		<p>Continuous integration servers are autonomous. In addition to creating unnecessary overhead, a UIRunner prevents FlexUnit from running in a headless environment.</p>
+	</li>
+	<li>
+		<p>Within the <code>&#60;fx:Script&#62;</code> block, there is a method named <code>onCreationComplete()</code>. Remove the body of this method, leaving just the empty shell of the method.</p>
+
+<code><pre>private function onCreationComplete():void {
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>Within the <code>&#60;fx:Script&#62;</code> block add a new public variable named <code>core</code> of type <code>FlexUnitCore</code>.</p>  
+
+		<code><pre>public var core:FlexUnitCore;</pre></code>
+
+		<p>If you did not use code-completion, add the import statement for and org.flexunit.runner.FlexUnitCore at this time.</p>
+		<p>The <code>core</code> acts as our runner; we will be adding the <code>CIListener</code> to the core listeners.</p>
+	</li>
+	<li>
+		<p>In the <code>onCreationComplete()</code> method instantiate the <code>core</code> variable to a new <code>FlexUnitCore()</code>. Call the <code>core.addListener()</code> method on the next line, passing it an argument of <code>new CIListener()</code>. On the next line call the <code>core.run( currentRunTestSuite() )</code>.</p> 
+
+<code><pre>private function onCreationComplete():void {
+	core = new FlexUnitCore();
+	core.addListener( new CIListener() );
+}</pre></code>
+		
+	</li>
+	<li>
+		<p>On the following line, call <code>core.run()</code> passing <code>currentRunTestSuite()</code> as its argument.</p> 
+
+<code><pre>private function onCreationComplete():void {
+	core = new FlexUnitCore();
+	core.addListener( new CIListener() );
+	core.run( currentRunTestSuite() );
+}</pre></code>
+		
+		<p>If you did not use code-completion, add the import statement for org.flexunit.listeners.CIListener at this time.</p>
+	</li>
+	<li>
+		<p>Save this mxml file. Do not run it at this time.</p>
+	</li>
+</ol>
+
+<h2>Examining an Ant build script</h2>
+
+<p>A build script is an XML configuration file to run compiling and, in some cases, testing of the app. The build file acts as an instruction manual to the CI server on what files to include and what tests to run. It may also contain additional behaviors.</p>
+<p>Scripts are made up of a project, optional properties, optional task definitions and a series of 'targets' which must include at least one default target.</p>
+
+<h3>Project tag</h3>
+
+<ul>
+	<li>Acts as the build header</li>
+	<li>name - name of the project</li>
+	<li>default - the default target, or command, to run when the build is run</li>
+	<li>basedir - Base directory for all work. If none is specified, Ant uses the build file directory as base directory</li>
+	<li>Project tag structure</li>
+</ul>
+
+<code><pre>&#60;project name=<i>"project_name"</i> basedir=<i>"project_base"</i> default=<i>"default_target"</i> &#62;</pre></code>
+
+<h3>Property tag</h3>
+
+<ul>
+	<li>Frequently used to create shorthand variables for directory locations</li>
+	<li>Also used to specify directories of task targets</li>
+	<li>Property tag structure</li>
+</ul>
+
+<code><pre>&#60;property name=<i>"property_name"</i> location=<i>"property_location"</i> /&#62;</pre></code>
+
+<h3>Taskdef tag</h3>
+
+<ul>
+	<li>Tasks define the custom behavior to be used with the build</li>
+	<li>Frequently built into a jar file</li>
+	<li>The taskdef tag defines the location of a task within the jar</li>
+	<li>Task definition tag structure</li>
+</ul>
+
+<code><pre>&#60;taskdef resource=<i>"task_location_within_jar"</i> classpath=<i>"task_jar_location"</i> /&#62;</pre></code>
+
+<h3>Target tag</h3>
+
+<ul>
+	<li>Creates possible start points for where the build should begin</li>
+	<li>Targets may depend on other targets</li>
+	<li>The compile target, common in most Flex builds, will depend on directory construction</li>
+	<li>In the case of testing, the test target will depend on the application being compiled</li>
+	<li>If a target has dependencies, the dependencies will be run when the target is run</li>
+	<li>Target tag structure</li>
+</ul>
+
+<code><pre>&#60;target name=<i>"target_name"</i> depends=<i>"target_dependencies"</i>&#62;</pre></code>
+
+<h3>Task</h3>
+
+<ul>
+	<li>Each task is a job or file to be run as part of the build</li>
+	<li>A task is a custom piece of code to be executed during the build</li>
+	<li>There are many common tasks included with Ant</li>
+	<li>We are also concerned with the compile task, FlexUnit task and delete task</li>
+	<li>Each task may have its own unique properties</li>
+	<li>Common task tag structure</li>
+</ul>
+
+<code><pre>&#60;taskname id=<i>"task_id"</i> attribute1=<i>"..."</i> attribute2=<i>"..."</i> ... /&#62;</pre></code> 
+
+<ul>
+	<li>For building projects with Hudson we will be using 6 tasks, Flex Ant task, FlexUnit task, JUnit report task, copy task, zip task and delete task</li>
+	<li>The flex ant task consists of the following tasks</li>
+	<ul>
+		<li>mxmlc - Application compiler for SWFs</li>
+		<li>compc - Component compiler for SWFs and RSLs</li>
+		<li>html-wrapper - Generates wrapper and supporting files</li>
+		<li>asdoc - Generates ASDoc output</li>
+	</ul>
+	<li>The flexunit task which consists solely of the flexunit task</li>
+	<li>The junitreport task, which allows viewing of JUnit style reports</li>
+	<li>The delete task, which will be used as a clean target</li>
+	<li>Copy task, for copying files</li>
+	<li>Zip task, for zipping files</li>
+</ul>
+
+<h2>Hudson</h2>
+
+<p>A popular, open-source, continuous integration server, Hudson is simple to set up, configure and use. It can monitor multiple jobs, and through use of the FlexUnitAntTask, can make automating testing virtually a painless process.</p>
+<p>In order to use Hudson, it requires that Ant and/or Maven be installed on the CI system. It may be deployed through the .war file to an Apache, Tomcat, Glassfish or other HTTP server project. Hudson may also be used by way of the Windows service on a Windows machine, or integrated directly with many Linux distributions.</p>
+<p>For more information about Hudson and its capabilities, visit:</p>
+
+<a class='contentlink' href='http://hudson-ci.org' target='blank'>http://hudson-ci.org</a>
+
+<h2>Failure and Success reporting options</h2>
+
+<p>The FlexUnit Ant Task allows several options for test reporting</p>
+<ul>
+	<li><p>haltonfailure=true|false</p></li>
+	<ul>
+		<li><p>If true, when a failure or error is encountered will complete all currently executing tests then cancel the run</p></li>
+	</ul>
+	<li><p>verbose=true|false</p></li>
+	<ul>
+		<li><p>If true, reports the complete failure message for each failed test</p></li>
+		<li><p>If false, reports number of tests passed and failed only</p></li>
+	</ul>
+	<li><p>port=&#60;port results will be reported on, default is CIListener port&#62;</p></li>
+	<li><p>timeout=&#60;length of time to wait for runner to send results before considering test a failure&#62;</p></li>
+	<li><p>failureproperty=&#60;property name to set to <code>true</code> if any tests fail&#62;</p></li>
+</ul>
+
+<h2>Walkthrough 2: Running your tests from Hudson test launch</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Prepare a debug projector</li>
+	<li>Prepare an Ant build file</li>
+	<li>Install Ant and Hudson</li>
+	<li>Setup your environment to run tests from Hudson</li>
+</ul>
+
+<h3>Import the CI Project</h3>
+
+<ol>
+	<li>
+		<p>Import the FlexUnitTraining_wt2.fxp contained in Unit 16/Start folder.</p>
+		<p>Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Preparing the debug projector</h3>
+		
+	</li>
+	<li>
+		<p>Navigate to Unit 16/FlexUnitCI and find the file flashplayer_sa_win.exe (Windows users) or flashplayer_10_sa_debug.app.zip (Mac users). This is the debug version of the standalone FlashPlayer. Copy it to your local file system somewhere you will remember.</p>  
+		<p>In this walkthrough, you will associate swf files with the standalone, debug player. Failure to associate SWF files with a standalone FP will cause Ant builds to fail. This requires administrator privileges.</p>
+	</li>
+	<li>
+		<p>Windows Users: Return to the FlexUnitCI folder. Right-click on the TestSwf.swf and select <b>Open with...</b>. If an expanding menu appears, instead click <b>choose program</b>. This should open the following screen:</p>
+
+		<img alt='WindowsOpenWith' id='shift' src='../images/unit16/image1.jpeg' />
+
+		<p>Depending on your version, the dialog may appear slightly different.  Click on <b>Browse...</b> and select the standalone player you saved earlier.  Click OK.  The file will attempt to open and throw a SecurityError. This is normal. Click Dismiss and close the player.</p>
+		<p>Mac Users: Return to the FlexUnitCI folder. Right-click, or if using a single mouse button control-click, on the file <b>TestSwf.swf</b> and select <b>Get Info</b>. In this dialogue you will see a section titled <b>Open With</b>.</p>
+
+		<img alt='MacOpenWith' id='shift' src='../images/unit16/image2.png' /> 
+		<p>Select the drop down menu and click <b>Other...</b> When the browser box opens, navigate to the location you saved the debug player and select that file.</p>
+		
+		<h3><br />Prepare the Ant build file</h3>
+		
+		<p>Continuous integration projects require a build file.  Since you will be using Ant along with Hudson, you need a build.xml file.</p>
+	</li>
+	<li>
+		<p>Open the build.xml.</p>  
+		<p>You will need to make some modifications to this file for it to work with your project build. You will see a heading that reads: <b>Setup paths for build</b>.</p>  
+		<p>If you changed the organization of your project, make sure these paths reflect those changes.</p>
+		
+		<img alt='BuildPath' id='shift' src='../images/unit16/image3.png' />
+		
+		<p>You will also see a heading <code>&#60;!--Setup Flex and FlexUnit ant tasks --&#62;</code>.  Here you will need to modify the path locations of your tasks as well as set the <code>FLEX_HOME</code>.</p>
+	</li>
+	<li>
+		<p>First, navigate to your Flex SDK. In most cases, your Flex SDK should be located at root/Program Files/Adobe/Adobe Flash Builder 4/sdks.</p> 
+
+		<code><pre>&#60;property name="FLEX_HOME" 
+ location="rootpath:/Program Files/Adobe/Adobe Flash Builder 4/sdks/4.1.0/" /&#62;</pre></code>
+
+		<p>It is highly recommended you use Flex 4.1 SDK. Keep every directory in this walkthrough relative to the FLEX_HOME directory, this way the build file is guaranteed to reference these correctly.</p>
+
+		<h3><br />Install Ant and Hudson</h3>
+		
+	</li>
+	<li>
+		<p>Navigate to Unit 16/FlexUnitCI.  Copy this entire directory to the root drive.</p>  
+		<p>You may copy it to another location; however this guide assumes you have copied it to this location. If you do not, be sure to adjust all directory references to your installed location.</p>
+	</li>
+	<li>
+		<p>Navigate to the URL:  <a class='contentlink' href='https://hudson.dev.java.net/hudson.jnlp' target='_blank'>https://hudson.dev.java.net/hudson.jnlp</a></p>
+	</li>
+	<li>
+		<p>Choose to download and run the hudson.jnlp file.</p>
+		<p>After the Java Web Start has completed you should see a startup dialog:</p>
+ 
+		<img alt='HudsonConsole' id='shift' src='../images/unit16/image4.jpeg' />
+		
+		<p>This is the Hudson test drive. For our purposes this is sufficient. However, if you are running Hudson through your CI machine you will want to install the windows service or console app depending on your OS.</p>
+	</li>
+	<li>
+		<p>Open your browser and navigate to the <a class='contentlink' href='http://localhost:8080/' target='_blank'>http://localhost:8080/</a></p>
+		<p>You should see the Hudson start page.</p>		
+	</li>
+	<li>
+		<p>On the left is a menu of options. Click on <b>Manage Hudson</b> and navigate to <b>Configure System</b>. Here, you will need to specify the Ant location.</p>
+	</li>
+	<li>
+		<p>Go to the sub heading <b>Ant</b> and click the <b>Add Ant</b> button.  For the name, specify 'FlexUnit Intro Ant'. Uncheck <b>Install automatically.</b></p>
+	</li>
+	<li>
+		<p>In the <b>ANT_HOME</b> field, specify the install directory of your Ant installation. If you used the walkthroughs location, specify 'root/FlexUnitCI/Ant'.</p>
+		
+		<img alt='' id='shift' src='../images/unit16/image5.jpeg' />
+	</li>
+	<li>
+		<p>Navigate to the bottom of the page and click <b>Save</b>.</p>
+	</li>
+	<li>
+		<p>On the left hand menu, click <b>New Job</b>.</p>
+	</li>
+	<li>
+		<p>Give the job a name of FlexUnitCI Intro. Select <b>Build a free-style software project</b>. This version will allow you to build directly from an Ant script.</p>
+
+		<img alt='NewProjectPage' id='shift' src='../images/unit16/image6.jpeg' />
+		
+		<p>You will now see the new project page. You may at this time assign a description to the project. Take note of the Source Code Management settings.  The SCM is what will turn our build into a continually integrating project.  Normally we would specify our SCM and pass the location of the SCM. Hudson would then be pushed any changes to the repository and immediately execute a build. However, since we do not have any SCM for this project we will be executing manual builds.</p>
+	</li>
+	<li>
+		<p>Leave this option as <b>None</b>.</p>
+		
+		<img alt='None' id='shift' src='../images/unit16/image7.png' />
+	</li>
+	<li>
+		<p>Under the heading <b>Build</b>, add a new build step. Click on the drop down and select <b>Invoke Ant</b>. For the <b>Ant Version</b> select the <b>FlexUnit Intro Ant</b>.  Under <b>Targets</b> enter 'test'. This will cause Hudson to run the test target every time a build is run.</p>
+	</li>
+	<li>
+		<p>Click <b>Save</b>.</p>
+	</li>
+	<li>
+		<p>You should now be taken to the project homepage. Right now this project will do nothing. You need to specify a workspace.  To do so, select <b>Workspace</b> from the main screen. This can also be accessed from the menu on the left.</p>
+
+		<img alt='Workspace' id='shift' src='../images/unit16/image8.png' /> 
+
+		<p>You will receive an error:</p>
+
+		<img alt='Error' id='shift' src='../images/unit16/image9.jpeg' />
+		 
+		<p>This is completely expected. Hudson needs to execute a new build to configure the workspace.</p>
+	</li>
+	<li>
+		<p>Select <b>Run a build</b>.</p>  
+		<p>You should see new Build History menu on the left, it will update with the new build.  At completion, this build should fail (red dot indicates failure). The build will fail because the current target does not exist. However, the workspace setup is now complete.</p>
+	</li>
+	<li>
+		<p>Click on the workspace link in the left-hand menu again.</p>
+		<p>You should now see:</p>
+
+		<img alt='NoFiles' id='shift' src='../images/unit16/image10.jpeg' /> 
+		<p>Hudson is expecting the base directory of your project which should also contain the build.xml. Unfortunately, since we are not using a SCM, this directory will not populate correctly. We need to add the files directly to the workspace.</p>
+	</li>
+	<li>
+		<p><i>Windows</i>: Navigate to: C:/Documents and Settings/&#60;username&#62;/.hudson/jobs/FlexUnitCI Intro/workspace</p>  
+		<p><i>Mac</i>: Navigate to: Users/&#60;username&#62;/.hudson/jobs/FlexUnitCI Intro/workspace</p>
+	</li>
+	<li>
+		<p>This is the default location of the test launch workspace. Copy <b>all</b> files contained within the FlexUnit4Training project directory into this directory.</p>
+	</li>
+	<li>
+		<p>Refresh the Hudson page in your browser.</p>
+	</li>
+	<li>
+		<p>Hudson should now show the current contents of your project.</p>
+
+		<img alt='CurrentContents' id='shift' src='../images/unit16/image11.jpeg' /> 
+
+		<p>The project is now ready to be built. Since we are running this from the Test Launch and do not have a SCM specified, we will need to run manual builds.</p>
+	</li>
+	<li>
+		<p>Select <b>Build Now</b> from the menu on the left.</p>  
+		<p>Build now will force an immediate build on any files currently in the workspace.  This should return a success (blue dot on the left under build history.)</p> 
+
+		<img alt='BuildHistory' id='shift' src='../images/unit16/image12.jpeg' />
+		 
+		<p>During test execution, you will see the standalone player load with a blank screen. This is normal and will close automatically. Do not close this manually or your build may fail.</p>
+	</li>
+	<li>
+		<p>Click on <b>build #2</b>.</p> 
+		<p>This is the details view of the build. Since we have verbose set to true in the build file, we can view the details of each run.</p>
+	</li>
+	<li>
+		<p>Click on <b>Console Output</b>. Here will print detail of each test. Failures will also appear here.</p>
+		<p>Since JUnit reports were created for the test run, you may also view these.</p>
+	</li>
+	<li>
+		<p>Click on <b>Back to Project</b> in the left hand menu. Then click on <b>Workspace</b>. This will open the current workspace setup. Click on target then report then html. Select index.html to see the detailed JUnit report.</p>
+	</li>
+	<li>
+		<p>Congratulations, you have now completed your first Hudson test run.</p>
+		<p>Hudson will not auto build when new changes are made to the main project.  Because we had to copy the build files manually any new changes will also need to be manually copied. This is not necessary in a server version where a SCM tool has been specified for the project. Hudson will pull any new changes and create a new build automatically.</p>
+	</li>
+</ol>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-15.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-2.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-2.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-2.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,364 @@
+<!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>Overview of Testing Terms and Terminology</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/unit2.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 2 - Overview of Testing Terms and Terminology</h1>
+
+<p>While FlexUnit 4.x makes it easy for you to write clear and simple tests, you have to understand some of the basic terminology of unit testing frameworks, and specifically of FlexUnit, to become an effective user of this tool.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Explain unit testing, integration testing, and functional testing</li>
+	<li>Explain the role of metadata in FlexUnit 4.x testing</li>
+	<li>Explain testing framework and fixtures</li>
+	<li>Understand the difference between tests, test cases, and test suites</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Test Types</li>
+	<li>Metadata</li>
+	<li>Testing Framework</li>
+	<li>Assertions</li>
+	<li>Test / Test Case / Test Suite</li>
+	<li>Test Fixture</li>
+</ul>
+
+<h2>Test Types</h2>
+
+<p>Testing is a broad term and is applied by individuals in many different ways. Applications can be tested for security, performance and functionality. They may be tested before they are accepted by a user or tested for international deployment in multiple locales around the world.</p>
+<p>This course specifically deals with testing to ensure your code functions properly. In the simplest models, functionality is assured by three types of testing. Each type is performed at a different time during the development cycle.</p>
+
+<h3>Unit Testing</h3>
+
+<ul>
+	<li>Performed during development or immediately after</li>
+	<li>Tests the smallest blocks of code in complete isolation</li>
+	<li>Ensures the return values of functions are correct for expected input</li>
+	<li>Ensures that any side effects (other aspects of a class that change as the result of executing this block of code) are correct for the expected input</li>
+	<li>In general, you must have a unit test for each pathway or branch through your code. This means every <i>if-statement</i> guarantees two tests.</li>
+</ul>
+
+<h3>Integration Testing</h3>
+
+<ul>
+	<li>Also performed during development or immediately after</li>
+	<li>Eventually, in the development lifecycle, each testable unit is likely to interact with other testable units. Integration testing tests the interaction between testable units.</li>
+</ul>
+ 
+<h3>Functional Testing</h3>
+
+<ul> 
+	<li>Generally performed on an entire system or set of components</li>
+	<li>Tests expected behavior for the use cases of the application</li>
+	<li>Designed to test functional requirements</li>
+	<li>This can often be the easiest type of test to create; however, it is not as thorough or flexible as unit testing.</li>
+</ul>
+<p>This course focused mainly on unit testing but introduces some integration testing in later sections. Functional testing is beyond the scope of this class.</p>
+
+<h2>Metadata</h2>
+
+<p>Metadata provides additional information or a description of data. In Flex and ActionScript, metadata is most often used to provide additional information about a property, method or class. It can be interpreted by the compiler while building the application or by the development environment while writing code.</p>
+<p>Examples of metadata used in Flex include [Bindable], [Inspectable] and [Event]. [Bindable] instructs the pre-compiler to add additional code to a class to facilitate automated view updates when data changes. [Inspectable] and [Event] instruct the Flash Builder IDE in expected and available configuration options. This additional information allows the IDE to assist you with code completion and compile time type checking.</p>
+<p>To create a test using FlexUnit .9 or Fluint 1, you must extend a specific class and then name each method with the prefix <i>test</i>, such as <i>testMyFunction()</i>. Following this convention formed the basis of using these frameworks.</p>
+<p>Unlike its predecessors, FlexUnit 4 is a metadata driven framework. Rather than using a special naming convention for tests, FlexUnit 4 allows you to decorate a test using metadata.</p>
+
+<code><pre>[Test]
+public function shouldDoThis():void {
+}</pre></code>
+
+<p>This use of metadata removes the need to extend a specific class, or name your methods in a specific way. It provides more flexibility and opportunity.</p>
+<p>There are many metadata tags such as [Test], [Suite] and [Theory] used to mark classes, methods or properties when using FlexUnit 4.</p>
+
+<h2>Testing Frameworks</h2>
+
+<p>You can test without a testing framework, and you likely already do. Each time you write a piece of code, execute it and check for an expected outcome, you are performing the same tasks as a testing framework.</p>
+<p>A testing framework only exists to automate these manual operations. It codifies assumptions about the way a piece of code will work into a series of test method, including the code's expected return value, side effects and exceptions in a given situation.</p>
+<p>When those methods are executed, the testing framework verifies the result of the execution and reports the results. This provides a standard way in which users can execute and share tests.</p>
+<p>FlexUnit.9, Fluint and FlexUnit 4.x are properly referred to as testing frameworks. The same is true for ASUnit, or the JUnit and TestNG frameworks written for Java.</p>
+
+<h2>Assertions</h2>
+
+<p>Assertions are a tool used to reveal whether or not a piece of code is working as expected. They take the form of a strong statement indicating an expected result. For example, if you add the numbers 2 and 3.</p>
+<code><pre>result = 2 + 3;</pre></code>
+<p>You can assert that the result is 5. You do so as you are sure that no other answer is satisfactory and that a different answer is just plain wrong.</p> 
+<code><pre>assertEquals( 5, result );</pre></code>
+<p>If this assertion fails, meaning that <code>result</code> is not equal to <code>5</code>, then you can conclude that the plus operator no longer works correctly in all cases. This is the basis of testing.</p>
+
+<h2>Tests</h2>
+
+<p>Ultimately, assertions are the atom of a test. However, an assertion is only applicable to a given condition. The assertion made in the previous section only applies because the numbers 2 and 3 were added.</p> 
+
+<code><pre>result = 2 + 3;
+assertEquals( 5, result );</pre></code>
+
+<p>If instead, the numbers 6 and 7 were added, a different assertion is needed, and this is the point of a test. A test sets up the necessary preconditions in order to make an assertion. Ideally, you will have one test for every possible branch in your class.</p>
+<p>Continuing with the addition example, you would likely have tests to:</p>
+<ol>
+	<li>add two positive numbers</li>
+	<li>add a positive and a negative number</li>
+	<li>add two negative numbers</li>
+	<li>add 0 to a number</li>
+	<li>add NaN to a number</li>
+	<li>add positive or negative infinity to a number</li>
+</ol>
+<p>Collectively all of the tests in a system, each making assertions, verify that the units of the system individually work as intended.</p>
+<p>Even in the simplest cases, each unit of code generally requires at least two tests: one test to check positive results with valid inputs and another to check negative results with invalid input.</p>
+<p>Most units will require more than two tests. It is best to test both positive and negative outcomes against a variety of inputs, strengthening the coverage of the test.</p>
+
+<h2>Test Cases</h2>
+
+<p>A test case is a collection of tests contained within one class that is designed to test related functionality. Often, a single test case tests a single class.</p>
+<p>Continuing with the mathematics example, a test case might contain the following collection of test methods:</p>
+
+<code><pre>[Test]
+public function shouldAddTwoPosAndReturnPos() {
+}
+
+[Test]
+public function shouldAddPosAndNegAndReturnPos() {
+}
+
+[Test]
+public function shouldAddPosAndNegAndReturnNeg() {
+}
+
+[Test]
+public function shouldAddTwoNegReturnNeg() {
+}
+
+[Test]
+public function shouldReturnSamePosWhenAdd0() {
+}
+
+[Test]
+public function shouldReturnSameNegWhenAdd0() {
+}</pre></code>
+
+<p>Again, all tests in a given case should be related, either by the fact that they test the same class or the same concept across multiple classes.</p>
+<p>The test case may also specify the order of every test in a test case as well as exclude certain tests from running in specific circumstances. While unit tests may be ordered they should <b>never</b> depend on an order. In other words, if Test A <b>must</b> run before Test B, as Test A does some setup or precondition, you are no longer writing unit tests. Unit tests are isolated, and relationships are not a component of isolation.</p>
+
+<code><pre>[Test(order=1)]
+public function shouldReturnSamePosWhenAdd0() {
+}
+
+[Test(order=2)]
+public function shouldReturnSameNegWhenAdd0() {
+}</pre></code>
+
+<p>As FlexUnit 4.x only executes methods marked with the [Test] metadata as tests, you can also add support methods for doing additional work in your class. This will become clearer as the course continues.</p>
+
+<h2>Test Fixture</h2>
+
+<p>The term <i>test fixture</i> refers to a well-known and fixed environment required to run a repeatable test. This environment, also referred to as a <i>test context</i>, is recreated before each test.</p>
+<p>For example, if a given object must exist before your test can run, then that object is part of the test fixture.  A fixture contains everything that must be in a known state before the tests in the test case can be executed.</p>
+
+<code><pre>[Test]
+public function shouldBeBlueSky():void {
+	var sky:Sky = new Sky();
+	sky.color = "blue";
+
+	assertTrue( sky.color == "blue" );
+}</pre></code>
+
+<p>In the example, the <code>assertTrue()</code> statement checks if the sky's color is blue. Notice that you must first have a Sky object before the value of its color can be tested. It is effectively a precondition to the test.</p>
+<p>A fixture can create objects, set initial values, or perhaps even create substitute (you will learn to call these fake or mock) objects for use during testing. A well-formed test fixture can greatly decrease the time for adding new tests to a test case by factoring out code performed in each test to a common location.</p>
+<p>Test cases should create all the elements required to create the fixture. No test case should ever reach outside of its class for objects instantiated elsewhere for use in its tests.</p> 
+
+<h2>Test Suites</h2>
+
+<p>A test suite is used to group test cases together for ease of handling. As your collection of test cases grows, it becomes more and more convenient to group these in a hierarchical fashion.</p>
+<p>For example, all of your addition tests are in one test case. All of your subtraction tests might be in another. You can then create a suite which includes both of these cases. You can then instruct the testing framework to execute all tests in that suite.</p>
+<p>Suites can also be included within other suites and can be run recursively from higher level suites. This usually results in single top-level suite that runs other suites, which can run suites or test cases of their own. This allows for ease of organization as the number of cases and suites increase.</p>
+
+<h2>Walkthrough 1: Creating and Executing a Unit test</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Import the FlexUnit4Training.fxp file into Flash Builder.</li>
+	<li>Write a single test method.</li>
+	<li>Run a unit test case.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Start Flash Builder by choosing Start &#62; Programs &#62; Adobe &#62; Adobe Flash Builder.</p>
+	</li>
+	<li>
+		<p>From the main menu of Flash Builder, choose File &#62; Import &#62; Flash Builder Project.   Flash Builder has the ability to import pre-existing projects packaged in the FXP format as a stand-alone file.</p>
+	</li>
+	<li>
+		<p>In the Import Flash Builder Project dialog box that opens, click the first Browse button on the right of the screen. Navigate to the LocationContainingFXPFile/Unit 2/Start directory, and select the FlexUnit4Training.fxp file.</p>
+		<p>The screen will change to show new Import method options with either "Import new copy of project" or "Overwrite existing project."</p>
+	</li>
+	<li>
+		<p><b>If this is your first time opening the project:</b><br />
+		   Choose "Import new copy of Project" and extract the project to your Flash Builder workspace. Making sure to replace "LocationContainingFXPFile" and "YourFlexWorkspace" with the location of the FXP file on your machine and your preferred directory for Flex projects (See Figure 1).</p>
+
+		<p><b>If you have previously imported the FlexUnit4Training project:</b><br />
+		   Choose "Overwrite existing project" and select the FlexUnit4Training project from the dropdown (See Figure 2).</p>
+		
+		<img alt='ImportFlexProject' id='shift' src='../images/unit2/image1.png' />
+		<p class='caption' id='shift'>Figure 1: Importing a new project</p>
+		
+		<img alt='OverwriteFlexProject' id='shift' src='../images/unit2/image2.png' />
+		<p class='caption' id='shift'>Figure 2: Overwriting an existing project</p>
+		
+		<p>Once the project has been imported, it should appear in the Package Explorer on the left.</p>
+	</li>
+	<li>
+		<p>In the Package Explorer, expand the src folder's default package and double-click the FlexUnit4Training.mxml file to open it. The contents of this file will be explored in more detail in a future unit.</p>
+		
+		<img alt='PackageExplorer' id='shift' src='../images/unit2/image3.png' />
+		<p class='caption' id='shift'>Figure 3: Opening files in the Package Explorer</p>
+	</li>
+	<li>
+		<p>In the <code>&#60;fx:Script&#62;</code> block, you should see the following lines:</p>
+		
+		<code><pre>import math.testcases.BasicCircleTest;
+
+public function currentRunTestSuite():Array {
+	var testsToRun:Array = new Array();
+	testsToRun.push( BasicCircleTest );
+	return testsToRun;
+}
+
+private function onCreationComplete():void {
+	testRunner.runWithFlexUnit4Runner(currentRunTestSuite(),
+"FlexUnit4Training");
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>To open the <code>BasicCircleTest</code> class, you can either browse to it in the Package Explorer (test/math.testcases.BasicCircleTest), or you can move your mouse over the <code>BasicCircleTest</code> text in the line that reads <code>testsToRun.push( BasicCircleTest )</code>. Press control, when you see the <code>BasicCircleTest</code> turn blue, click on <code>BasicCircleTest</code>. Either way, this will open the <code>BasicCircleTest</code> class in Flash Builder.</p>
+	
+		<img alt='ControlClick' id='shift' src='../images/unit2/image4.png' />
+		<p class='caption' id='shift'>Figure 4: Control Clicking BasicCircleTest</p>
+		
+		<p>The class should read as follows.</p>
+		
+		<code><pre>package math.testcases {	
+	public class BasicCircleTest {		
+		
+	}
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a new public function named <code>shouldReturnProvidedRadius()</code> to the class. The function needs to be marked with <code>[Test]</code> metadata, which is placed on the line just above the function.</p>
+
+		<code><pre>public class BasicCircleTest {		
+	[Test]
+	public function shouldReturnProvidedRadius():void {
+
+	}
+}		</pre></code>
+		
+		<p>This function is going to test a method of the <code>Circle</code> class. The <code>Circle</code> object is created by the <code>Circle</code> constructor which takes an origin argument of type <code>Point</code> and a radius argument of data type <code>Number</code>.</p>
+		
+		<code><pre>Circle( origin:Point, radius:Number );</pre></code>
+		
+	</li>
+	<li>
+		<p>Declare a variable named <code>circle</code> of type <code>Circle</code> in the <code>shouldReturnProvidedRadius()</code> function. This Circle should be instantiated with an origin of <code>(0, 0)</code> and a radius of <code>5</code>.</p>
+
+		<code><pre>[Test]
+public function shouldReturnProvidedRadius():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+}		</pre></code>
+		
+		<p>While you are typing <code>Circle</code>, Flash Builder will try to provide possible choices as you type. If you choose one of the items on the pop-up menu (or use the arrow keys and press Enter on the correct option), Flash Builder will complete the name for you and perform one other very important step: importing the class.</p>
+		<p>If you choose one of the options on the pop-up menu, Flash Builder adds an import line just above the class definition. This line is an import statement that lets Flash Builder know where the class you are referencing resides. You can think of import statements as more or less the ActionScript equivalent of the namespaces you used in MXML:</p> 
+		<code><pre>import net.digitalprimates.math.Circle;</pre></code>
+		<p>and</p>
+		<code><pre>import flash.geom.Point;</pre></code>
+		<p>If you do not have these lines in your file, you have two options: You can place your cursor right after the closing e in Circle and t in Point and press Ctrl+Spacebar. This will cause Flash Builder to open the code-completion pop-up again. If there is only one matching option, Flash Builder automatically selects it and adds the import for you. Alternatively, you can just type the import statements just inside the package, outside of the class definition.</p>
+	</li>
+	<li>
+		<p>Just below the circle instantiation, add a line that calls to the <code>assertEquals()</code> method with arguments <code>5</code> and <code>circle.radius</code>.</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>If you did not use code completion, add the import statement for <code>org.flexunit.asserts.assertEquals</code> at this time. While you may be used to importing classes, <code>assertEquals()</code> is actually a package level function. These are functions that can be addressed directly without an associated class. While this concept may be new to many of you, it is actually used extensively in Flash Player with methods such as <code>trace()</code>, <code>getDefinitionByName()</code> and <code>setInterval()</code>.</p>
+	</li>
+	<li>
+		<p>Save the BasicCircleTest.as file.</p>
+	</li>
+	<li>
+	 	<p>Reopen the FlexUnit4Training.mxml file using the navigator view on the left.</p> 
+	</li>
+	<li>
+		<p>Click on the run button in the upper toolbar as shown.</p>
+		
+		<img alt='RunButton' id='shift' src='../images/unit2/image5.png' />
+		<p class='caption' id='shift'>Figure 5: The Flash Builder "Run" Button</p>
+
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+		
+		<img alt='TestPassed' id='shift' src='../images/unit2/image6.png' />
+		<p class='caption' id='shift'>Figure 6: FlexUnit test passed</p>
+	</li>		
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li><p>There are many types of tests, including:</p></li>
+	<ul>
+		<li><p>Unit Tests</p></li>
+		<li><p>Integration Tests</p></li>
+		<li><p>Functional Tests</p></li>
+		<li><p>Performance Tests</p></li>
+	</ul>
+	<li><p>Unit testing is about testing isolated blocks of code.</p></li>
+	<li><p>FlexUnit 4 defines a test method with the [Test] metadata.</p></li>
+	<li><p>Tests make one or more assertions.</p></li>
+	<li><p>A class with one or more tests is called a Test Case.</p></li>
+	<li><p>A Test Fixture includes all the elements needed to provide the correct environment for repeatable testing.</p></li>
+	<li><p>A Test Suite is a collection of Test Cases.</p></li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-3.html" class="next"></a>
+			<a href="Unit-1.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