package com.ericfeminella.tests
{
import com.ericfeminella.collections.ArrayList;
import com.ericfeminella.collections.Collection;
import com.ericfeminella.collections.Iterator;
import com.ericfeminella.utils.AbstractStaticType;
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
import flexunit.framework.TestSuite;
/**
*
* All static utility class which provides a mechanism for adding
* a <code>TestCase</code> to a <code>TestSuite</code> for each
* method defined by a specific class
*
* @example The following example demonstrates how a class which
* extends TestCase can utilize <code>TestSuiteBuilder</code> to
* automate the creation of the associated <code>TestSuite</code>
*
* <listing version="3.0">
*
* package
* {
* public class ExampleTest extends TestCase
* {
* public function testX() : void
* {
* // test implementation...
* }
*
* public function testY() : void
* {
* // test implementation...
* }
*
* public function testZ() : void
* {
* // test implementation...
* }
* }
* }
*
* // TestRunner.mxml on creationComplete Event
* private function onCreationComplete() : void
* {
* testRunner.test = TestSuiteFactory.createSuite( ExampleTest );
* testRunner.startTest();
* }
*
* // creates a new TestSuite and adds each method defined by ExampleTest
* // to the suite
*
* </listing>
*
* @see flexunit.framework.TestSuite
* @see flexunit.framework.TestCase
*
*/
public final class TestSuiteFactory extends AbstractStaticType
{
/**
*
* Specifies all inherited test fixtures which are not to be included in
* the tests.
*
*/
protected static const FIXTURES:Array = [ "addAsync",
"countTestCases",
"getNextAsync",
"getTestMethodNames",
"hasAsync",
"run",
"runFinish",
"runMiddle",
"runStart",
"runWithResult",
"setTestResult",
"setUp",
"startAsync",
"tearDown",
"toString" ];
/**
*
* Creates a <code>TestSuite</code> and, through introspection,
* determines all methods defined by a specific class which
* extends <code>TestCase</code> and adds each method to the
* <code>TestSuite</code>
*
* @param the class in which to locate all tests
* @return a <code>TestSuite</code> containing all of the tests
*
*/
public static function createSuite(Type:Class) : TestSuite
{
var tests:XMLList = getTests( Type );
var testSuite:TestSuite = new TestSuite();
for each ( var methodName:String in tests.@name )
{
if ( !isTestFixture( methodName ) )
{
testSuite.addTest( new Type( methodName ) );
}
}
return testSuite;
}
/**
*
* Creates a <code>TestSuite</code> which contains all test classes
* to be run as part of the <code>TestRunner</code>.
*
* <p>
* <code>createSuites</code> requires an <code>Array</code> of Class
* objects which extend <code>TestCase</code>. Each Class in the Array
* will have all public methods added to a suite, which in turn will
* run in the test runner. By creating an <code>Array</code> containing
* each test class to be tested, and invoking <code>createSuites</code>
* the process of creating <code>TestSuites</code> for every test
* method can be completely automated.
* </p>
*
*/
public static function createSuites(client:TestSuiteFactoryClient) : TestSuite
{
var suite:TestSuite = new TestSuite();
var allTests:Collection = client.allTests;
var it:Iterator = allTests.iterator;
while ( it.hasNext() )
{
var TestClass:Class = it.next() as Class;
suite.addTest( createSuite( TestClass ) );
}
return suite;
}
/**
*
* Retrieves all tests which have been defined for a specific
* <code>TestCase</code> sub class
*
* @param the class or type in which to locate tests
* @return an <code>XMLList</code> containing all test names
*
*/
protected static function getTests(Type:Class) : XMLList
{
var type:String = getQualifiedClassName( Type );
var definedMethods:XMLList = describeType(Type)..method.(@declaredBy == type)
return definedMethods;
}
/**
*
* @private
*
* <code>TestSuiteFactory.isTestFixture</code> determines if the specified
* method is an override of a defined test fixture, if so this operation
* returns true, otherwise false.
*
* @param specified method in which to validate
* @return true if method name is not a test fixture, otherwise false
*
*/
private static function isTestFixture(methodName:String) : Boolean
{
var list:ArrayList = ArrayList.createArrayList( FIXTURES );
var it:Iterator = list.iterator;
var valid:Boolean = false;
while ( it.hasNext() )
{
if ( it.next() == methodName )
{
valid = true;
}
}
return valid;
}
}
}