flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r902467 [6/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-3.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-3.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-3.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,118 @@
+<!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 Capabilities</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">
+				
+			</div>
+			<div id="content">
+
+<h1>Unit 3 - FlexUnit Capabilities</h1>
+
+<p>Flexunit 4.x was designed to address many of the shortcomings of available Flex testing frameworks while enabling the extensibility needed by an evolving Flex community.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Explain the role of listeners, runners, and rules</li>
+	<li>Explain the roles of the default runners available in FlexUnit 4.x</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Goals of FlexUnit 4</li>
+	<li>Integration Points</li>
+	<li>Extensibility</li>
+	<li>Integration with other frameworks</li>
+	<li>Provided Runners</li>
+</ul>
+
+<h2>Goals of FlexUnit 4.x</h2>
+
+<p>FlexUnit 4.x is an extensible testing framework designed to provide unit and integration testing to its users. It was designed with several important goals in mind:</p>
+<ul>
+	<li>It needed to handle both ActionScript and Flex projects.</li>
+	<li>It needed to run legacy FlexUnit .9 tests.</li>
+	<li>It needed to run legacy Fluint 1.x tests.</li>
+	<li>It needed to provide test results to a continually growing variety of external systems.</li>
+	<li>It needed to reach parity with modern testing frameworks for other languages.</li>
+	<li>It needed to support future expansion without another complete rewrite.</li>
+	<li>It needed to be extensible by individuals for their own types of testing.</li>
+</ul>
+<p>It achieves these goals through the use of several concepts referred to as runners, rules and listeners which you will explore in this unit.</p> 
+
+<h2>Integration Points</h2>
+
+<p>FlexUnit is simply a testing framework responsible for executing user-created tests. It neither has a user interface for reporting the failure of specific tests to its users nor a way to launch a new test run. Instead, FlexUnit provides simple integration points for other tools and applications to use its capabilities and monitor the results.</p>
+<p>This integration occurs mainly through the concept of listeners. Listeners allow an external class to register with the FlexUnit framework and receive progress notifications as tests progress. This progress information includes key data such as when a test begins, ends and how much time it took to execute. It also provides information about the success and failure of each test, with additional information provided about the cause of any failure.</p>
+<p>Developers can use this information to provide simple visual representations of test status, such as the UIListener project (available on FlexUnit.org), or complex interactive pieces. The Adobe Flash Builder 4, IntelliJ and FDT integrated development environments have all used this same technique to provide advanced testing integration to their users.</p>
+<p>It should be noted that the FlexUnit team only maintains the testing framework and directly associated projects. Features and continuing integration into the IDEs mentioned above is solely at the discretion and hard work of teams at these companies.</p>
+
+<h2>Extensibility</h2>
+
+<p>A major goal of FlexUnit 4 was the ability to add new testing features in the future without the need for another rewrite. Further, it was important that developers be able to add new testing features for their own specific use cases that they may not be able to share nor wish to contribute back to the project. FlexUnit 4 provides this capability via two concepts: runners and rules.</p>
+<p>A runner is a class which contains the necessary functionality to find and execute tests in a specific class. As you will continue to learn throughout this course, there are many types of tests ranging from simple static tests to those requiring parameters and data points.</p>
+<p>With FlexUnit 4, developers are allowed to create their own runners for any unique circumstance present in their environment and register that runner with the testing framework. This allows a developer to replace the specific functionality around test execution but still maintain all of the integration with tools and IDE provided by the FlexUnit team.</p>
+<p>Creating an entirely custom runner is a powerful but complex feature of FlexUnit. However, if you simply need to add additional features to the existing FlexUnit runners, you can use a concept called rules.</p>
+<p>Rules allow you to 'bolt-on' additional functionality to the existing runners, giving developers the opportunity to execute additional code before and after tests or add extra layers of evaluation and comparison not present in the existing framework.</p>
+<p>Later in this course you will use a rule implementation to handle mocking of objects during testing.</p>
+
+<h2>Integration with other frameworks</h2>
+
+<p>While FlexUnit 4 provides significant new features, there are many thousands of unit tests written in the original FlexUnit and Fluint framework which developers are rightfully reluctant to migrate. To allow developers access to these new features, it was necessary to run the existing unit tests precisely as they executed today without changes to timing or other errors that could be introduced in a port of these technologies.</p>
+<p>Instead, FlexUnit 4 uses the concept of the runner, explained above, to wrap the entire FlexUnit .9 and Fluint frameworks. This means that when FlexUnit 4 encounters a legacy test, it instantiates the original framework and uses that object to execute that particular test.</p>
+<p>Quite literally, the entire FlexUnit .9 and Fluint frameworks are available inside of FlexUnit 4.x as runners which can be used at anytime to ensure that legacy tests are executed precisely as originally intended.</p>
+
+<h2>Provided Runners</h2>
+
+<p>Although FlexUnit 4.x is intended to be extended by developers as needed, it still ships with a rich set of available test runners. These runners provide the ability to run a variety of test types. Standard runners include:</p>
+<ul>
+	<li>Fluint1ClassRunner which executes Fluint 1.x test classes. *</li>
+	<li>FlexUnit1ClassRunner which executes FlexUnit .9 test classes.</li>
+	<li>BlockFlexUnit4ClassRunner the default runner for FlexUnit 4.x with features and functionality that you will use throughout this course.</li>
+	<li>Suite which executes FlexUnit 4 Suite classes.</li>
+	<li>ParameterizedRunner which executes test cases that use parameterized data.</li>
+	<li>TheoryBlockRunner which executes a special type of test case called a Theory.</li>
+	<li>IgnoredRunner which understands how to ignore and skip tests and test cases marked with special [Ignore] metadata.</li>
+</ul>
+<p style='font-size:0.9em;'>* Note: Due to the nature of Fluint, this runner is only available with the Flex-specific version of FlexUnit.</p>
+
+<h2>Summary</h2>
+
+<ul>
+	<li>FlexUnit 4 was designed with a priority on extensibility.</li>
+	<li>Extensibility is achieved through the use of runners, listeners and rules.</li>
+	<li>FlexUnit 4 has built in support for FlexUnit .9 and Fluint 1.</li>
+	<li>Support for additional testing frameworks may be integrated by an individual developer or by the FlexUnit team.</li>
+	<li>Adding additional support does not require any change to the FlexUnit 4 framework.</li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-4.html" class="next"></a>
+			<a href="Unit-2.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-4.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-4.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-4.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,728 @@
+<!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 Basics</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/unit4.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 4 - FlexUnit Basics</h1>
+
+<p>FlexUnit 4.x tests are simply methods that are decorated with special metadata. They setup conditions, execute code and make assertions about expected results.</p> 
+<p>These methods are grouped together by common themes and executed often to ensure consistent, functional code.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Explain the basics of unit tests and test metadata</li>
+	<li>Perform basic assertions in multiple unit tests</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Testing a unit</li>
+	<li>Examining a test</li>
+	<li>Creating tests</li>
+</ul>
+
+<h2>Testing a Unit</h2>
+
+<h3>Understanding a Unit</h3>
+
+<p>A unit is the smallest block of code that can be isolated and tested independently.</p> 
+<p>Suppose you had a table lamp that was not working properly. You might first try changing the light bulb to see if that fixes the issue. Perhaps you would try that light bulb in another fixture or move the lamp to another room to try another outlet. These are all steps to isolate a problem and realizations of the idea behind testing units.</p>
+<p>When the lamp is fully assembled with light bulb in place and plugged into the wall it is not possible to definitively see where an issue might exist. There could be an issue with the outlet, cord, switch, wiring or bulb. You can only begin to determine the problem by isolating one system at a time and testing it. If you could not change the light bulb, move the lamp, or disassemble it, your ability to test would only be at the whole system level. This likely means you throw away your lamp each time the bulb burns out.</p>
+<p>While a lamp is a relatively simple example, the average class in your application is likely not. To be able to test a class properly, you need to ensure it is capable of being isolated and then test each piece in an isolated fashion.</p>
+<p>To successfully unit test a class, you will:</p>
+<ul>
+	<li>Generally write at least one test for each method of a class.</li>
+	<li>Write one test for every possible outcome of a method with conditional logic.</li>
+	<li>Test both valid/expected and invalid/unexpected input to your methods.</li>
+</ul>
+<p>This is only possible if you can test one isolated object at a time.</p>
+
+<h3>The Need for Seams</h3>
+
+<p>We call the point where objects can be separated from each other seams. Continuing with the lamp example, the light bulb socket and wall plug are both seams. Seams allow us to isolate an object and ensure that we are only testing one object at a time.</p>
+<p>Let's examine the following piece of code:</p>
+
+<code><pre>public class TestSeams {
+	private var someMathObj:SomeMathClass = new SomeMathClass();
+
+	public function findDistance( a:Number, b:Number ):Number {
+		var difference:Number = ( b - a );
+		var distance:Number = someMathObj.abs( difference );
+		return distance;
+	}
+}</pre></code>
+
+<p>Unfortunately, you cannot test the <code>findDistance()</code> method alone. That method depends upon <code>SomeMathClass</code> and its <code>abs()</code> function. Therefore, it cannot be isolated. Any attempt to test this method results in testing the code in the TestSeams class, an unknown amount in the SomeMathClass, and the integration between the classes.</p>
+<p>When creating new code you must keep the need for seams in mind. Not only does it facilitate testable code, it also has the side effect of creating loosely coupled code with a minimum of interwoven dependencies.</p>
+
+<h3>Examining the Circle Class and the Circle Layout</h3>
+
+<p>Let's take a look at the Circle class and the <code>getPointOnCircle()</code> method.</p>
+
+<code><pre>public function getPointOnCircle( t:Number ):Point {
+	var x:Number = origin.x + ( radius * Math.cos( t ) );
+	var y:Number = origin.y + ( radius * Math.sin( t ) );
+
+	return new Point( x, y );
+}</pre></code>
+
+<p>In this unit of code:</p>
+<ul>
+	<li>The method takes a single argument, <code>t</code>.</li>
+	<li>The method calculates the point on a circle using the <code>origin</code> and <code>radius</code> properties.</li>
+	<li>The <code>origin</code> and <code>radius</code> properties are set in the Circle class constructor.</li>
+	<li>The method depends upon the static Math class, which is unfortunate. It could use better seams but is typical of methods you might encounter in real world classes.</li>
+</ul>
+<p>A unit test for <code>getPointOnCircle()</code> would need to test:</p>
+<ul>
+	<li>For a given t, origin, and radius, does the returned point match what is expected?</li>
+	<li>What happens when invalid values of t, origin, and radius are provided to this method?</li>
+</ul>
+<p>As you can see, most units will need more than one test to fully validate the unit's function.</p>
+<p>Here is a unit from the CircleLayout class:</p>
+
+<code><pre>public function getLayoutRadius( contentWidth:Number, contentHeight:Number ):Number {
+	var maxX:Number = (contentWidth/2)*.8;
+	var maxY:Number = (contentHeight/2)*.8;
+	var radius:Number = Math.min( maxX, maxY );
+
+	return Math.max( radius, 1 );
+}</pre></code>
+
+<p>While not perfect, this unit has a couple testing advantages over the previous method:</p>
+<ul>
+	<li>All the required values for the computation are passed as arguments.</li>
+	<li>Save for the Math class, this method has no external dependencies.</li>
+</ul>
+<p>A unit test for this method would need to test:</p>
+<ul>
+	<li>For a given set of <code>contentWidth</code> and a <code>contentHeight</code>, is the proper value returned?</li>
+	<li>If an invalid <code>contentWidth</code> or <code>contentHeight</code>, does the expected behavior occur?</li>
+</ul>
+
+<h3>Examining a Test Case</h3>
+
+<p>As you learned in the previous unit, a test case is merely a collection of individual test methods that test related behaviors. Each of the methods of a test case is decorated with [Test] metadata to signal to the FlexUnit framework that a method is a test. The [Test] metadata tag can also accept user defined attributes for descriptive and organizational purposes</p>
+
+<code><pre>[Test(description="Test is supposed to fail",issueID="0012443")]
+
+public function thisTestFails():void {}</pre></code>
+
+<p>or system-defined attributes that provide further instructions to FlexUnit when it runs the test.</p>
+<p>A test fixture comprises all of the state required to evaluate your test methods. For example, in the following test:</p>
+
+<code><pre>[Test]
+public function shouldComputeCorrectDiameter():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 ); 
+	assertEquals( 10, circle.diameter );
+}</pre></code>
+
+<p>The existence of the Circle is necessary for the assertion and can therefore be considered part of your test fixture.</p>
+
+<h2>Walkthrough 1: Adding Tests to a Case</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Add tests to the BasicCircleTest case.</li>
+	<li>Run the case with the new 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 4/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+	</li>
+	<li>
+		<p>Add seven new public functions to the class right under the <code>shouldReturnProvidedRadius()</code> function. They should be named <code>shouldComputeCorrectDiameter()</code>, <code>shouldReturnProvidedOrigin()</code>, <code>shouldReturnTrueForEqualCircle()</code>, <code>shouldReturnFalseForUnequalOrigin()</code>, <code>shouldReturnFalseForUnequalRadius()</code>, <code>shouldGetPointsOnCircle()</code>, and <code>shouldThrowRangeError()</code>.</p>
+		<p>Mark each function with <code>[Test]</code> metadata.</p>
+		
+		<code><pre>[Test]
+public function shouldComputeCorrectDiameter():void {
+}
+
+[Test]
+public function shouldReturnProvidedOrigin():void {
+}
+
+[Test]
+public function shouldReturnTrueForEqualCircle():void {	
+}
+
+[Test]
+public function shouldReturnFalseForUnequalOrigin():void {
+}
+
+[Test]
+public function shouldReturnFalseForUnequalRadius():void {
+}
+
+[Test]
+public function shouldGetPointsOnCircle():void {	
+}
+
+[Test]
+public function shouldThrowRangeError():void {	
+}		</pre></code>
+	</li>
+	<li>
+		<p>Although you have written out seven methods, only the first five are going to be used in this walkthrough. Within <code>shouldComputeCorrectDiameter()</code>, <code>shouldReturnProvidedOrigin()</code>, <code>shouldReturnTrueForEqualCircle()</code>, <code>shouldReturnFalseForUnequalOrigin()</code>, and <code>shouldReturnFalseForUnequalRadius()</code> declare a local variable named <code>circle</code> of type <code>Circle</code>. Instantiate <code>circle</code> with an origin Point at <code>(0, 0)</code> and a radius of <code>5</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldComputeCorrectDiameter():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 ); 
+}
+
+[Test]
+public function shouldReturnProvidedOrigin():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 ); 
+}
+
+[Test]
+public function shouldReturnTrueForEqualCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );	
+}
+
+[Test]
+public function shouldReturnFalseForUnequalOrigin():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );	
+}
+
+[Test]
+public function shouldReturnFalseForUnequalRadius():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );	
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Just below the circle instantiation in the <code>shouldComputeCorrectDiameter()</code> method, add a line that calls to the <code>assertEquals()</code> method with arguments <code>10</code> and <code>circle.diameter</code>.</p> 
+		
+		<code><pre>[Test]
+public function shouldComputeCorrectDiameter ():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 ); 
+	assertEquals( 10, circle.diameter );
+}		</pre></code>
+	
+	</li>
+	<li>
+		<p>Just below the circle instantiation in the <code>shouldReturnProvidedOrigin()</code> method, add two lines that each call the <code>assertEquals()</code> method. This test requires two assertion statements because it will check the x and y coordinates' equality to 0, each on a different line.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnProvidedOrigin():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 ); 
+	assertEquals( 0, circle.origin.x );
+	assertEquals( 0, circle.origin.y );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a new local variable named <code>circle2</code> of type <code>Circle</code> to the <code>shouldReturnTrueForEqualCircle()</code> method. Instantiate <code>circle2</code> with an origin of <code>(0, 0)</code> and radius of <code>5</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnTrueForEqualCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var circle2:Circle = new Circle( new Point( 0, 0 ), 5 );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a new line to the <code>shouldReturnTrueForEqualCircle()</code> function that calls to the <code>assertTrue()</code> method with the argument <code>circle.equals( circle2 )</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnTrueForEqualCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var circle2:Circle = new Circle( new Point( 0, 0 ), 5 );
+
+	assertTrue( circle.equals( circle2 ) );	
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the import for org.flexunit.asserts.assertTrue at this time.</p>	
+	</li>
+	<li>
+		<p>Add a variable named <code>circle2</code> of type <code>Circle</code> to the <code>shouldReturnFalseForUnequalOrigin()</code> method. Instantiate <code>circle2</code> with an origin of <code>(0, 5)</code> and a radius of <code>5</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnFalseForUnequalOrigin():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var circle2:Circle = new Circle( new Point( 0, 5 ), 5 );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a call to the <code>assertFalse()</code> method. The statement <code>circle.equals( circle2 )</code> should be passed in as its argument.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnFalseForUnequalOrigin():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var circle2:Circle = new Circle( new Point( 0, 5 ), 5);
+
+	assertFalse( circle.equals( circle2 ) );
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the import for org.flexunit.asserts.assertFalse at this point.</p>
+	</li>
+	<li>
+		<p>Add a variable named <code>circle2</code> of type <code>Circle</code> to the <code>shouldReturnFalseForUnequalRadius()</code> method. Instantiate <code>circle2</code> with an origin of <code>(0, 0)</code> and a radius of <code>7</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnFalseForUnequalRadius():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var circle2:Circle = new Circle( new Point( 0, 0 ), 7);
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add a call to the <code>assertFalse()</code> method. The expression <code>circle.equals( circle2 )</code> should be passed in as its argument.</p>
+		
+		<code><pre>[Test]
+public function shouldReturnFalseForUnequalRadius():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var circle2:Circle = new Circle( new Point( 0, 0 ), 7);
+
+	assertFalse( circle.equals( circle2 ) );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save the BasicCircleTest.as file.</p>
+	</li>
+	<li>
+		<p>Re-Open the FlexUnit4Training.mxml file. Click the run button in the upper toolbar.</p> 
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+		
+		<img alt='UnitsPassed' id='shift' src='../images/unit4/image1.png' />
+		
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed.</p>
+	</li>
+</ol>
+
+<h2>Creating tests</h2>
+
+<h3>Examining a passing test</h3>
+
+<p>In the section above you used assertions to establish several passing tests. Many took the same form as this simple math example:</p>
+
+<code><pre>[Test]
+public function testAddition():void {
+	var num1:Number = 5;
+	var num2:Number = 3;
+	var total:Number = 8;
+
+	assertEquals( total, num1 + num2 );
+}</pre></code>
+
+<ul>
+	<li>5 and 3 are expected to add up to 8.</li>
+	<li>The tests <b>assert</b> this expectation using the <code>assertEquals()</code> method</li>
+	<li>Since 5 + 3 == 8, this test will pass.</li>
+</ul>
+
+<h3>Performing basic assertions</h3>
+
+<p>Assertions allow us to specify expected conditions that help determine whether a test passes or fails. They are statements that evaluate to true or false. If you make an assertion that is false under the conditions you have set up, the test fails. If all of the assertions in the test are true, the test passes.</p>
+<p>FlexUnit provides many assertion methods to use in your test methods. You might use an assertion to state that you expect a value to be true or false, null or not null, equal to another variable, or simply not in a list of acceptable values.</p>
+<p>The three most common assertions in FlexUnit 4 are:</p>
+<ul>
+	<li><code>assertTrue( condition:Boolean )</code> - Asserts that a condition is true. This passes if the condition is true.</li>
+	<li><code>assertFalse( condition:Boolean )</code> - Asserts that a condition is false. This passes if the condition is false.</li>
+	<li><code>assertEquals( value1:Obj, value2:Obj )</code> - Asserts that two objects are equal. This passes if value1 == value2.</li>
+</ul>
+<p>If all of the assertion in a test evaluate correctly, that test is added to the list of passed tests. If any assertion fails, it throws an <code>AssertionError</code>. FlexUnit handles the error and adds the test to a list of failed tests.</p>
+ 
+<h3>Examining a failed test</h3>
+
+<p>Consider this slightly modified <code>testAddition()</code> method:</p>
+
+<code><pre>[Test]
+public function testAddition():void {
+	var num1:Number = 5;
+	var num2:Number = 3;
+	var total:Number = 1000;
+
+	assertEquals( total, num1 + num2 );
+}</pre></code>
+
+<ul>
+	<li>The test asserts that 5 + 3 == 1000.</li>
+	<li>This test will fail as your assertion is false.</li>
+</ul>
+<p>FlexUnit 4.x catches the <code>AssertionError</code> that is thrown when this test fails, and the following result is displayed within the FlexUnit Results window in Flash Builder:</p>
+
+<code><pre>
+"expected: &#60;1000&#62; but was: &#60;8&#62;"
+</pre></code>
+
+<p>A test will be registered as a failure after the <i>first</i> instance of a failed assertion.  FlexUnit will not continue to evaluate the other assertions in the method. This means that if multiple assertions are written in a single test you will only receive notification of the first failure and the others will be in an unknown state.</p>
+
+<code><pre>[Test]
+public function testAddition():void {
+		var num1:Number = 5;
+		var num2:Number = 3;
+		var total:Number = 1000;
+
+		assertEquals( total, num1 + num2 );
+		assertEquals( num1 + num2, total );
+}</pre></code>
+
+<p>For example, both of these assertions would fail given the opportunity.  However, as soon as FlexUnit catches the first failed assertion it stops the test.  The second assert will never be called.  The error message would read:</p>
+
+<code><pre>
+"expected: &#60;1000&#62; but was: &#60;8&#62;"
+</pre></code>
+
+<p>With multiple assertions in a test, a test can fail for one of several reasons. In diagnosis, it is not immediately clear what caused the test to fail.</p>
+ 
+<h2>Walkthrough 2: Failing and Passing Assertions</h2>
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Add multiple assertions to a test method.</li>
+	<li>Run the test case.</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 4/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3>Write multiple assertions for a test method</h3>
+		
+	</li>
+	<li>
+		<p>In the <code>shouldGetPointsOnCircle()</code> method, create a local variable named <code>circle</code> of type <code>Circle</code>. 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 shouldGetPointsOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Declare a variable named <code>point</code> of type <code>Point</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldGetPointsOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Set the point variable equal to the return value of <code>circle.getPointOnCircle( 0 )</code>. Above that line, it is useful to add a comment line specifying that this is the top-most point of circle.</p>
+		
+		<code><pre>[Test]
+public function shouldGetPointsOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	//top-most point of circle
+	point = circle.getPointOnCircle( 0 );
+}		</pre></code>
+
+		<p>The <code>getPointOnCircle( t:Number )</code> returns a Circle object's point that corresponds to the radians passed in as the <code>t</code> parameter.</p>
+	</li>
+	<li>
+		<p>Add two new lines, each with a call to the <code>assertEquals()</code> method. The first takes the arguments <code>5</code> and <code>point.x</code>. The second takes the arguments <code>0</code> and <code>point.y</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldGetPointsOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	//top-most point of circle
+	point = circle.getPointOnCircle( 0 );
+	assertEquals( 5, point.x );
+	assertEquals( 0, point.y );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Copy these four new lines of code and paste them into the bottom of the function.</p> 
+		<p>Alter the comment in this section to read <code>//bottom-most point on circle</code>.</p>
+	</li>
+	<li>
+		<p>Replace the <code>0</code> in <code>circle.getPointOnCircle( 0 )</code> with <code>Math.PI</code>.</p>
+	</li>
+	<li>
+		<p>Update the <code>assertEquals()</code> statements to <code>assertEquals( -5, point.x )</code> and <code>assertEquals( 0, point.y )</code>.</p>
+		<p>This should create a duplicate set of assertions for the bottom-most point on the circle.</p>
+		
+		<code><pre>[Test]
+public function shouldGetPointsOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	//top-most point of circle
+	point = circle.getPointOnCircle( 0 );
+	assertEquals( 5, point.x );
+	assertEquals( 0, point.y );
+
+	//bottom-most point of circle
+	point = circle.getPointOnCircle( Math.PI );
+	assertEquals( -5, point.x );
+	assertEquals( 0, point.y );
+}		</pre></code>
+
+	</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='SingleTestFailure' id='shift' src='../images/unit4/image2.png' />
+		<p class='caption' id='shift'>Figure 1: A single test failure</p>
+
+		<p>One of the tests in the case has failed. Further evaluation within the FlexUnit results tab will show that the newly populated <code>shouldGetPointsOnCircle()</code> method failed.</p>
+		<p>While you know that this test failed, you do not know the failure. Fewer assertions in a method provide you better context to understand the root cause quickly.</p>
+		<p>If you examine the failure in Flash Builder, you will see that the root cause actually has to do with the imprecision of floating point calculations. You will learn to adapt your code to these issues in future lessons.</p>
+		
+		<img alt='FailureStackTrace' id='shift' src='../images/unit4/image3.png' />
+		<p class='caption' id='shift'>Figure 2: The failure stack trace </p>
+	</li>
+</ol>
+
+<h2>Understanding multiple assertions</h2>
+
+<p>As you have previously learned, FlexUnit 4.x marks a test as a failure after the first failed assertion. Therefore a test with many assertions provides a limited amount of useful information as to the root cause of the failure.</p>
+<p>The <code>shouldGetPointsOnCircle()</code> method already has too many assertions to be useful. Furthermore, to test it effectively you still need additional data points along the circle.</p>
+<p>The way to resolve this issue is to refactor these test cases into multiple small cases which provide useful context during a failure. Each test will make a single assertion. Subsequently, if a single test fails, a single assertion has failed.</p>
+
+<h2>Walkthrough 3: Factoring into Multiple Test Methods</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Refactor a test method with multiple assertions.</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_wt3.fxp project from the Unit5/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3>Refactor point tests</h3>
+	
+	</li>
+	<li>
+		<p>Replace the <code>shouldGetPointsOnCircle()</code> function with two new public functions in the <code>BasicCircleTest</code> class. These functions will be named so that each clearly represents the point on the circle being tested.</p>
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+}
+
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+}		</pre></code>
+
+		<p>Although the original <code>shouldGetPointsOnCircle()</code> method contained tests for only the top and bottom points of the Circle, in this Walkthrough you will add tests for the left and right points as well.</p>
+	</li>
+	<li>
+		<p>Add two new methods named <code>shouldGetRightPointOnCircle()</code> and <code>shouldGetLeftPointOnCircle()</code>.</p>
+	</li>
+	<li>
+		<p>Copy the instantiation of the circle, and declaration of the point from the <code>shouldgetPointsOnCircle()</code> method into each of the four new methods.</p>
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+}
+
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+}
+
+[Test]
+public function shouldGetRightPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+}
+
+[Test]
+public function shouldGetLeftPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Copy the block of code following <code>//top-most point of circle</code> comment into the <code>shouldGetTopPointOnCircle()</code> method.  Copy the block following the <code>//bottom-most point of circle</code> comment into the <code>shouldGetBottomPointOnCircle()</code> method.</p>
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	//top-most point of circle 
+	point = circle.getPointOnCircle( 0 );
+	assertEquals( 5, point.x );
+	assertEquals( 0, point.y );
+}
+
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	//bottom-most point of circle
+	point = circle.getPointOnCircle( Math.PI );
+	assertEquals( -5, point.x );
+	assertEquals( 0, point.y );
+}		</pre></code>
+
+		<p>Because the methods each test specific points, the name is clear enough to distinguish one test from another. Remove the comment fields in each of the tests accordingly.</p>
+	</li>
+	<li>
+		<p>Modify the <code>shouldGetTopPointOnCircle()</code> and <code>shouldGetBottomPointOnCircle()</code> methods to save space by instantiating the point variable as it is declared in each function, much like the circle variable. The comments can be removed as well.</p>
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( 0 );
+
+	assertEquals( 5, point.x );
+	assertEquals( 0, point.y );
+}
+
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( Math.PI );
+
+	assertEquals( -5, point.x );
+	assertEquals( 0, point.y );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>In the <code>shouldGetRightPointOnCircle()</code> method, set the <code>point</code> variable to <code>circle.getPointOnCircle( Math.PI/2 )</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldGetRightPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( Math.PI/2 );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>In the <code>shouldGetLeftPointOnCircle()</code> method, set the <code>point</code> variable to <code>circle.getPointOnCircle( (3*Math.PI)/2 )</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldGetLeftPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( (3*Math.PI)/2 );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add two calls to the <code>assertEquals()</code> method to <code>shouldGetRightPointOnCircle()</code>. One should assert that <code>point.x</code> is equal to <code>5</code>, and <code>point.y</code> is equal to <code>0</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldGetRightPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( Math.PI/2 );
+
+	assertEquals( 0, point.x );
+	assertEquals( 5, point.y );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Add two calls to the <code>assertEquals()</code> method to <code>shouldGetLeftPointOnCircle()</code>. One should assert that <code>point.x</code> is equal to <code>0</code>, and <code>point.y</code> is equal to <code>-5</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldGetLeftPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( (3*Math.PI)/2 );
+
+	assertEquals( 0, point.x );
+	assertEquals( -5, point.y );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Delete the previously used <code>shouldGetPointsOnCircle()</code> method, because its tests have been replicated.</p>
+	</li>
+	<li>
+		<p>Save the BasicCircleTest.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='ThreeTestsFailed' id='shift' src='../images/unit4/image4.png' />
+		<p class='caption' id='shift'>Figure 1: Three tests failed.</p>
+		
+		<p>Previously, when all the point assertions were bundled into a single method, it was impossible to determine which assertions caused the failure. Refactoring these assertions into four different test methods makes it clear that three of the four conditions are failures.</p> 
+		<p>Further inspection will reveal that the <code>shouldGetTopPointOnCircle()</code> is the only of the four tests that is passing. It is also the only test with an integer value of 0 passed in for its radians argument. The root cause of the situation is the way in which Flash Player handles fractions and the precision of those comparisons. This will be explored further and a solution demonstrated later in this text.</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+<ul>
+	<li>A unit is the smallest piece of code that can be isolated and tested independently</li>
+	<li>Code with seams is testable. Code without seams is impossible to truly unit test.</li>
+	<li>You can create seams in your code by:</li>
+	<ul>
+		<li>Passing dependencies as arguments</li>
+		<li>Limiting the use of static classes or global state</li>
+	</ul>
+	<li>Test cases are collections of test methods</li> 
+	<li>A test without a failing assertion is a passing test</li>
+	<ul>
+		<li>This means an empty tests is a passing test</li>
+	</ul>
+	<li>Common assertions in FlexUnit include:</li>
+	<ul>
+		<li><code>assertEquals()</code></li>
+		<li><code>assertTrue()</code></li>
+		<li><code>assertFalse()</code></li>
+	</ul>
+	<li>Any failing assertion within a test causes the test to cease execution and fail</li>
+	<li>When a test with multiple assertions fails, it is difficult to narrow down which assertion failed.</li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-5.html" class="next"></a>
+			<a href="Unit-3.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-5.html
==============================================================================
--- websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-5.html (added)
+++ websites/staging/flex/trunk/content/flexunit/tutorial/flexunit/Unit-5.html Thu Mar 20 03:56:18 2014
@@ -0,0 +1,724 @@
+<!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>Developing Static Tests</title>
+
+	<script language="JavaScript" src="../scripts/jquery-1.5.min.js" ></script>
+	<link href="../css/style.css" rel="stylesheet" type="text/css" />
+
+</head>
+<body>
+	
+	<div id="container">
+		
+		<div id="contentborder">
+			<div id="unitdownload">
+				
+					<a href="../code/unit5.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 5 - Developing Static Tests</h1>
+
+<p>FlexUnit 4.x has available features for developers to plan ahead and prepare tests for classes still under development. Ignoring a test is a capability that will allow you to prototype or create tests that may not yet be relevant or operational.</p> 
+<p>While the basic assertions you have used so far will accomplish much, the more advanced assertions available by using Hamcrest inside of FlexUnit 4 will reduce complexity in your test cases and increase test legibility.</p>
+
+<h3>Objectives:</h3>
+
+<p>After completing this lesson, you should be able to:</p>
+<ul>
+	<li>Set test methods to be ignored</li>
+	<li>Refactor test methods for greater specificity</li>
+	<li>Use <code>assertThat()</code> and extensible assertions in your test methods</li>
+	<li>Write a custom matcher to be used in an <code>assertThat()</code> statement</li>
+	<li>Write tests that expect an exception</li>
+</ul>
+
+<h3>Topics</h3>
+
+<p>In this unit, you will learn about the following topics:</p>
+<ul>
+	<li>Adding additional tests</li>
+	<li>Dealing with incomplete tests</li>
+	<li>Ignoring a test and its benefits</li>
+	<li>Understanding multiple assertions</li>
+	<li>Extensible assertions</li>
+	<li>Hamcrest</li>
+	<li>Writing matchers</li>
+</ul>
+
+<h2>Adding additional tests</h2>
+
+<p>If you are a practitioner of test-first development, then you create each test in your system just before you create the code to make that test pass. In essence, you are defining the interface progressively.</p> 
+<p>However, if you are writing tests for legacy code, or writing your tests immediately after a class is written, you can inspect the code and note the expected outcome of each method. You can then write tests that will cover these conditions.</p>
+<p>In the latter situation, it is common to write test stubs, empty functions for each required test, and implement them sequentially. The practice of creating these empty tests serves as documentation for the needed tests as they are discovered.</p>
+<p>Consider the needed tests for the following objects:</p>
+<ul>
+	<li>A box of crayons contains 12 crayons each of which is a unique color.</li>  
+	<li>Each crayon is made of wax, has a color, and a wrapper.</li>  
+	<li>Each wrapper has the color name on it.</li>
+</ul>
+<p>You probably notice several things that need to be tested right away.  Minimally, you need to test that the box has 12 crayons. You would need to test that each crayon is of type wax, has a color and a wrapper.  You would need to test that the wrapper has a color name and that the color name is the same as the color of the crayon it wraps. Finally, you would need to test that each crayon color is unique.</p>
+
+<code><pre>public class BoxOfCrayonsCase {
+	[Test]
+	public function shouldHaveTwelveCrayons():void {}
+	[Test]
+	public function shouldHaveUniqueColors():void {}
+}
+
+public class CrayonCase {
+	[Test]
+	public function shouldBeWax():void {}
+	[Test]
+	public function shouldHaveColor():void {}
+	[Test]
+	public function shouldBeWrapped():void {}
+}
+
+public class WrapperCase {
+	[Test]
+	public function shouldHaveColorName():void {}
+	[Test]
+	public function shouldMatchWrappedCrayon():void {}
+}</pre></code>
+
+<p>You now have a road map for testing.  Currently none of these tests actually verify functionality. As noted previously, the lack of a failing assertion is a success so all of these tests would pass.  Excellent, testing complete!</p>  
+<p>If only the world were so easy.  In reality, these tests are far from complete, the fact that all these <i>incomplete</i> tests will pass is a problem that needs to be addressed.</p>
+
+<h2>Dealing with incomplete tests</h2>
+
+<p>There are several possible ways to deal with incomplete tests</p>
+<ul>
+	<li>
+		<p>Leave them as stubs - Stubbed tests still show in the test complete dialogue.  They will always be marked as passing.  It is very easy to forget to implement these tests and it artificially appears as though you have many valid tests.</p>
+	</li>
+	<li>
+		<p>Comment the tests out - These tests will not show in the complete dialogue.  Like stub tests, it is very easy to forget to complete these tests as there is no visible reminder.</p>
+	</li>
+	<li>
+		<p>Add a special type of assertion named <code>fail()</code> inside each method - This type of assertion always marks a test as a failure.  This is effective, and certainly serves as a reminder that the test needs to be completed, but not the best solution as it artificially appears as though you have many failing tests.</p>
+	</li>
+	<li>
+		<p>Ignoring - This will mark the tests in the complete dialogue without marking them as failures. When ignoring, you will receive a reminder that these tests need to be implemented but without the side effect of artificial statistics. This is the best way to deal with incomplete tests.</p>
+	</li>
+</ul>
+
+<h2>Ignoring a test</h2>
+
+<p>The [Ignore] metadata is a special type of metadata recognized by FlexUnit 4.x. It can be used on a test, test case or test suite. It is often used when a test has been written but is not ready to run with any reasonable outcome or when refactoring of a class renders specific tests temporarily irrelevant or broken</p>
+<p>The [Ignore] metadata can also be applied to tests that have been written for a particular case, but the actual components or methods that they need to test are non-existent. For example, in the crayon example above, you may want to write the wrapper test before the wrapper class.</p>
+<p>Finally, they can also be useful to hold on to deprecated tests that may be relevant again at a later point.</p>
+<p>Ignored tests:</p>
+<ul>
+	<li>Are neither passing nor failing tests</li>
+	<li>Are counted and reported as Ignored by FlexUnit as a reminder</li>
+	<li>Are easily identified and ignored through the <code>[Ignore]</code> decoration</li>
+</ul>
+
+<code><pre>[Ignore]
+[Test]
+public function ignoreTest() :void</pre></code>
+
+<h2>Walkthrough 1: Commenting out and Ignoring Tests</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Comment out several test methods.</li>
+	<li>Ignore several test methods.</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 5/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+		<h3><br />Commenting out tests</h3>
+	</li>
+	<li>
+		<p>Highlight the text that comprises the <code>shouldGetBottomPointOnCircle()</code> function. Press Shift+Control+c (Shift+Command+C on MacOS) and the comment markers (/* and */) should be added as shown.</p>
+		
+		<img alt='CommentingCode' id='shift' src='../images/unit5/image1.png' />
+		<p class='caption' id='shift'>Figure 1: Commenting code</p>
+	</li>
+	<li>
+		<p>Save BasicCircleTest.as</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file again.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window. Note that there is one less test than previously results:</p>
+
+		<img alt='TwoTestFailures' id='shift' src='../images/unit5/image2.png' />
+		<p class='caption' id='shift'>Figure 2: Two test failures</p>	
+		
+		<h3><br />Using Ignore metadata</h3>
+	</li>
+	<li>
+		<p>Re-Open the BasicCircleTest.as file. Remove the comments by highlighting the commented <code>shouldGetBottomPointOnCircle()</code> function and pressing Shift+Control+c. This command will remove the comment markers. The function should look as it did at the start of this walkthrough.</p>
+	</li>
+	<li>
+		<p>Add a line with <code>[Ignore]</code> metadata above the <code>[Test]</code> metadata of the <code>shouldGetBottomPointOnCircle()</code> function.</p>
+		
+		<code><pre>[Ignore]
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+...
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save BasicCircleTest.as.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file again.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+ 
+ 		<img alt='TwoTestsOneIgnore' id='shift' src='../images/unit5/image3.png' />
+		<p class='caption' id='shift'>Figure 3: Two test failures and one has been ignored</p>
+	</li>
+	<li>
+		<p>Similarly, mark the <code>shouldGetRightPointOnCircle</code>, <code>shouldGetLeftPointOnCircle()</code> and <code>shouldThrowRangeError()</code> test method with ignore metadata.</p>
+		
+		<code><pre>[Ignore]
+[Test]
+public function shouldThrowRangeError():void {
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save BasicCircleTest.as</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file again.</p>
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='FourIgnores' id='shift' src='../images/unit5/image4.png' /> 
+		<p class='caption' id='shift'>Figure 4: Four tests have been ignored</p>
+	</li>
+</ol>
+
+<h2>Benefits of Ignore over Comments</h2>
+
+<p>As you have just demonstrated, [Ignore] provides a useful way of indicating that a test exists but is, for whatever reason, not ready to run at this time. Ignoring a test ensures that the test is not lost in comments and forgotten.</p>
+<p>The [Ignore] metadata provides a few additional benefits over commenting. First, the [Ignore] metadata can accept additional system and user defined arguments.</p> 
+<p>For example:</p>
+
+<code><pre>[Ignore(description="Phase II Requirement",category="Required"]
+[Test]
+public function shouldGetPointsOnCircle():void 
+{
+...
+}</pre></code>
+
+<p>This additional information can be used for filtering, sorting and reporting on some test systems. Unfortunately, at this time, Flash Builder does not display this extra information to its users. However, it does provide one useful function when using [Ignore]: Flash Builder Premium will display the ignored tests in the case hierarchy. This means you can easily find and click on an ignored method to quickly find it in a large project.</p>
+
+<h2>Extensible Assertions</h2>
+
+<p>So far we have discussed three types of assertions</p>
+<ol>
+	<li><code>assertTrue( condition:Boolean )</code></li>
+	<ul>
+		<li>Valid if the condition is true</li>
+	</ul>
+	<li><code>assertFalse( condition:Boolean )</code></li>
+	<ul>
+		<li>Valid if the condition is false</li>
+	</ul>
+	<li><code>assertEquals( value1:Object, value2:Object )</code></li>
+	<ul>
+		<li>Valid if value1 == value2</li>
+	</ul>
+</ol>
+<p>Standard assertions work well for many cases. However, as the complexity of your tests increases, you may find yourself with long, complicated compound assertions. For example: what if you needed to ensure that the result of a method call was an array that contained at least two specific values?</p> 
+<p>Ideally, tests not only verify functionality but are also a portion of the documentation for the system. This is only possible if the tests are clear, concise and legible.  Further, in cases like the array examples above, you would end up with significant logic in your tests. Any place where logic exists needs to be considered suspect unless there are tests to verify that functionality, and we simply can't recommend writing tests for your tests.</p>
+<p>Additionally, the simplistic nature of the assertions you have learned so far, also means they provide simplistic error messages. Take the case of this slightly more complicated assertion that determines if a number is between two other numbers:</p>
+<code><pre>assertTrue( num1 &#62; num2 &#38;&#38; num1 &#60; num3 );</pre></code>
+<p>If this test fails, it would yield the basic and uninformative failure message:</p>
+<code><pre>"Expected &#60;true&#62; but was &#60;false&#62;."</pre></code>
+<p>This information, while true, is not all that useful for instant problem identification. This lack of information forces the developer back to the original test to understand what was being tested and helps defeat one of the key advantages of having tests.</p>
+
+<h2>Hamcrest</h2>
+
+<p>Hamcrest is an open source library of matchers, which are simple classes that perform comparisons. These matchers, along with encompassing logic, allow Hamcrest to perform complicated matching with a simple and extensible syntax.</p>
+<p>Hamcrest itself is neither a unit testing library, nor specifically made to work with unit tests, but the matchers it exposes are used by FlexUnit to provide a powerful and flexible way to move beyond basic assertions.</p>
+<p>When using Hamcrest assertions in FlexUnit, you use a special function named <code>assertThat()</code>.</p> 
+<code><pre>public function assertThat( value, matcher );</pre></code>
+<p>Unlike the assertions used so far, the <code>assertThat()</code> method does not inherently prescribe any specific type of comparison or evaluation. Instead, you provide a value and a matcher. It is the matcher that dictates the type of comparison.</p>
+<p>Referring back to the example from above, if you wished to know if num1 was between num2 and num3 using standard assert syntax, you would write:</p>
+<code><pre>assertTrue( num2 &#60; num1 &#38;&#38; num1 &#60; num3);</pre></code>
+<p>Using Hamcrest, this same assertion would read:</p>
+<code><pre>assertThat( num1, is( between( num2, num3 ) ) );</pre></code>
+<p>There are several advantages to the Hamcrest assertion. First, this statement could be read by someone with little testing or development experience and would still be understandable.</p>
+<p>Second, if the <code>assertThat()</code> statement above fails it would yield the following result:</p>
+<code><pre>"Expected a number between &#60;num2&#62; and &#60;num3&#62; but was &#60;num1&#62;."</pre></code>
+<p>which is many, many times more useful than the <code>assertTrue()</code> statement's failure message in this same situation:</p>
+<code><pre>"Expected &#60;true&#62; but was &#60;false&#62;."</pre></code>
+<p>This particular assertion uses the <code>is()</code> and <code>between()</code> matchers to create a more readable assertion. These are just two of the many types of matchers offered by Hamcrest. Further, as each matcher is simply a class that implements a specific interface, you are encouraged to create your own matchers to make even the most difficult matching clear inside of your test cases.</p>
+<p>For more information on Hamcrest and extensible matchers, check out the Hamcrest-as3 page on github available at <a class='contentlink' href='http://github.com/drewbourne/hamcrest-as3' target='_blank'>http://github.com/drewbourne/hamcrest-as3</a>.</p>
+
+<h2>Understanding the Floating Point Issue</h2>
+
+<p>There were three test failures in Unit 4: Walkthrough 3 because the <code>assertEquals()</code> statement is used to judge equality, which seems logical on the surface. However, there are many times when a computer's concept of equal and our concept of 'equal enough' are not the same.</p> 
+<p>The <code>shouldGetTopPointOnCircle()</code> method was the only one of the four point tests that passed:</p>
+
+<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( 0 );
+
+	assertEquals( 5, point.x );
+	assertEquals( 0, point.y );
+}</pre></code>
+
+<p>This was the only of the four new point tests that called <code>circle.getPointOnCircle()</code> with an argument of 0. The other three point tests called <code>circle.getPointOnCircle()</code> with <code>Math.PI/2</code>, <code>Math.PI</code>, and <code>(3*Math.PI)/2</code>.</p> 
+<p>Pi is an irrational number that cannot be expressed exactly. Further, Flash Player itself can only store large numbers to a certain precision. This means that calculations involving any floating point value, and especially an irrational one like Pi, will always have a margin of error.</p>
+
+<code><pre>[Test]
+public function shouldGetBottomPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( Math.PI );
+
+	assertEquals( -5, point.x );
+	assertEquals( 0, point.y );
+}</pre></code>
+
+<img alt='FailureStackTrace' src='../images/unit5/image5.png' />
+<p class='caption'>Figure 1: Failure Stack Trace</p>
+
+<p>If you examine the failure in Flash Builder (Figure 1), you will quickly understand the issue. The result our <code>shouldGetBottomPointOnCircle()</code> method returned the following values for x and y:</p>
+<ul>
+	<li>point.x = -5</li>	
+	<li>point.y = 6.123031769111886E-16 (which is actually 0.0000000000000006123031769111886, expressed in scientific notation)</li>
+</ul>
+<p>Both of these calculations are correct within a very acceptable margin of error. However, we told FlexUnit, and hence Flash Player, that they needed to be exactly equal. The problem comes with the specificity of our request, not the test. To that end, we need a way to explain to FlexUnit that we are okay with a margin of error. While the standard assertions can't provide that for us, Hamcrest can.</p>
+
+<h2>Walkthrough 2: Using Hamcrest to deal with Floating Point Issues</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Use the <code>assertThat()</code> statement with extensible assertions.</li>
+</ul>
+
+<h3>Steps</h3>
+
+<ol>
+	<li>
+		<p>Open the FlexUnit4Training.mxml 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 5/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+		
+		<h3><br />Using the assertThat() method with extensible assertions</h3>
+	
+	</li>
+	<li>
+		<p>At the top of the <code>BasicCircleTest</code> class declare a private, static constant with the name of <code>TOLERANCE</code> and a data type of <code>Number</code>. Set the constant equal to <code>.0001</code>.</p> 
+		
+		<code><pre>public class BasicCircleTest {
+	private static const TOLERANCE:Number = .0001;
+	...
+}		</pre></code>
+
+		<p>We will use this value to determine "close enough."  If the result is between our expected value plus or minus the tolerance, we are willing to consider the value to be close enough.</p>
+	</li>
+	<li>
+		<p>Replace the first <code>assertEquals()</code> assertion of the <code>shouldgetTopPointOnCircle()</code> function with the <code>assertThat()</code> statement as shown.</p>
+		<p>Replace this statement:</p>
+		<code><pre>assertEquals( 5, point.x );</pre></code>
+		<p>With this statement:</p>
+		<code><pre>assertThat( point.x, closeTo( 5, TOLERANCE ) );</pre></code>
+		<p>Be sure to either use the code complete with assertThat and closeTo, or manually add their imports.</p>
+		<code><pre>import org.flexunit.assertThat;<br />import org.hamcrest.number.closeTo;</pre></code>	
+	</li>
+	<li>
+		<p>Remove [Ignore] metadata from the <code>shouldGetBottomPointOnCircle()</code>, <code>shouldGetLeftPointOnCircle()</code> and <code>shouldGetRightPointOnCircle()</code> methods.</p>
+		<p>Unlike <code>assertEquals()</code>, the <code>closeTo()</code> Hamcrest matcher specifies that we need to look for numerical equivalence within a specific margin of error.</p>
+	</li>
+	<li>
+		<p>Change all the point tests so that each uses the <code>assertThat()</code> statement in place of <code>assertEquals()</code>.</p> 
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	point = circle.getPointOnCircle( 0 );
+	assertThat( point.x, closeTo( 5, TOLERANCE ) );
+	assertThat( point.y, closeTo( 0, TOLERANCE ) );
+}
+
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	point = circle.getPointOnCircle( Math.PI );
+	assertThat( point.x, closeTo( -5, TOLERANCE ) );
+	assertThat( point.y, closeTo( 0, TOLERANCE ) );
+}
+
+[Test]
+public function shouldGetRightPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	point = circle.getPointOnCircle( Math.PI/2 );
+	assertThat( point.x, closeTo( 0, TOLERANCE ) );
+	assertThat( point.y, closeTo( 5, TOLERANCE ) );
+}
+
+[Test]
+public function shouldGetLeftPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point;
+
+	point = circle.getPointOnCircle( (3*Math.PI)/2 );
+	assertThat( point.x, closeTo( 0, TOLERANCE ) );
+	assertThat( point.y, closeTo( -5, TOLERANCE ) );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save the BasicCircleTest.as file.</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file. If the tests ran successfully, you should see the following output.</p>
+
+		<img alt='PassedOneIgnore' id='shift' src='../images/unit5/image6.png' /> 
+		<p class='caption' id='shift'>Figure 1: FlexUnit tests passed, one ignored</p>
+	</li>
+</ol>
+
+<h2>Writing Matchers</h2>
+
+<p>The Hamcrest library includes base matchers to cover a wide variety of potential situations. You are encouraged to create your own custom matchers when encountering a situation that can be handled more easily, or more clearly, with a new matcher.</p> 
+<p>One of the goals behind Hamcrest is to create highly readable matching. If you examine your unit tests, they are still legible but becoming less so as the complexity of testing increases. For example:</p>
+
+<code><pre>	assertThat( point.x, closeTo( -5, TOLERANCE ) );
+	assertThat( point.y, closeTo( 0, TOLERANCE ) );</pre></code>
+
+<p>Neither you, nor another individual that may read this code later, really cares that the point's x and y properties are within a tolerance. What you really care about is that one Point is close to another Point within a given tolerance.</p>
+
+<code><pre>	assertThat( point, closeToPoint( otherPoint, TOLERANCE ) );</pre></code>
+
+<p>While this is a simple example, custom matchers continue to become more effective as the complexity of your tests grows.</p>
+<p>Custom matcher classes extend the <code>TypeSafeMatcher</code> class. Basic custom matchers are written with three methods.</p>
+<ul>
+	<li>Constructor</li>
+	<ul> 
+		<li>Used to provide the values being matched.</li>
+	</ul>
+	<li>Override of <code>matchesSafely()</code></li>
+	<ul>
+		<li>Accepts an item of data type <code>Object</code> that will be compared to the provided values.  You perform any logic to determine if the values match or not in this method and return a Boolean indicating the result.</li>
+	</ul>
+	<li>Override of <code>describeTo()</code></li>
+	<ul>
+		<li>Used to create the informative error descriptions characteristic of Hamcrest.  This should return the descriptive string.</li>
+	</ul>
+</ul>
+
+<h2>Walkthrough 3: Writing your own matcher</h2>
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Create a new ActionScript package.</li>
+	<li>Write a custom matcher.</li>
+	<li>Use the custom matcher in the <code>getPointOnCircle()</code> 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_wt3.fxp project from the Unit 5/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Create the matcher package</h3>
+	</li>
+	<li>
+		<p>Within the tests directory, create another package named matcher.  Right click on the tests directory and choose New > Package.</p> 
+
+		<img alt='CreateNewPackage' id='shift' src='../images/unit5/image7.png' /> 
+		<p class='caption' id='shift'>Figure 1: Create a new package</p>
+	</li>
+	<li>
+		<p>The Name should be matcher.</p>
+
+		<img alt='NewPackageWindow' id='shift' src='../images/unit5/image8.png' />
+		<p class='caption' id='shift'>Figure 2: New package window</p>
+		
+		<h3><br />Create the matcher class</h3>
+	</li>
+	<li>
+		<p>You will now need to create a new class within the helper package. Right click on the package and choose New &#62; ActionScript Class.</p>
+
+		<img alt='NewHelperClass' id='shift' src='../images/unit5/image9.png' />
+		<p class='caption' id='shift'>Figure 3: Create a new class in the helper package</p>
+	</li>
+	<li>
+		<p>The class should be named CloseToPointMatcher and its Superclass should be org.hamcrest.TypeSafeMatcher. Modifiers should be set to public and the Generate constructor from superclass option should be checked. Click Finish.</p>
+
+		<img alt='NewCloseToPointMatcher' id='shift' src='../images/unit5/image10.png' /> 
+		<p class='caption' id='shift'>Figure 4: New ActionScript Class CloseToPointMatcher</p>
+	</li>
+	<li>
+		<p>Open the CloseToPointMatcher.as file from the matcher package.</p>
+
+		<img alt='PackageDirectoryStructure' id='shift' src='../images/unit5/image11.png' /> 
+		<p class='caption' id='shift'>Figure 5: Package directory structure</p>
+	</li>
+	<li>
+		<p>Add a private variable named <code>point</code> of type <code>Point</code> and another named <code>tolerance</code> of data type <code>Number</code> to the class.</p> 
+
+		<code><pre>	private var point:Point;
+	private var tolerance:Number;</pre></code>
+
+		<p>If you did not use code-completion, add the import for flash.geom.Point at this time.</p>
+	</li>
+	<li>
+		<p>Modify the automatically created <code>CloseToPointMatcher()</code> constructor. To accept point and tolerance parameters, instead of an <code>expectedType</code>.  Pass a reference of the Point class to the superclass's constructor, and populate the local circle and offset properties with the appropriate argument from the constructor.</p>
+		
+		<code><pre>public function CloseToPointMatcher( point:Point, tolerance:Number ) {
+	super(Point);
+	this.point = point;
+	this.tolerance = tolerance;
+}		</pre></code>
+		
+		<p>The <code>super(Point)</code> declaration is informing the classes the data types that the class will be dealing with is a Point class.</p>
+	</li>
+	<li>
+		<p>Override the <code>matchesSafely()</code> method of the class. It will take an argument named <code>item</code> of data type <code>Object</code>, and will return a Boolean.</p>
+		
+		<code><pre>override public function matchesSafely(item:Object):Boolean {
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>In the <code>matchesSafely()</code> method, declare a variable named <code>distance</code> of data type <code>Number</code>. Set it equal to <code>Point.distance( item as Point, point )</code>;</p>
+		
+		<code><pre>override public function matchesSafely(item:Object):Boolean {
+	var distance:Number = Point.distance( item as Point, point );
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Add a return statement that checks if the <code>tolerance</code> subtracted from the absolute value of the <code>distance</code> is less than 0.</p>
+		
+		<code><pre>override public function matchesSafely(item:Object):Boolean {
+	var distance:Number = Point.distance( item as Point, point );
+
+	return( Math.abs( distance ) - tolerance &#60; 0 );
+}		</pre></code>
+		
+	</li>
+	<li>
+		<p>Add an override for the public function <code>describeTo()</code>. It will take an argument named <code>description</code> of type <code>Description</code>. Because there are two available <code>Description</code> classes, make sure to choose the <code>org.hamcrest.Description</code> class when you use code completion.</p>
+		
+		<code><pre>override public function describeTo(description:Description):void {
+	description.appendText( "point " ).appendText( point.toString() );
+}		</pre></code>
+		
+		<p>If you did not use code-completion, add the import for <code>org.hamcrest.Description</code>.</p>
+	</li>
+	<li>
+		<p>Save CloseToPointMatcher.as.</p>
+	</li>
+	<li>
+		<p>Open the BasicCircleTest.as file.</p>
+	</li>
+	<li>
+		<p>Modify the <code>shouldGetTopPointOnCircle()</code> method so that it reads as follows.</p>
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( 0 );
+
+	assertThat( point, new CloseToPointMatcher( new Point( 5, 0 ), TOLERANCE ) );
+}		</pre></code>
+		
+		<p>Be sure to either choose CloseToPointMatcher from the code-completion, or manually add the import:</p>
+		<code><pre>import matcher.CloseToPointMatcher;</pre></code>
+	</li>
+	<li>
+		<p>Each of the point testing functions should follow this format. Instantiate the circle, instantiate the expected point, and finish with the assertion.</p>
+		
+		<code><pre>[Test]
+public function shouldGetTopPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( 0 );
+
+	assertThat( point, new CloseToPointMatcher( new Point( 5, 0 ), TOLERANCE ) );
+}
+
+[Test]
+public function shouldGetBottomPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( Math.PI );
+
+	assertThat( point, new CloseToPointMatcher( new Point( -5, 0 ), TOLERANCE ) );
+}
+
+[Test]
+public function shouldGetRightPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( Math.PI/2 );
+
+	assertThat( point, new CloseToPointMatcher( new Point( 0, 5 ), TOLERANCE ) );
+}
+
+[Test]
+public function shouldGetLeftPointOnCircle():void {
+	var circle:Circle = new Circle( new Point( 0, 0 ), 5 );
+	var point:Point = circle.getPointOnCircle( (3*Math.PI)/2 );
+
+	assertThat( point, new CloseToPointMatcher( new Point( 0, -5 ), TOLERANCE ) );
+}		</pre></code>
+
+	</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='PassedOneIgnored' id='shift' src='../images/unit5/image6.png' /> 
+		<p class='caption' id='shift'>Figure 6: FlexUnit tests passed, one test ignored</p>
+	</li>
+</ol>
+
+<h2>Exceptions</h2>
+
+<p>There are times when your code should throw an error in response to a given situation, such as when an illegal value or null is provided to a required property. In these cases the actual outcome of a test is not to assert a condition but to verify that the error was thrown as expected.</p> 
+<p>If an error is NOT thrown in this situation, it should be considered a failure while throwing the error would be a success. This logical inversion is often handled by wrapping all testing functionality in try-catch blocks. However, this leads to ugly, illegible and difficult to maintain code.</p>
+<p>FlexUnit 4 simplifies this process by allowing an <i>expects</i> argument in the Test annotation for this purpose.</p>
+<ul>
+	<li>To use the <i>expects</i> annotation, simply provide the type of error expected.</li>
+	
+	<code><pre>
+[Test (expects="full.package.ThrownError")]
+public function testError():void {}						
+	</pre></code>
+	
+	<li>If the tested method throws the <code>ThrownError</code>, FlexUnit 4.x will recognize this method as a success and mark the test as passed.</li>
+	<li>If the error is not thrown, then the test is marked as a failure.</li> 
+	<li>If the method throws an error that is not of type <code>ThrownError</code> then FlexUnit 4 marks that test as a failure, since the expected error type did not match the error that was thrown, and something else is causing your method to fail.</li>
+</ul>	
+<p>The <code>expects=""</code> attribute only verifies the type of the error, it does not evaluate the properties of the error instance. If you need to verify data internal to the error you must catch the error yourself and perform assertions.</p>
+<p>In most cases, the <code>expects=""</code> attribute works well as the existence of the error is often most important.</p>
+
+<h2>Walkthrough 4: Handling an exception in a Test</h2>
+
+<p>In this walkthrough you will perform the following tasks:</p>
+<ul>
+	<li>Add a statement that will throw an error when the tests are run.</li>
+	<li>Handle a desired exception using <code>expects=""</code> attribute.</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_wt4.fxp project from the Unit5/Start folder. Please refer to Unit 2: Walkthrough 1 for instructions on importing a Flash Builder project.</p>
+
+		<h3><br />Run a new test</h3>
+		
+	</li>
+	<li>
+		<p>At the end of the <code>BasicCircleTest</code> class there is an ignored test method named <code>shouldThrowRangeError()</code>. Remove the <code>[Ignore]</code> metadata from this function and declare a variable named <code>someCircle</code> of type <code>Circle</code>. Instantiate the <code>Circle</code> with an origin of <code>(10, 10)</code> and a radius of <code>-5</code>.</p>
+		
+		<code><pre>[Test]
+public function shouldThrowRangeError():void {
+	var someCircle:Circle = new Circle( new Point( 10, 10 ), -5 );
+}		</pre></code>
+
+	</li>
+	<li>
+		<p>Save BasicCircleTest.as</p>
+	</li>
+	<li>
+		<p>Run FlexUnit4Training.mxml.</p>
+		
+		<p>If FlexUnit4Training.mxml ran successfully you should see the following output in your browser window:</p>
+
+		<img alt='SingleErrorThrown' id='shift' src='../images/unit5/image12.png' />
+		<p class='caption' id='shift'>Figure 1: A single test has thrown an error</p>
+
+		<p>The <code>shouldThrowRangeError()</code> test is throwing an error. The error comes from the test's attempt to instantiate a Circle object with a radius of -5. Even without looking at the code, one could conclude that a Circle with a negative radius has conceptual issues.</p> 
+		<p>Notice that FlexUnit is registering the error without any assertion statement present in the function. If a test method throws an error at any point, FlexUnit will register that method as an error.</p> 
+		<p>When a test fails due to a failed assertion, it is considered a failure. When it fails due to a run time exception, it is considered an error. While the result is the same, a test that does not pass, errors are generally considered more heinous as they indicate an unhandled exception.</p>
+	
+		<h3><br />Using "expects" metadata to deal with anticipated errors</h3>
+	</li>
+	<li>
+		<p>Return to the BasicCircleTest class. Modify the <code>[Test]</code> metadata tag on the line above the <code>shouldThrowRangeError()</code> function to indicate that it expects a <code>RangeError</code>.</p>
+
+		<code><pre>[Test(expects="RangeError")]
+public function shouldThrowRangeError():void {
+	var someCircle:Circle = new Circle( new Point( 10, 10 ), -5 );
+}		</pre></code>
+		
+		<p>RangeError exists in the default package, and hence appears to just be the class name. For your own custom errors or errors defined in the Flex framework, it is important you provide the full path.</p>
+	</li>
+	<li>
+		<p>Save BasicCircleTest.as</p>
+	</li>
+	<li>
+		<p>Run the FlexUnit4Training.mxml file again.</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/unit5/image13.png' /> 
+		<p class='caption' id='shift'>Figure 2: FlexUnit tests passed</p>
+		
+		<p>The <code>shouldThrowRangeError()</code> method has still thrown an error. Because of the <code>expects="RangeError"</code> metadata, FlexUnit knows that this is the expected condition. If that particular error is not thrown, FlexUnit considers it a failure for the test.</p>
+	</li>
+</ol>
+
+<h2>Summary</h2>
+
+<ul>
+	<li>
+		<p>You can create a roadmap for testing by writing out all the expected tests without functionality.</p>
+	</li>
+	<li>
+		<p>Marking tests with [Ignore] metadata is the best way to ensure that you are aware of incomplete test methods.</p>
+	</li>
+	<li>
+		<p>Test methods should be written with as few assertions per test as possible.</p>
+	</li>
+	<li>
+		<p>Hamcrest can:</p>
+	</li>
+	<ul>
+		<li>Increase code readability</li>
+		<li>Increase test report specificity</li>
+		<li>Customize tests to assert better conditions</li>
+	</ul>
+	<li>
+		<p>You can write custom matchers for use with the <code>assertThat()</code> method.</p>
+	</li>
+	<li> 
+		<p>The <code>expects=""</code> attribute of [Test] annotation can be used to handle expected exceptions in your tests.</p>
+	</li>
+</ul>
+
+			</div>
+		</div>
+		
+		<div id="footnav">
+			<a href="Unit-6.html" class="next"></a>
+			<a href="Unit-4.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