SOURCE CODE: Uize.Test
VIEW REFERENCE

/*______________
|       ______  |   U I Z E    J A V A S C R I P T    F R A M E W O R K
|     /      /  |   ---------------------------------------------------
|    /    O /   |    MODULE : Uize.Test Class
|   /    / /    |
|  /    / /  /| |    ONLINE : http://www.uize.com
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|          /___ |   LICENSE : Available under MIT License or GNU General Public License
|_______________|             http://www.uize.com/license.html
*/

/* Module Meta Data
  type: Class
  importance: 9
  codeCompleteness: 50
  testCompleteness: 0
  docCompleteness: 100
*/

/*?
  Introduction
    The =Uize.Test= class provides the foundation for a JavaScript Testing Framework, supporting unit testing, functional testing, performance testing, etc.

    *DEVELOPERS:* `Chris van Rensburg`

  ### In a Nutshell
    document...

*/

Uize.module ({
  name:'Uize.Test',
  superclass:'Uize.Class',
  required:[
    'Uize.Data',
    'Uize.Json',
    'Uize.Util.Oop'
  ],
  builder:function (_superclass) {
    /*** Variables for Scruncher Optimization ***/
      var
        _true = true,
        _false = false,
        _undefined
      ;

    /*** General Variables ***/
      var
        _forceAsync = typeof navigator == 'object',
          /* NOTE:
            Force tests to be asynchronous for browsers for two reasons

            1. Some browsers don't repaint while locked in JavaScript execution, so executing tons of tests without giving the browser opportunities to paint DOM updates would make for a lousy experience when running a test suite in a browser.

            2. Some browsers pop up alert dialogs if JavaScript takes too long before returning control, which is definitely not what you want when running a large test suite in a browser.
          */
        _synopsisDivider = '\n----------------------------------------------------------\n\n'
      ;

    /*** Class Constructor ***/
      var
        _class = _superclass.subclass (),
        _classPrototype = _class.prototype
      ;

    /*** Utility Functions ***/
      function _valueToJsonSerializer (_value) {
        return function () {return Uize.Json.to (_value)};
      }

    /*** Private Instance Methods ***/
      _classPrototype._expectSuccess = function (_succeeded,_serializeExpected,_serializeActual) {
        _succeeded ||
          this.set ({
            _reasonForFailure:
              'EXPECTED:\n\n' +
              (Uize.isFunction (_serializeExpected) ? _serializeExpected () : _serializeExpected) + '\n\n' +
              'ACTUAL:\n\n' +
              _serializeActual ()
          })
        ;
        return _succeeded;
      };

    /*** Public Instance Methods ***/
      _classPrototype.expect = function (_expectedValue,_value) {
        return this._expectSuccess (
          Uize.Data.identical (_expectedValue,_value),
          _valueToJsonSerializer (_expectedValue),
          _valueToJsonSerializer (_value)
        );
        /*?
          Instance Methods
            expect
              Returns a boolean value, indicating whether or not the specified actual value is identical to the specified expected value.

              SYNTAX
              ...............................................................
              resultBOOL = myTest.expect (expectedValueANYTYPE,valueANYTYPE);
              ...............................................................

              Identical, Not Same
                When comparing the values of the =expectedValueANYTYPE= and =valueANYTYPE= parameters, the values are compared for identical contents, but not sameness of object references.

                So, for example, the statement =myTest.expect ({foo:'bar'},{foo:'bar'})= would return the value =true=, even though the values of the =expectedValueANYTYPE= and =valueANYTYPE= parameters would be references to different anonymous objects. In cases where you wish to test for sameness, you can use the =expectSameAs= instance method.

              NOTES
              - compare to the =expectSameAs= instance method
              - this method is one of the many available `Expectation Methods`
        */
      };

      _classPrototype.expectSameAs = function (_expectedValue,_value) {
        return this._expectSuccess (
          Uize.isSameAs (_value,_expectedValue),
          _valueToJsonSerializer (_expectedValue),
          _valueToJsonSerializer (_value)
        );
        /*?
          Instance Methods
            expectSameAs
              Returns a boolean value, indicating whether or not the specified actual value is exactly equal to the specified expected value.

              SYNTAX
              .....................................................................
              resultBOOL = myTest.expectSameAs (expectedValueANYTYPE,valueANYTYPE);
              .....................................................................

              Same, Not Identical
                When comparing the values of the =expectedValueANYTYPE= and =valueANYTYPE= parameters, the values are compared using a sameness (strict equality) test, so contents of arrays or objects are not compared.

                So, for example, the statement =myTest.expectSameAs ({foo:'bar'},{foo:'bar'})= would return the value =false=, even though the contents of the objects specified by the =expectedValueANYTYPE= and =valueANYTYPE= parameters are identical. Because the two values are compared using a strict equality, and because the two values would be references to different anonymous objects, they are not considered the same. In cases where you wish to test for identical contents of arrays or objects and not sameness of object references, you can use the =expect= instance method.

              NOTES
              - compare to the =expect= instance method
              - this method is one of the many available `Expectation Methods`
        */
      };

      _classPrototype.expectNonNull = function (_value) {
        return this._expectSuccess (
          _value != null,
          'value that is not null or undefined',
          _valueToJsonSerializer (_value)
        );
        /*?
          Instance Methods
            expectNonNull
              Returns a boolean, indicating whether or not the specified value is non-null (ie. not =null= or =undefined=.

              SYNTAX
              .................................................
              resultBOOL = myTest.expectNonNull (valueANYTYPE);
              .................................................

              This method tests whether or not a value is non-null. Any value other than =null= or =undefined= is considered non-null. So, the boolean value =false=, the number value =0=, the string value =''= (empty string), the object value ={}= (empty object), and the array value =[]= (empty array) are all considered non-null.

              EXAMPLES
              .......................................................
              // when called with non-null values...

              myTest.expectNonNull (1);              // returns true
              myTest.expectNonNull (0);              // returns true
              myTest.expectNonNull ('blah');         // returns true
              myTest.expectNonNull ('');             // returns true
              myTest.expectNonNull (true);           // returns true
              myTest.expectNonNull (false);          // returns true
              myTest.expectNonNull ({foo:'bar'});    // returns true
              myTest.expectNonNull ({});             // returns true
              myTest.expectNonNull (['foo','bar']);  // returns true
              myTest.expectNonNull ([]);             // returns true

              // when called with null values...

              myTest.expectNonNull (null);           // returns false
              myTest.expectNonNull (undefined);      // returns false
              .......................................................

              NOTES
              - this method is one of the many available `Expectation Methods`
        */
      };

      /*** methods for instance type expectations ***/
        _classPrototype.expectInstanceOf = function (_class,_value) {
          return this._expectSuccess (
            _value != _undefined &&
            _value.constructor == (typeof _class == 'string' ? eval (_class) : _class),
            function () {return 'instance of ' + Uize.Util.Oop.getClassName (_class)},
            function () {return 'instance of ' + Uize.Util.Oop.getClassName (_value.constructor)}
          );
          /*?
            Instance Methods
              expectInstanceOf
                Returns a boolean, indicating whether or not the specified value is an instance of the specified class.

                SYNTAX
                ..................................................................
                resultBOOL = myTest.expectInstanceOf (classOBJorSTR,valueANYTYPE);
                ..................................................................

                The value of the =classOBJorSTR= parameter can be an object, being a reference to the expected class, or a string representing the globally accessible name of the class' constructor (='Function'=, ='String'=, ='RegExp'=, ='Uize.Widget.Bar.Slider'=, etc.).

                What Qualifies as an Instance Of?
                  A value specified for the =valueANYTYPE= parameter will be considered to be an instance of a specified class when the following conditions are met...

                  - the value is non-null
                  - the value of the value's =constructor= property is a reference to the class

                Built-in Objects Supported
                  The "class" specified by the =classOBJorSTR= parameter can be a built-in JavaScript object (such as =Function=) or a =Uize.Class= subclass.

                  So, for example, the statement =myTest.expectInstanceOf (RegExp,/^\s+$/)= would return the value =true=.

                Uize Subclasses Supported
                  The class specified by the =classOBJorSTR= parameter can be a =Uize.Class= subclass.

                  So, for example, the statement =myTest.expectInstanceOf (Uize.Widget.Bar,Uize.Widget.Bar ())= would return the value =true=.

                Instances of Subclasses Don't Qualify
                  A value will *not* be considered to be an instance of a specified class if it is, in fact, an instance of a *subclass* of the specified class.

                  So, for example, the statement =myTest.expectInstanceOf (Uize.Widget,Uize.Widget.Bar ())= would return the value =false=.

                Expecting Arrays or Regular Expressions
                  While you can use the =expectInstanceOf= method to test for instances of arrays or regular expressions, there are dedicated `Expectation Methods` to test for instances of those built-in JavaScript objects.

                  To test for instances of the =Array= object, you can use the =expectArray= instance method. So, the statement =myTest.expectInstanceOf (Array,['foo','bar'])= would be equivalent to the more concise statement =myTest.expectArray (['foo','bar'])=. Similarly, the statement =myTest.expectInstanceOf (RegExp,/^\s+$/)= would be equivalent to the more concise statement =myTest.expectRegExp (/^\s+$/)=.

                Null Is Not An Instance of Object
                  While JavaScript's =typeof= operator will return the value ='object'= for the value =null=, the =expectInstanceOf= method does not consider =null= to be an instance of =Object= (mainly because it's not).

                  So, the statement =myTest.expectType ('object',null)= will return the value =true=, while the statement =myTest.expectInstanceOf (Object,null)= will return the value =false=.

                Primitives Are Instances, Too
                  While JavaScript's built-in =instanceof= operator fails to recognize primitive values as instances of the underlying built-in objects that implement their behavior, the =expectInstanceOf= method *does* recognize such primitives as instances.

                  This is because the =expectInstanceOf= method tests to see if the =constructor= property of the value is a reference to the expected class. So, for example, while the statement ='foo' instanceof String= would produce the value =false=, the statement =myTest.expectInstanceOf (String,'foo')= would return the value =true=. This same rule applies also to number and boolean primitives. Also, both of the statements =myTest.expectInstanceOf (String,'foo')= and =myTest.expectInstanceOf (String,new String ('foo'))= would return the value =true=.

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

      /*** methods for type expectations ***/
        _classPrototype.expectType = function (_expectedType,_value) {
          return this._expectSuccess (
            typeof _value == _expectedType,
            function () {return 'type ' + _expectedType},
            function () {return 'type ' + typeof _value}
          );
          /*?
            Instance Methods
              expectType
                Returns a boolean, indicating whether or not the specified value is of the specified type.

                SYNTAX
                ......................................................
                resultBOOL = myTest.expectType (typeSTR,valueANYTYPE);
                ......................................................

                Primitives Versus Instances
                  The =expectType= method uses JavaScript's built-in =typeof= operator to determine the type of the specified actual value.

                  Using the =typeof= operator, instances of JavaScript's built-in =String=, =Number=, and =Boolean= objects are all considered of type ='object'=. So, the statement =myTest.expectType ('string',new String ('foo'))= will return the value =false=, while the statement =myTest.expectType ('object',new String ('foo'))= will return the value =true=. In contrast, the statement =myTest.expectInstanceOf (String,new String ('foo'))= would return the value =true=, while the statement =myTest.expectInstanceOf (String,'foo')= would also return the value =true=.

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectArray = function (_value) {
          return this.expectInstanceOf (Array,_value);
          /*?
            Instance Methods
              expectArray
                Returns a boolean, indicating whether or not the specified value is an instance of JavaScript's built-in =Array= object.

                SYNTAX
                ...............................................
                resultBOOL = myTest.expectArray (valueANYTYPE);
                ...............................................

                Array, Not Array-like
                  The =expectArray= method tests specifically whether or not the value is an instance of the =Array= object.

                  So, in other words, the statement =myTest.expectArray ([])= is equivalent to the statement =myTest.expectInstanceOf (Array,[])=. This method will return the value =false= for values that are only array-like and that are not strictly =Array= instances. An example of an array-like value is a reference to a function's =arguments=. In order to test more broadly for array-like values, you can use the =expectArrayLike= instance method. The statement =myTest.expectArray (arguments)= would return the value =false=, while the statement =myTest.expectArrayLike (arguments)= would return the value =true=.

                NOTES
                - see the related =expectArrayLike= instance method
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectBoolean = function (_value) {
          return this.expectType ('boolean',_value);
          /*?
            Instance Methods
              expectBoolean
                Returns a boolean, indicating whether or not the specified value is a boolean primitive (ie. of type ='boolean'=).

                SYNTAX
                .................................................
                resultBOOL = myTest.expectBoolean (valueANYTYPE);
                .................................................

                Boolean Type, Not Boolean Object Instance
                  The =expectBoolean= method uses JavaScript's built-in =typeof= operator to determine the type of the specified actual value.

                  Using the =typeof= operator, instances of JavaScript's built-in =Boolean= object are considered of type ='object'= - *not* type ='boolean'=. So, the statement =myTest.expectBoolean (new Boolean (false))= will return the value =false=, while the statement =myTest.expectBoolean (false)= will return the value =true=. In contrast, the statement =myTest.expectInstanceOf (Boolean,new Boolean (false))= would return the value =true=, while the statement =myTest.expectInstanceOf (Boolean,false)= would also return the value =true=.

                NOTES
                - see the related =expectType= and =expectInstanceOf= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectFunction = function (_value) {
          return this.expectType ('function',_value);
          /*?
            Instance Methods
              expectFunction
                Returns a boolean, indicating whether or not the specified value is a function (ie. of type ='function'=).

                SYNTAX
                ..................................................
                resultBOOL = myTest.expectFunction (valueANYTYPE);
                ..................................................

                Examples of things that would test true as functions include...

                - static methods (because they are functions)
                - instance methods (because they are functions)
                - anonymous functions
                - functions created using the =Function= constructor
                - constructors for the built-in JavaScript objects, such as =String=, =Boolean=, =Number=, =RegExp=, =Function=, etc.
                - pure =Uize= namespace modules, such as =Uize.Templates=, =Uize.Util=, etc.
                - package modules, such as =Uize.Data=, =Uize.Fx=, =Uize.Node=, etc.
                - class modules, such as =Uize.Class=, =Uize.Fade=, =Uize.Widget=, etc.

                EXAMPLE
                ................................................................................
                myTest.expectFunction (Uize.copyInto);                           // returns true
                myTest.expectFunction (myTest.expectFunction);                   // returns true
                myTest.expectFunction (function (value) {alert (value)});        // returns true
                myTest.expectFunction (new Function ('value','alert (value')));  // returns true
                myTest.expectFunction (Date);                                    // returns true
                myTest.expectFunction (Uize.Util);                               // returns true
                myTest.expectFunction (Uize.Node);                               // returns true
                myTest.expectFunction (Uize.Widget);                             // returns true
                ................................................................................

                NOTES
                - see the related =expectType= and =expectInstanceOf= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNumber = function (_value) {
          return this.expectType ('number',_value);
          /*?
            Instance Methods
              expectNumber
                Returns a boolean, indicating whether or not the specified value is a number primitive (ie. of type ='number'=).

                SYNTAX
                ................................................
                resultBOOL = myTest.expectNumber (valueANYTYPE);
                ................................................

                Number Type, Not Number Object Instance
                  The =expectNumber= method uses JavaScript's built-in =typeof= operator to determine the type of the specified actual value.

                  Using the =typeof= operator, instances of JavaScript's built-in =Number= object are considered of type ='object'= - *not* type ='number'=. So, the statement =myTest.expectNumber (new Number (0))= will return the value =false=, while the statement =myTest.expectNumber (0)= will return the value =true=. In contrast, the statement =myTest.expectInstanceOf (Number,new Number (0))= would return the value =true=, while the statement =myTest.expectInstanceOf (Number,0)= would also return the value =true=.

                EXAMPLES
                .......................................................
                myTest.expectNumber (1);               // returns true
                myTest.expectNumber (0);               // returns true
                myTest.expectNumber (NaN);             // returns true
                myTest.expectNumber (Infinity);        // returns true
                myTest.expectNumber (new Number (5));  // returns false
                .......................................................

                NOTES
                - see the related =expectType= and =expectInstanceOf= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectObject = function (_value) {
          return this.expectType ('object',_value);
          /*?
            Instance Methods
              expectObject
                Returns a boolean, indicating whether or not the specified value is an object (ie. of type ='object'=).

                SYNTAX
                ................................................
                resultBOOL = myTest.expectObject (valueANYTYPE);
                ................................................

                Not Only Object Instances Are Object Type
                  The =expectObject= method uses JavaScript's built-in =typeof= operator to determine the type of the specified actual value.

                  Using the =typeof= operator, instances of many of JavaScript's built-in objects (such as the =Date=, =RegExp=, =Number=, =Boolean=, and =String= objects) are considered of type ='object'= - not just instances of the built-in =Object= object. In addition, the value =null= is considered to be of type ='object'=. If you want to test specifically whether or not a value is an instance of the =Object= object, then you should use a statement like =myTest.expectInstanceOf (Object,value)=.

                EXAMPLES
                ..............................................................................
                myTest.expectObject ({});                                     // returns true
                myTest.expectObject ({foo:'bar'});                            // returns true
                myTest.expectObject (new Object);                             // returns true
                myTest.expectObject ([]);                                     // returns true
                myTest.expectObject (['foo','bar']);                          // returns true
                myTest.expectObject (/^\s+$/);                                // returns true
                myTest.expectObject (new Boolean (false));                    // returns true
                myTest.expectObject (Uize.Widget.Bar.Slider ());              // returns true
                myTest.expectObject (null);                                   // returns true

                myTest.expectObject (undefined);                              // returns false
                myTest.expectObject (function (value) {alert (value)});       // returns false
                myTest.expectObject (new Function ('value','alert (value)');  // returns false
                ..............................................................................

                NOTES
                - see the related =expectType= and =expectInstanceOf= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectRegExp = function (_value) {
          return this.expectInstanceOf (RegExp,_value);
          /*?
            Instance Methods
              expectRegExp
                Returns a boolean, indicating whether or not the specified value is an instance of JavaScript's built-in =RegExp= object.

                SYNTAX
                ................................................
                resultBOOL = myTest.expectRegExp (valueANYTYPE);
                ................................................

                Because the =expectRegExp= method tests whether or not the value is an instance of the =RegExp= object, the statement =myTest.expectRegExp (/^\s+$/)= would be equivalent to the statement =myTest.expectInstanceOf (RegExp,/^\s+$/)=.

                EXAMPLES
                ..............................................................
                myTest.expectObject (/^\s+$/);                // returns true
                myTest.expectObject (new RegExp);             // returns true
                myTest.expectObject (new RegExp ('^\\s+$'));  // returns true

                myTest.expectObject ('^\\s+$');               // returns false
                ..............................................................

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectString = function (_value) {
          return this.expectType ('string',_value);
          /*?
            Instance Methods
              expectString
                Returns a boolean, indicating whether or not the specified value is a string primitive (ie. of type ='string'=).

                SYNTAX
                ................................................
                resultBOOL = myTest.expectString (valueANYTYPE);
                ................................................

                String Type, Not String Object Instance
                  The =expectString= method uses JavaScript's built-in =typeof= operator to determine the type of the specified actual value.

                  Using the =typeof= operator, instances of JavaScript's built-in =String= object are considered of type ='object'= - *not* type ='string'=. So, the statement =myTest.expectString (new String ('foo'))= will return the value =false=, while the statement =myTest.expectString ('foo')= will return the value =true=. In contrast, the statement =myTest.expectInstanceOf (String,new String ('foo'))= would return the value =true=, while the statement =myTest.expectInstanceOf (String,'foo')= would also return the value =true=.

                NOTES
                - see the related =expectType= and =expectInstanceOf= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

      /*** methods for type-like expectations ***/
        _classPrototype.expectArrayLike = function (_value) {
          return (
            this.expectObject (_value) &&
            this.expectNonNull (_value) &&
            this.expectLengthInRange (0,Infinity,_value.length)
          );
          /*?
            Instance Methods
              expectArrayLike
                Returns a boolean, indicating whether or not the specified value is array-like.

                SYNTAX
                ...................................................
                resultBOOL = myTest.expectArrayLike (valueANYTYPE);
                ...................................................

                A value is regarded as array-like when the following conditions are met...

                - the value is of type ='object'=
                - the value is non-null
                - the value's =length= property is a positive number

                Array-like Includes Array
                  Array-like values can be considered a superset that includes strict Array values.

                  So, in other words, while the statement =myTest.expectArray ([])= would return the value =true= but the statement =myTest.expectArray (arguments)= would return the value =false=, *both* the statements =myTest.expectArrayLike ([])= and =myTest.expectArrayLike (arguments)= would return the value =true=. In order to test specifically for =Array= instance values, you should use the =expectArray= instance method.

                NOTES
                - see the related =expectArray= instance method
                - this method is one of the many available `Expectation Methods`
          */
        };

      /*** methods for range expectations ***/
        _classPrototype.expectInRange = function (_minValue,_maxValue,_value) {
          return this._expectSuccess (
            Uize.constrain (_value,_minValue,_maxValue) === _value,
            function () {return 'value within range ' + _minValue + ' to ' + _maxValue},
            _valueToJsonSerializer (_value)
          );
          /*?
            Instance Methods
              expectInRange
                Returns a boolean, indicating whether or not the specified value is in the specified range.

                SYNTAX
                .................................................................................
                resultBOOL = myTest.expectInRange (minValueANYTYPE,maxValueANYTYPE,valueANYTYPE);
                .................................................................................

                Multiple Types Supported
                  The =expectInRange= method uses JavaScript's built-in less =<&#61;= (less than or equal to) and =>&#61;= (greater than or equal to) operators in comparing the specified value to the range boundary values.

                  This means that the type of the =minValueANYTYPE=, =maxValueANYTYPE=, and =valueANYTYPE= parameters can be any type that can be compared using those operators. So, a number can be tested to see if it lies within a numerical range, a string can be tested to see if it lies in an ASCIIbetical range, a date can be tested to see if it lies within a date range, etc.

                  EXAMPLES
                  .........................................................................
                  // range boundaries and value are strings

                    myTest.expectInRange ('betty','samantha','annette');  // returns false
                    myTest.expectInRange ('betty','samantha','kelly');    // returns true
                    myTest.expectInRange ('betty','samantha','wynona');   // returns false


                  // range boundaries are boolean, value is number

                    myTest.expectInRange (false,true,-1);   // returns false
                    myTest.expectInRange (false,true,0);    // returns true
                    myTest.expectInRange (false,true,.5);   // returns true
                    myTest.expectInRange (false,true,1);    // returns true
                    myTest.expectInRange (false,true,1.5);  // returns false


                  // range boundaries and value are date objects

                    myTest.expectInRange (       // returns false
                      new Date ('2010-01-31'),
                      new Date ('2010-12-01'),
                      new Date ('2010-01-15')
                    );
                    myTest.expectInRange (       // returns true
                      new Date ('2010-01-31'),
                      new Date ('2010-12-01'),
                      new Date ('2010-05-13')
                    );
                    myTest.expectInRange (       // returns false
                      new Date ('2010-01-31'),
                      new Date ('2010-12-01'),
                      new Date ('2010-12-22')
                    );


                  // range boundaries and value are class instances

                    myTest.expectInRange (    // returns false
                      Uize.Class ({value:0}),
                      Uize.Class ({value:1}),
                      Uize.Class ({value:-1})
                    );
                    myTest.expectInRange (    // returns true
                      Uize.Class ({value:0}),
                      Uize.Class ({value:1}),
                      Uize.Class ({value:.5})
                    );
                    myTest.expectInRange (    // returns false
                      Uize.Class ({value:0}),
                      Uize.Class ({value:1}),
                      Uize.Class ({value:1.5})
                    );
                  .........................................................................

                Range Boundary Order Unimportant
                  When specifying a value range, the order of the boundaries is unimportant.

                  So, while it is customary to specify minimum value first and maximum value second, the order can be reversed. For example, the statement =myTest.expectNumberInRange (0,100,value)= would be equivalent to the statement =myTest.expectNumberInRange (100,0,value)=. This is particularly useful when the range values are determined programmatically and the first value is not guaranteed to be lower than the second value.

                  EXAMPLE
                  .................................................
                  myTest.expectInRange (100,0,50);  // returns true
                  .................................................

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNumberInRange = function (_minValue,_maxValue,_value) {
          return this.expectNumber (_value) && this.expectInRange (_minValue,_maxValue,_value);
          /*?
            Instance Methods
              expectNumberInRange
                Returns a boolean, indicating whether or not the specified value is a number that falls within the specified range.

                SYNTAX
                ...............................................................................
                resultBOOL = myTest.expectNumberInRange (minValueNUM,maxValueNUM,valueANYTYPE);
                ...............................................................................

                The =expectNumberInRange= method uses the =expectNumber= and =expectInRange= methods in its implementation. The statement =myTest.expectNumberInRange (value,0,100)= would be equivalent to the statement =myTest.expectNumber (value) && myTest.expectInRange (0,100,value)=.

                Range Boundary Order Unimportant
                  When specifying a value range, the order of the boundaries is unimportant.

                  So, while it is customary to specify minimum value first and maximum value second, the order can be reversed. For example, the statement =myTest.expectNumberInRange (0,100,value)= would be equivalent to the statement =myTest.expectNumberInRange (100,0,value)=. This is particularly useful when the range values are determined programmatically and the first value is not guaranteed to be lower than the second value.

                EXAMPLES
                .....................................................................
                myTest.expectNumberInRange (0,100,0);                // returns true
                myTest.expectNumberInRange (0,100,100);              // returns true
                myTest.expectNumberInRange (0,100,50);               // returns true
                myTest.expectNumberInRange (100,0,50);               // returns true

                myTest.expectNumberInRange (0,100,-1);               // returns false
                myTest.expectNumberInRange (0,100,101);              // returns false
                myTest.expectNumberInRange (0,100,'50');             // returns false
                myTest.expectNumberInRange (0,100,true);             // returns false
                myTest.expectNumberInRange (0,100,new Number (50));  // returns false
                .....................................................................

                NOTES
                - see the related =expectNegativeNumber=, =expectPositiveNumber=, =expectNegativeInteger=, =expectPositiveInteger=, and =expectIntegerInRange= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        /*** convenience methods for negative and positive value ranges ***/
          _classPrototype.expectNegativeNumber = function (_value) {
            return this.expectNumberInRange (-Infinity,0,_value);
            /*?
              Instance Methods
                expectNegativeNumber
                  Returns a boolean, indicating whether or not the specified value is a negative number.

                  SYNTAX
                  ........................................................
                  resultBOOL = myTest.expectNegativeNumber (valueANYTYPE);
                  ........................................................

                  A value will be considered to be a negative number when the following conditions are met...

                  - the value is of type ='number'=
                  - the value is in the range of =-Infinity= to =0= (=0= is considered both a negative *and* a positive number)

                  The =expectNegativeNumber= method uses the =expectNumberInRange= method in its implementation. The statement =myTest.expectNegativeNumber (value)= would be equivalent to the statement =myTest.expectNumberInRange (-Infinity,0,value)=.

                  EXAMPLE
                  ........................................................................
                  myTest.expectNegativeNumber (0);                        // returns true
                  myTest.expectNegativeNumber (-.5);                      // returns true
                  myTest.expectNegativeNumber (-Infinity);                // returns true

                  myTest.expectNegativeNumber (1.333);                    // returns false
                  myTest.expectNegativeNumber ('-5');                     // returns false
                  myTest.expectNegativeNumber (Uize.Class ({value:-5}));  // returns false
                  ........................................................................

                  NOTES
                  - see the companion =expectPositiveNumber= instance method
                  - see the related =expectNegativeInteger=, =expectPositiveInteger=, =expectIntegerInRange=, and =expectNumberInRange= instance methods
                  - this method is one of the many available `Expectation Methods`
            */
          };

          _classPrototype.expectPositiveNumber = function (_value) {
            return this.expectNumberInRange (0,Infinity,_value);
            /*?
              Instance Methods
                expectPositiveNumber
                  Returns a boolean, indicating whether or not the specified value is a positive number.

                  SYNTAX
                  ........................................................
                  resultBOOL = myTest.expectPositiveNumber (valueANYTYPE);
                  ........................................................

                  A value will be considered to be a positive number when the following conditions are met...

                  - the value is of type ='number'=
                  - the value is in the range of =0= to =Infinity= (=0= is considered both a positive *and* a positive number)

                  The =expectPositiveNumber= method uses the =expectNumberInRange= method in its implementation. The statement =myTest.expectPositiveNumber (value)= would be equivalent to the statement =myTest.expectNumberInRange (0,Infinity,value)=.

                  EXAMPLE
                  .......................................................................
                  myTest.expectPositiveNumber (0);                       // returns true
                  myTest.expectPositiveNumber (5);                       // returns true
                  myTest.expectPositiveNumber (Infinity);                // returns true

                  myTest.expectPositiveNumber (-1.333);                  // returns false
                  myTest.expectPositiveNumber ('5');                     // returns false
                  myTest.expectPositiveNumber (Uize.Class ({value:5}));  // returns false
                  .......................................................................

                  NOTES
                  - see the companion =expectNegativeNumber= instance method
                  - see the related =expectNegativeInteger=, =expectPositiveInteger=, =expectIntegerInRange=, and =expectNumberInRange= instance methods
                  - this method is one of the many available `Expectation Methods`
            */
          };

        _classPrototype.expectLengthInRange = function (_minLength,_maxLength,_value) {
          var _valueLength = _value.length;
          return this._expectSuccess (
            Uize.constrain (_valueLength,_minLength,_maxLength) === _valueLength,
            function () {return 'length within range ' + _minLength + ' to ' + _maxLength},
            function () {return _valueLength}
          );
          /*?
            Instance Methods
              expectLengthInRange
                Returns a boolean, indicating whether or not the length of the specified value falls into the specified length range.

                SYNTAX
                .................................................................................
                resultBOOL = myTest.expectLengthInRange (minLengthNUM,maxLengthNUM,valueANYTYPE);
                .................................................................................

                Multiple Types Supported
                  The =expectLengthInRange= method supports any type of value for the =valueANYTYPE= parameter, provided that the value has a =length= property.

                  So, the =expectLengthInRange= method can be used to test whether or not a string's length falls within a specific range, whether or not an array's length falls within a specific range, or whether or not the value of the =length= property for any value falls within a range.

                  EXAMPLES
                  .....................................................................
                  // value with length property is string

                    myTest.expectLengthInRange (1,10,'Cleopatra');    // returns true
                    myTest.expectLengthInRange (1,10,'Amanda');       // returns true
                    myTest.expectLengthInRange (1,10,'Margueritta');  // returns false
                    myTest.expectLengthInRange (1,10,'');             // returns false


                  // value with length property is array

                    myTest.expectLengthInRange (1,5,[1,2,3,4,5]);     // returns true
                    myTest.expectLengthInRange (1,5,[1,2,3]);         // returns true
                    myTest.expectLengthInRange (1,5,[1]);             // returns true
                    myTest.expectLengthInRange (1,5,[1,2,3,4,5,6]);   // returns false
                    myTest.expectLengthInRange (1,5,[]);              // returns false


                  // value with length property is object

                    myTest.expectLengthInRange (5,10,{length:10});    // returns true
                    myTest.expectLengthInRange (5,10,{length:5});     // returns true
                    myTest.expectLengthInRange (5,10,{length:11});    // returns false
                    myTest.expectLengthInRange (5,10,{length:4});     // returns false
                  .....................................................................

                Range Boundary Order Unimportant
                  When specifying a value range, the order of the boundaries is unimportant.

                  So, while it is customary to specify minimum value first and maximum value second, the order can be reversed. For example, the statement =myTest.expectLengthInRange (1,10,'Amanda')= would be equivalent to the statement =myTest.expectLengthInRange (10,1,'Amanda')=. This is particularly useful when the range values are determined programmatically and the first value is not guaranteed to be lower than the second value.

                  EXAMPLE
                  ............................................................
                  myTest.expectLengthInRange (10,1,'Amanda');  // returns true
                  ............................................................

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNonEmpty = function (_value) {
          return this._expectSuccess (!Uize.isEmpty (_value),'non-empty',_valueToJsonSerializer (_value));
          /*?
            Instance Methods
              expectNonEmpty
                Returns a boolean, indicating whether or not the specified value is regarded as being empty.

                SYNTAX
                ..................................................
                resultBOOL = myTest.expectNonEmpty (valueANYTYPE);
                ..................................................

                A value specified for the =valueANYTYPE= parameter will be considered empty if it is any of the following...

                - =null=
                - =undefined=
                - =NaN= (the special not-a-number value)
                - =false=
                - =0=
                - =''= (empty string)
                - =[]= (empty array)
                - ={}= (empty object)

                NOTES
                - see also the more specific =expectNonEmptyArray=, =expectNonEmptyObject=, and =expectNonEmptyString= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

      /*** convenience methods for compound expectations ***/
        _classPrototype.expectInteger = function (_value) {
          return (
            this.expectNumber (_value) &&
            this._expectSuccess (Math.floor (_value) == _value,'integer',_valueToJsonSerializer (_value))
          );
          /*?
            Instance Methods
              expectInteger
                Returns a boolean, indicating whether or not the specified value is an integer.

                SYNTAX
                .................................................
                resultBOOL = myTest.expectInteger (valueANYTYPE);
                .................................................

                A value specified for the =valueANYTYPE= parameter will be considered to be an integer when the following conditions are met...

                - the value is of type ='number'=
                - the value does not have a fractional component

                EXAMPLES
                .................................................................
                myTest.expectInteger (10);                       // returns true
                myTest.expectInteger (0);                        // returns true
                myTest.expectInteger (-10);                      // returns true
                myTest.expectInteger (Infinity);                 // returns true

                myTest.expectInteger (10.5);                     // returns false
                myTest.expectInteger ('10');                     // returns false
                myTest.expectInteger (new Number (10));          // returns false
                myTest.expectInteger (Uize.Class ({value:10}));  // returns false
                myTest.expectInteger (NaN);                      // returns false
                .................................................................

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectIntegerInRange = function (_minValue,_maxValue,_value) {
          return this.expectInteger (_value) && this.expectInRange (_minValue,_maxValue,_value);
          /*?
            Instance Methods
              expectIntegerInRange
                Returns a boolean, indicating whether or not the specified value is an integer that falls within the specified range.

                SYNTAX
                ................................................................................
                resultBOOL = myTest.expectIntegerInRange (minValueNUM,maxValueNUM,valueANYTYPE);
                ................................................................................

                The =expectIntegerInRange= method uses the =expectInteger= and =expectInRange= methods in its implementation. The statement =myTest.expectIntegerInRange (0,100,value)= would be equivalent to the statement =myTest.expectInteger (value) && myTest.expectInRange (0,100,value)=.

                Range Boundary Order Unimportant
                  When specifying a value range, the order of the boundaries is unimportant.

                  So, while it is customary to specify minimum value first and maximum value second, the order can be reversed. For example, the statement =myTest.expectIntegerInRange (0,100,value)= would be equivalent to the statement =myTest.expectIntegerInRange (100,0,value)=. This is particularly useful when the range values are determined programmatically and the first value is not guaranteed to be lower than the second value.

                Range Boundaries Can Be Floating Point
                  While the =expectIntegerInRange= method tests, for one thing, that the value of the =valueANYTYPE= parameter is an integer, it is *not* required that the range boundary values be integers.

                  So, for example, the statement =myTest.expectIntegerInRange (0,100.25,100)= would return the value =true=, because the value =100= *is* in the range of =0= to =100.25=.

                EXAMPLES
                .......................................................................
                myTest.expectIntegerInRange (0,100,0);                 // returns true
                myTest.expectIntegerInRange (0,100,100);               // returns true
                myTest.expectIntegerInRange (0,100,50);                // returns true
                myTest.expectIntegerInRange (100,0,50);                // returns true
                myTest.expectIntegerInRange (0,100.25,100);            // returns true

                myTest.expectIntegerInRange (100,0,.5);                // returns false
                myTest.expectIntegerInRange (0,100,-1);                // returns false
                myTest.expectIntegerInRange (0,100,101);               // returns false
                myTest.expectIntegerInRange (0,100,'.5');              // returns false
                myTest.expectIntegerInRange (0,100,true);              // returns false
                myTest.expectIntegerInRange (0,100,new Number (.5));   // returns false
                .......................................................................

                NOTES
                - see the related =expectNegativeNumber=, =expectPositiveNumber=, =expectNegativeInteger=, =expectPositiveInteger=, and =expectNumberInRange= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNegativeInteger = function (_value) {
          return this.expectInteger (_value) && this.expectNegative (_value);
          /*?
            Instance Methods
              expectNegativeInteger
                Returns a boolean, indicating whether or not the specified value is a negative integer.

                SYNTAX
                .........................................................
                resultBOOL = myTest.expectNegativeInteger (valueANYTYPE);
                .........................................................

                A value will be considered to be a negative integer when the following conditions are met...

                - the value is of type ='number'=
                - the value does not have a fractional component
                - the value is in the range of =-Infinity= to =0= (=0= is considered both a negative *and* a positive number)

                The =expectNegativeInteger= method uses the =expectIntegerInRange= method in its implementation. The statement =myTest.expectNegativeInteger (value)= would be equivalent to the statement =myTest.expectIntegerInRange (-Infinity,0,value)=.

                EXAMPLE
                .........................................................................
                myTest.expectNegativeInteger (0);                        // returns true
                myTest.expectNegativeInteger (-1);                       // returns true
                myTest.expectNegativeInteger (-Infinity);                // returns true

                myTest.expectNegativeInteger (-1.5);                     // returns false
                myTest.expectNegativeInteger ('-1');                     // returns false
                myTest.expectNegativeInteger (Uize.Class ({value:-1}));  // returns false
                myTest.expectNegativeInteger (1);                        // returns false
                myTest.expectNegativeInteger (1.5);                      // returns false
                .........................................................................

                NOTES
                - see the companion =expectPositiveInteger= instance method
                - see the related =expectNegativeNumber=, =expectPositiveNumber=, =expectIntegerInRange=, and =expectNumberInRange= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectPositiveInteger = function (_value) {
          return this.expectInteger (_value) && this.expectPositive (_value);
          /*?
            Instance Methods
              expectPositiveInteger
                Returns a boolean, indicating whether or not the specified value is a positive integer.

                SYNTAX
                .........................................................
                resultBOOL = myTest.expectPositiveInteger (valueANYTYPE);
                .........................................................

                A value will be considered to be a positive integer when the following conditions are met...

                - the value is of type ='number'=
                - the value does not have a fractional component
                - the value is in the range of =0= to =Infinity= (=0= is considered both a positive *and* a positive number)

                The =expectPositiveInteger= method uses the =expectIntegerInRange= method in its implementation. The statement =myTest.expectPositiveInteger (value)= would be equivalent to the statement =myTest.expectIntegerInRange (0,Infinity,value)=.

                EXAMPLE
                ........................................................................
                myTest.expectPositiveInteger (0);                       // returns true
                myTest.expectPositiveInteger (1);                       // returns true
                myTest.expectPositiveInteger (Infinity);                // returns true

                myTest.expectPositiveInteger (1.5);                     // returns false
                myTest.expectPositiveInteger ('1');                     // returns false
                myTest.expectPositiveInteger (Uize.Class ({value:1}));  // returns false
                myTest.expectPositiveInteger (-1);                      // returns false
                myTest.expectPositiveInteger (-1.5);                    // returns false
                ........................................................................

                NOTES
                - see the companion =expectNegativeInteger= instance method
                - see the related =expectNegativeNumber=, =expectPositiveNumber=, =expectIntegerInRange=, and =expectNumberInRange= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNoRepeats = function (_value) {
          return this._expectSuccess (
            Uize.totalKeys (Uize.lookup (_value)) == _value.length,
            'array with no repeated values',
            _valueToJsonSerializer (_value)
          );
          /*?
            Instance Methods
              expectNoRepeats
                Returns a boolean, indicating whether or not there are no repeated values in the specified array.

                SYNTAX
                ...................................................
                resultBOOL = myTest.expectNoRepeats (valueANYTYPE);
                ...................................................

                EXAMPLES
                .........................................................
                myTest.expectNoRepeats ([1,2,3,4,5]);    // returns true
                myTest.expectNoRepeats ([1,2,3,4,5,2]);  // returns false
                .........................................................

                NOTES
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNonEmptyArray = function (_value) {
          return this.expectArray (_value) && this.expectNonEmpty (_value);
          /*?
            Instance Methods
              expectNonEmptyArray
                Returns a boolean, indicating whether or not the specified value is an instance of JavaScript's built-in =Array= object and has a non-zero length.

                SYNTAX
                .......................................................
                resultBOOL = myTest.expectNonEmptyArray (valueANYTYPE);
                .......................................................

                This method uses the =expectArray= and =expectNonEmpty= methods in its implementation. The statement =myTest.expectNonEmptyArray (value)= is equivalent to the statement =this.expectArray (value) && this.expectNonEmpty (value)=.

                EXAMPLES
                ............................................................................
                myTest.expectNonEmptyArray (['foo','bar']);                 // returns true
                myTest.expectNonEmptyArray (new Array ('foo','bar'));       // returns true
                myTest.expectNonEmptyArray (new Array (5));                 // returns true

                myTest.expectNonEmptyArray ([]);                            // returns false
                myTest.expectNonEmptyArray (new Array);                     // returns false
                myTest.expectNonEmptyArray (Uize.Class ({value:['foo']}));  // returns false
                myTest.expectNonEmptyArray ({foo:'bar'});                   // returns false
                myTest.expectNonEmptyArray (1.2345);                        // returns false
                myTest.expectNonEmptyArray (true);                          // returns false
                ............................................................................

                NOTES
                - compare to the =expectNonEmpty=, =expectNonEmptyObject=, and =expectNonEmptyString= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNonEmptyObject = function (_value) {
          return this.expectObject (_value) && this.expectNonEmpty (_value);
          /*?
            Instance Methods
              expectNonEmptyObject
                Returns a boolean, indicating whether or not the specified value is of type ='object'= and has at least one enumerable property.

                SYNTAX
                ........................................................
                resultBOOL = myTest.expectNonEmptyObject (valueANYTYPE);
                ........................................................

                This method uses the =expectObject= and =expectNonEmpty= methods in its implementation. The statement =myTest.expectNonEmptyObject (value)= is equivalent to the statement =this.expectObject (value) && this.expectNonEmpty (value)=.

                EXAMPLES
                ...........................................................................
                myTest.expectNonEmptyObject ({foo:'bar'});                 // returns true
                myTest.expectNonEmptyObject (new Object ({foo:'bar'}));    // returns true
                myTest.expectNonEmptyObject (['foo','bar']);               // returns true
                myTest.expectNonEmptyObject (new Array (5));               // returns true
                myTest.expectNonEmptyObject (Uize.Class ({value:'foo'}));  // returns true
                myTest.expectNonEmptyObject ({});                          // returns false
                myTest.expectNonEmptyObject (new Object);                  // returns false
                myTest.expectNonEmptyObject ([]);                          // returns false
                myTest.expectNonEmptyObject (new Array);                   // returns false
                myTest.expectNonEmptyObject (1.2345);                      // returns false
                myTest.expectNonEmptyObject (true);                        // returns false
                ...........................................................................

                Not Only Object Instances Are Object Type
                  The =expectNonEmptyObject= method relies on JavaScript's built-in =typeof= operator to determine the type of the specified actual value.

                  Using the =typeof= operator, instances of many of JavaScript's built-in objects (such as the =Date=, =RegExp=, =Number=, =Boolean=, and =String= objects) are considered of type ='object'= - not just instances of the built-in =Object= object. Therefore, instances of any object or class will be considered non-empty objects if they contain any enumerable properties.

                NOTES
                - compare to the =expectNonEmpty=, =expectNonEmptyArray=, and =expectNonEmptyString= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

        _classPrototype.expectNonEmptyString = function (_value) {
          return this.expectString (_value) && this.expectNonEmpty (_value);
          /*?
            Instance Methods
              expectNonEmptyString
                Returns a boolean, indicating whether or not the specified value is of type ='string'= and contains one or more characters.

                SYNTAX
                ........................................................
                resultBOOL = myTest.expectNonEmptyString (valueANYTYPE);
                ........................................................

                This method uses the =expectString= and =expectNonEmpty= methods in its implementation. The statement =myTest.expectNonEmptyString (value)= is equivalent to the statement =this.expectString (value) && this.expectNonEmpty (value)=.

                EXAMPLES
                ...........................................................................
                myTest.expectNonEmptyString ('foo');                       // returns true

                myTest.expectNonEmptyString ('');                          // returns false
                myTest.expectNonEmptyString (new String ('foo'));          // returns false
                myTest.expectNonEmptyString (Uize.Class ({value:'foo'}));  // returns false
                myTest.expectNonEmptyString (1.2345);                      // returns false
                myTest.expectNonEmptyString (true);                        // returns false
                ...........................................................................

                NOTES
                - compare to the =expectNonEmpty=, =expectNonEmptyArray=, and =expectNonEmptyObject= instance methods
                - this method is one of the many available `Expectation Methods`
          */
        };

      _classPrototype.getDepth = function () {
        var
          _depth = 0,
          _parent = this
        ;
        while (_parent = _parent.parent) _depth++;
        return _depth;
        /*?
          Instance Methods
            getDepth
              Returns an integer, indicating how deep within the test instance tree the test instance is.

              SYNTAX
              ..............................
              depthINT = myTest.getDepth ();
              ..............................

              The depth of a test instance is determined by traversing up the =parent= chain, all the way up to the root test. The depth of the root test is reported as =0=, the depth of a child test of the root test is reported as =1=, the depth of a child test of that child test is reported as =2=, and so on.

              NOTES
              - see the related =parent= instance property
              - see the related =getTotalTests= instance method
        */
      };

      _classPrototype.getTotalTests = function () {
        var _totalTests = 0;
        function _getTotalTests (_subtests) {
          _totalTests++;
          if (Uize.isArray (_subtests)) {
            for (var _subtestNo = -1, _subtestsLength = _subtests.length; ++_subtestNo < _subtestsLength;)
              _getTotalTests (_subtests [_subtestNo]._test)
            ;
          }
        }
        _getTotalTests (this._test);
        return _totalTests;
        /*?
          Instance Methods
            getTotalTests
              Returns an integer, indicating the total number of tests inside the test instance's test tree.

              SYNTAX
              ........................................
              totalTestsINT = myTest.getTotalTests ();
              ........................................

              This method recurses through the entire tree, essentially flattening the tree in order to count the total number of actual tests that would be performed. The method includes parent tests in the tally, along with all child tests. For example, if the test contained two child tests, and each one of those child tests contained two child tests, then the total number of tests in the tree would be =7= - one root test, two child tests, and four grandchild tests.

              NOTES
              - see the related =getDepth= instance method
        */
      };

      _classPrototype.getSynopsis = function () {
        var
          _this = this,
          _result = _this._result,
          _synopsis = (_result ? 'PASSED' : 'FAILED') + '\n',
          _reasonForFailure = _this._reasonForFailure
        ;
        /*** add the breadcrumbs ***/
          var
            _testParent = _this,
            _testBreadcrumbs = [],
            _testBreadcrumbsStr = '',
            _testBreadcrumbIndent = ''
          ;
          while (_testParent) {
            _testBreadcrumbs.push (_testParent._title);
            _testParent = _testParent.parent;
          }
          for (var _testBreadcrumbNo = _testBreadcrumbs.length; --_testBreadcrumbNo > -1;) {
            _testBreadcrumbsStr +=
              _testBreadcrumbIndent + _testBreadcrumbs [_testBreadcrumbNo] + '\n'
            ;
            _testBreadcrumbIndent += '   ';
          }
          _synopsis += _synopsisDivider + 'BREADCRUMBS...\n\n' + _testBreadcrumbsStr;

        /*** add the time information ***/
          _synopsis +=
            _synopsisDivider +
            'TIME STARTED: ' + _this._startTime + '\n' +
            'TIME ENDED: ' + _this._endTime + '\n' +
            'DURATION: ' + _this._duration + 'ms\n'
          ;

        if (!_result && _reasonForFailure)
          _synopsis += _synopsisDivider + 'REASON FOR FAILURE...\n\n' + _reasonForFailure
        ;
        return _synopsis;
        /*?
          Instance Methods
            getSynopsis
              Returns a string, providing a synopsis of the test instance's run.

              SYNTAX
              ....................................
              synopsisSTR = myTest.getSynopsis ();
              ....................................

              This method is useful when providing a report for a test, especially if the test fails. The synopsis provides an indication of whether the test passed or failed, breadcrumbs to indicate where the test is in a test tree, when the test started and ended and its duration, and the reason for failure if the test failed.

              NOTES
              - see also the =reasonForFailure= and =result= state properties
        */
      };

      _classPrototype.stop = function () {
        var _this = this;
        Uize.isArray (_this._test) && Uize.callOn (_this._test,'stop');
        _this.set ({_inProgress:false});
        /*?
          Instance Methods
            stop
              Stops running of the test instance's test(s).

              SYNTAX
              ...............
              myTest.stop ();
              ...............

              Upon calling the =stop= method, the =stop= method will first be called on any child tests belonging to the test, after which the =inProgress= state property for the instance will be set to =false=. If the instance is not running its test(s) at the time that this method is called, then calling it will have no effect.

              NOTES
              - see the companion =run= instance method
              - see the related =inProgress= state property
        */
      };

      _classPrototype.run = function (_callback) {
        /* NOTE:
          Ultimately, this code should find its way into the onChange handler for the inProgress state property, and then this method can be supplanted by a simple start method that only stops the test and then sets the inProgress property to true, making the interface for this class more in line with the Uize.Fade class.
        */
        var
          _this = this,
          _test = _this._test,
          _testResult = _true
        ;
        _this.stop ();
        _this.set ({
          _inProgress:_true,
          _progress:0,
          _startTime:new Date,
          _duration:_undefined,
          _endTime:_undefined,
          _isAsync:_false,
          _log:[],
          _result:_undefined,
          _reasonForFailure:_undefined
        });
        _this.fire ({name:'Start',bubble:_true});
        /*?
          Instance Events
            Start
              An bubbling instance event that is fired whenever the instance's test is run by calling its =run= instance method.

              NOTES
              - this event bubbles
              - see the companion =Done= instance event
        */
        function _updateResultProperty () {
          if (_testResult !== _true && _testResult !== _undefined && _testResult != _isAsync)
            _testResult = _false
          ;
          _this.set ({_result:_testResult});
          if (_testResult == _isAsync) {
            _this.set ({_isAsync:_true});
          } else {
            var _endTime = new Date;
            _this.set ({
              _duration:_endTime - _this._startTime,
              _endTime:_endTime,
              _progress:1
            });
            _this.stop (); // TO DO: why is this being called here, and will this lead to excessive recursive calling of stop on subtests, even when test running is not aborted?
            _this.fire ({name:'Done',bubble:_true});
            /*?
              Instance Events
                Done
                  An bubbling instance event that is fired whenever the instance's test completes running.

                  NOTES
                  - this event bubbles
                  - see the companion =Start= instance event
            */
            _this._isAsync && _callback && _callback (_testResult);
          }
        }
        if (Uize.isArray (_test)) {
          var
            _testLength = _test.length,
            _testNo = -1
          ;
          function _continue () {
            _this.set ({_progress:(_testNo + 1) / _testLength});
            function _setResultAndContinue (_result) {
              _testResult = _result;
              _continue ();
            }
            while (_this._inProgress && _testResult === _true && ++_testNo < _testLength)
              _testResult = _test [_testNo].run (_setResultAndContinue)
            ;
            _updateResultProperty ();
          }
          _continue ();
        } else {
          try {
            _testResult = _isAsync;
            var
              _returned = _false,
              _testFunctionReturnValue = _test.call (
                _this,
                function (_result) {
                  _testResult = _result;
                  _returned && _updateResultProperty ();
                }
              )
            ;
            if (_testFunctionReturnValue !== _undefined)
              _testResult = _testFunctionReturnValue
            ;
            _returned = true;
          } catch (_error) {
            _this.set ({
              _reasonForFailure:
                'JavaScript Error...\n' +
                'ERROR NAME: ' + _error.name + '\n' +
                'ERROR MESSAGE: ' + _error.message + '\n' +
                'ERROR DESCRIPTION: ' + _error.description + '\n' +
                'LINE NUMBER: ' + _error.number + '\n'
            });
            _testResult = _false;
          }
          if (_testResult != _isAsync && _forceAsync) {
            var _storedTestResult = _testResult;
            _testResult = _isAsync;
            _updateResultProperty ();
            setTimeout (
              function () {
                _testResult = _storedTestResult;
                _updateResultProperty ();
              },
              0
            );
          } else {
            _updateResultProperty ();
          }
        }

        return _testResult;
        /*?
          Instance Methods
            run
              Runs the instance's test(s) and returns the result.

              SYNTAX
              ...........................
              resultBOOL = myTest.run ();
              ...........................

              In the event that running of the instance's test(s) is asynchronous, the =run= method will return the value =Uize.Test.isAsync=, and the instance's =isAsync= state property will be set to the value =true=. For a more in-depth discussion, see the section `Asynchronous Tests` in the [[../explainers/javascript-testing-framework.html][JavaScript Testing Framework]] explainer.

              Callback Function For Asynchronous Tests
                When the optional =callbackFUNC= parameter is specified, a callback function can be specified that will be called once running of the instance's test(s) is complete, in the event that running of the instance's test(s) is asynchronous.

                VARIATION
                .......................................
                resultBOOL = myTest.run (callbackFUNC);
                .......................................

                The callback function should expect to receive one parameter, being the result value for the test.

              NOTES
              - see the companion =stop= instance method
        */
      };

      _classPrototype.log = function (_message) {
        this._log.push ({timestamp:new Date,message:_message});
        /*?
          Instance Methods
            log Instance Method
              Adds the specified message, along with a generated timestamp, to the =log= array for the instance and returns a reference to the instance.

              SYNTAX
              .................................
              myTest = myTest.log (messageSTR);
              .................................

              NOTES
              - see the related =log= state property
        */
      };

    /*** Public Static Properties ***/
      var _isAsync = _class.isAsync = function () {};
      /*?
        Static Properties
          Uize.Test.isAsync
            A read-only special value that is used to indicate that running of a test instance's test(s) is asynchronous.

            When a test instance is known to be asynchronous, the instance's =result= state property will be set to the value =Uize.Test.isAsync=. In this situation, the instance's =isAsync= state property will also be set to the value =true=. For a more in-depth discussion, see the section `Asynchronous Tests` in the [[../explainers/javascript-testing-framework.html][JavaScript Testing Framework]] explainer.

            NOTES
            - see the related =isAsync= and =result= state properties
      */

    /*** Public Static Methods ***/
      _class.addTest = function (_test) {
        (this._test || (this._test = [])).push (this.declare (_test));
        return this;
        /*?
          Static Methods
            Uize.Test.addTest
              Adds the specified child test to the test class and returns a reference to the test class.

              SYNTAX
              ............................
              Uize.Test.addTest (testOBJ);
              ............................
        */
      };

      var _splitHostAndProperty = _class.splitHostAndProperty = function (_propertyFullName) {
        var _lastPeriodPos = _propertyFullName.lastIndexOf ('.');
        return {
          host:_propertyFullName.slice (0,_lastPeriodPos),
          property:_propertyFullName.slice (_lastPeriodPos + 1)
        };
        /*?
          Static Methods
            Uize.Test.splitHostAndProperty
              Returns an object, containing =host= and =property= properties that represent the specified property full path name split into the two parts.

              SYNTAX
              ..........................................................................
              hostAndPropertyOBJ = Uize.Test.splitHostAndProperty (propertyFullNameSTR);
              ..........................................................................

              RETURN VALUE
              .............................
              {
                host     : hostPathSTR,
                property : propertyNameSTR
              }
              .............................

              The value of the =propertyFullNameSTR= parameter should be a string that fully qualifies the path for referencing a property in the global context (eg. ='Uize.Test.declare'=). The =Uize.Test.splitHostAndProperty= method splits this string into host and property strings, and packages these two string values into an object. Supplied our example value of ='Uize.Test.declare'=, the =Uize.Test.splitHostAndProperty= method would return the object ={host:'Uize.Test',property:'declare'}=.
        */
      };

      /*** factory methods for creating test classes using declarative syntax ***/
        _class.declare = function (_test) {
          if (!Uize.Util.Oop.inheritsFrom (_test,Uize.Test)) {
            var _testProperties = _test;

            /*** if test property is an array, then resolve all the subtests ***/
              var _subtests = _testProperties.test;
              if (Uize.isArray (_subtests)) {
                for (
                  var _subtestNo = -1, _subtestsLength = _subtests.length, _subtest;
                  ++_subtestNo < _subtestsLength;
                )
                  if ((_subtest = _subtests [_subtestNo]).constructor == Object)
                    _subtests [_subtestNo] = this.declare (_subtest)
                ;
              }

            (_test = this.subclass ()).set (_testProperties);
          }
          return _test;
          /*?
            Static Methods
              Uize.Test.declare
                Returns a =Uize.Test= subclass, being the specified test object resolved to a test class.

                SYNTAX
                ........................................
                testCLASS = Uize.Test.declare (testOBJ);
                ........................................

                testOBJ
                  An object, being either a set of property values for the state properties of the =Uize.Test= class, or a reference to a =Uize.Test= subclass.

                  In the event that the =testOBJ= parameter's value is a set of property value, a new subclass of the =Uize.Test= class is created, and its state properties are initialized with the values contained in the =testOBJ= object. The value of the =test= property receives special handling (see `Resolving Subtests`).

                More Concise and Declarative
                  The =Uize.Test.declare= method allows for a more concise, declarative syntax for defining tests.

                  INSTEAD OF...
                  ..................................................
                  var My2Plus2Equals4TestClass = Uize.Test.subclass ();
                  My2Plus2Equals4TestClass.set ({
                    title:'Test that 2 + 2 equals 4',
                    test:function () {return this.expect (4,2 + 2)}
                  });
                  ..................................................

                  USE...
                  ..................................................
                  Uize.Test.declare ({
                    title:'Test that 2 + 2 equals 4',
                    test:function () {return this.expect (4,2 + 2)}
                  });
                  ..................................................

                Returns a Test Class
                  Because the =Uize.Test.declare= method returns a =Uize.Test= subclass, it can be used for declaring a child test in an array of child tests, as with all the other `Test Class Factory Methods` (see `Example 2: A Set of Tests` for an illustration of this).

                Resolving Subtests
                  If a test properties object is specified for the =testOBJ= parameter (rather than a =Uize.Test= subclass), then the value of that object's =test= property is further resolved.

                  If the value of the =test= property is an array of child tests, then the elements of the child tests array are resolved to test classes by calling the =Uize.Test.declare= method for each of them, where each element value becomes the value of the =Uize.Test.declare= method's =testOBJ= parameter. For an example of this type of usage, see the `Example 2: A Set of Tests`.

                Example 1: A Single Test
                  In this example, a simple test class is being created using the =Uize.Test.declare= method.

                  EXAMPLE
                  ..................................................
                  Uize.Test.declare ({
                    title:'Test that 2 + 2 equals 4',
                    test:function () {return this.expect (4,2 + 2)}
                  });
                  ..................................................

                  The value of the =test= state property in this case is a function, which will be executed when an instance of the test class is run using the =run= instance method.

                Example 2: A Set of Tests
                  In this example, a test class is being created that serves as a wrapper for a set of child tests.

                  EXAMPLE
                  ........................................................................
                  Uize.Test.declare ({
                    title:'Test a whole bunch of things',
                    test:[
                      {
                        title:'Test that 2 + 2 equals 4',
                        test:function () {return this.expect (4,2 + 2)}
                      },
                      Uize.Test.declare ({
                        title:'Test that true is equal to 1 in a simple equality test',
                        test:function () {return this.expect (true,1 == true)}
                      }),
                      Uize.Test.staticPropertyTest ('Math.min','function'),
                      Uize.Test.staticPropertyTest ('Number.MAX_VALUE','number')
                    ]
                  });
                  ........................................................................

                  The value of the =test= state property in this case is an array, which contains a sequence of child tests. The elements of the child tests array are resolved to test classes (see `Resolving Subtests`). In this example, the child tests array contains a mix of child tests declared in different ways: the first child test is declared using the simple object syntax, the second is declared by calling the =Uize.Test.declare= method explicitly, and the remaining child tests are declared by calling the =Uize.Test.staticPropertyTest= static method.

                NOTES
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

        _class.requiredModulesTest = function (_modules) {
          return this.declare ({
            title:'REQUIRED MODULES TEST: ' + _modules,
            test:function (_continue) {
              Uize.module ({
                required:_modules,
                builder:function () {_continue (true)}
              });
            }
          });
          /*?
            Static Methods
              Uize.Test.requiredModulesTest
                Returns a =Uize.Test= subclass, for a test that tests whether or not the specified module(s) can be successfully required (and loaded and built, if necessary).

                SYNTAX
                ..............................................................
                testCLASS = Uize.Test.requiredModulesTest (modulesSTRorARRAY);
                ..............................................................

                modulesSTRorARRAY
                  The value of the =modulesSTRorARRAY= parameter can be a string, specifying the full name of a single module or a comma-separated list of the full names for multiple modules, or an array of the full names for multiple modules.

                  Essentially, the value specified for the =modulesSTRorARRAY= parameter can be any value that is acceptable for the =required= property in a =Uize.module= declaration (see the explainer [[../explainers/javascript-modules.html][JavaScript Modules]] for a refresher on modules).

                An Example
                  The =Uize.Test.requiredModulesTest= method is useful for creating a first test in a series of tests for a module that is being tested. Consider the following example...

                  EXAMPLE
                  .............................................................
                  var testClassForUizeArrayOrder = Uize.Test.declare ({
                    title:'Uize.Array.Order Module Test',
                    test:[
                      Uize.Test.requiredModulesTest ('Uize.Array.Order'),
                      Uize.Test.staticMethodsTest ([
                        // ...
                        // static method tests here, in comma-separated list
                        // ...
                      ])
                    ]
                  });
                  .............................................................

                  In the above example, a test class is being created for testing the =Uize.Array.Order= module, using the =Uize.Test.declare= static method (another of the `Test Class Factory Methods`). As you will notice, the very first child test in our test class is being created using the =Uize.Test.requiredModulesTest= method. This tests requiring the =Uize.Array.Order= module. If the test fails, then subsequent tests will not be performed. If the test succeeds, then the =Uize.Array.Order= module is guaranteed to be built and can be relied upon for the subsequent tests that will test the module's various features, such as its static methods.

                NOTES
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

        _class.staticPropertyTest = function (_propertyFullName,_expectedType) {
          var
            _hostAndProperty = _splitHostAndProperty (_propertyFullName),
            _propertyHost = _hostAndProperty.host
          ;
          return this.declare ({
            title:'Test that ' + _propertyFullName + ' exists and is a ' + _expectedType,
            test:[
              {
                title:'Test that host ' + _propertyHost + ' is defined',
                test:function () {return this.expectNonNull (eval (_propertyHost))}
              },
              {
                title:'Test that ' + _propertyFullName + ' is a ' + _expectedType,
                test:function () {
                  return this.expectType (
                    _expectedType,
                    eval (_propertyHost) [_hostAndProperty.property]
                  );
                }
              }
            ]
          });
          /*?
            Static Methods
              Uize.Test.staticPropertyTest
                Returns a =Uize.Test= subclass, for a test that tests whether or not the specified static property exists and is of the specified type.

                SYNTAX
                .......................................................................
                testCLASS = Uize.Test.staticPropertyTest (propertyFullNameSTR,typeSTR);
                .......................................................................

                propertyFullNameSTR
                  A string, specifying the full name of the static property, including the full host path.

                  For example, with the "isAsync" property of the =Uize.Test= module, the value specified for the =propertyFullNameSTR= parameter would be ='Uize.Test.isAsync'=.

                What Comprises a Static Property Test
                  The test class created by the =Uize.Test.staticPropertyTest= method has two child tests.

                  The first test tests whether or not the property's host is defined (with the value ='Uize.Test.isAsync'= specified for the =propertyFullNameSTR= parameter, that would test for =Uize.Test= to be defined). The second test tests that the specified property is of the specified type.

                An Example
                  The following example serves merely to illustrate the behavior of a static property test (typically static property tests won't be created in this way - they will typically be incorporated into a list of other tests, in a more concise declarative statement).

                  EXAMPLE
                  .........................................................................................
                  var
                    StaticPropertyTestClass = Uize.Test.staticPropertyTest ('Uize.Test.isAsync','object'),
                    staticPropertyTest = new StaticPropertyTestClass
                  ;
                  staticPropertyTest.run (
                    function () {
                      alert (staticPropertyTest.get ('result'));  // displays true
                    }
                  );
                  .........................................................................................

                  In the above example, a test class is being created to test for the =Uize.Test.isAsync= static property. The test class is assigned to the =StaticPropertyTestClass= variable. Then, an instance of that test class is created, assigned to the =staticPropertyTest= variable, and then run. Upon completion, the callback function is executed and the result of the test is reported in a JavaScript alert. The result is =true= (assuming something hasn't been broken in the =Uize.Test= module), since the =Uize.Test.isAsync= static property is of type ='object'=.

                NOTES
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

        _class.staticMethodTest = function (_methodFullName,_cases,_testProperties,_caseTestProperties) {
          var
            _this = this,
            _hostAndProperty = _splitHostAndProperty (_methodFullName),
            _methodHostName = _hostAndProperty.host,
            _methodName = _hostAndProperty.property,
            _test = [_this.staticPropertyTest (_methodFullName,'function')]
          ;
          function _getCaseTest (_case) {
            var _caseTest = Uize.isArray (_case)
              ? {
                title:_case [0],
                test:function () {
                  var
                    _methodHost = eval (_methodHostName),
                    _arguments = this.get ('cloneArguments') ? Uize.clone (_case [1]) : _case [1]
                  ;
                  return this.expect (
                    _case [2],
                    _methodHost [_methodName].apply (
                      _methodHost,
                      Uize.isArray (_arguments) ? _arguments : [_arguments]
                    )
                  );
                }
              }
              : _case
            ;
            if (_caseTestProperties)
              Uize.Util.Oop.inheritsFrom (_caseTest,Uize.Test)
                ? _caseTest.set (_caseTestProperties)
                : Uize.copyInto (_caseTest,_caseTestProperties)
            ;
            return _caseTest;
          }
          for (var _caseNo = -1, _casesLength = _cases.length; ++_caseNo < _casesLength;)
            _test.push (_getCaseTest (_cases [_caseNo]))
          ;
          var _testClass = _this.declare (
            Uize.copyInto (
              {
                title:'STATIC METHOD TEST: ' + _methodFullName,
                test:_test
              },
              _testProperties
            )
          );
          return _testClass;
          /*?
            Static Methods
              Uize.Test.staticMethodTest
                Returns a =Uize.Test= subclass, for a test that tests whether or not the specified static method is defined and all the specified test cases succeed.

                SYNTAX
                .................................................
                testCLASS = Uize.Test.staticMethodTest (
                  methodFullNameSTR,
                  casesARRAY,
                  supplementalTestPropertiesOBJ,     // optional
                  supplementalCaseTestPropertiesOBJ  // optional
                );
                .................................................

                methodFullNameSTR
                  A string, specifying the full name of the static method, including the full host path.

                  For example, with the "declare" method of the =Uize.Test= module, the value specified for the =methodFullNameSTR= parameter would be ='Uize.Test.declare'=.

                casesARRAY
                  An array, containing a sequence of test cases, all of which need to succeed in order for the static method test to succeed.

                  STRUCTURE
                  ..................
                  [
                    caseARRAYorOBJ,
                    caseARRAYorOBJ,
                    ...
                    caseARRAYorOBJ
                  ]
                  ..................

                  Each element of the =casesARRAY= array should be of the type =caseARRAYorOBJ= and will be resolved to a =Uize.Test= subclass.

                  caseARRAYorOBJ
                    An array, providing a concise declaration of a synchronous, deterministic test case for the static method, or an object providing a declaration of a generic test, or an instance of a =Uize.Test= subclass.

                    Synchronous and Deterministic Cases
                      When an array value is specified for the =caseARRAYorOBJ= value type, then the case describes a synchronous and deterministic test of the static method, and the array should have the following structure...

                      caseARRAY
                      ................................................................................
                      [
                        titleSTR,              // the title of the test case
                        argumentsANYTYPE,      // arguments to be used when calling the static method
                        expectedResultANYTYPE  // the expected return value for the test case
                      ]
                      ................................................................................

                      - =titleSTR= - a string, specifying the title of the test case
                      - =argumentsANYTYPE= - either an array of argument values, or a non-array value for the method's single argument (NOTE: in cases where the value for a method's single argument is an array, then that array value *must* be wrapped in an arguments array so that the =Uize.Test.staticMethodTest= method doesn't mistake that array for the arguments array)
                      - =expectedResultANYTYPE= - the result that is expected to be returned by the static method when calling it with the arguments specified for the case

                    Asynchronous or Non-deterministic Cases
                      When a case is either asynchronous or non-deterministic (ie. you can't be guaranteed to always get the same result returned for the same argument values), then you cannot use the concise array syntax for declaring the case as you can with `Synchronous and Deterministic Cases`.

                      Instead, you can use the object syntax accepted for the =testOBJ= parameter of the =Uize.Test.declare= static method, or you can provide a =Uize.Test= subclass (created by one of the `Test Class Factory Methods`, or otherwise created).

                supplementalTestPropertiesOBJ
                  When the optional =supplementalTestPropertiesOBJ= parameter is specified, then additional values for the state properties of the created =Uize.Test= subclass can be specified.

                  Among other things, this allows the =title= of the test class to be specified (rather than using the automatically generated title).

                supplementalCaseTestPropertiesOBJ
                  The optional =supplementalCaseTestPropertiesOBJ= parameter lets you specify supplemental test properties that should be applied to each of the cases specified by the =casesARRAY= parameter.

                An Example
                  In the following example, a test class is being created for the =Uize.capFirstChar= static method.

                  EXAMPLE
                  ..................................................................
                  Uize.Test.staticMethodTest (
                    'Uize.capFirstChar',
                    [
                      ['Many letters, first letter is lowercase','hello','Hello'],
                      ['Many letters, first letter is uppercase','Hello','Hello'],
                      ['Single letter, lowercase','h','H'],
                      ['Single letter, uppercase','H','H'],
                      ['Empty string','','']
                    ]
                  );
                  ..................................................................

                  Notice how, with each of the test cases, the value specified for the arguments is a string - not an array. This is because the =Uize.capFirstChar= method takes only one parameter, and for cases where methods only take a single parameter, the =Uize.Test.staticMethodTest= method supports that single value being specified without the arguments array "wrapper".

                NOTES
                - see the related =Uize.Test.staticMethodsTest= static method
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

        _class.staticMethodsTest = function (_staticMethodsTest) {
          var _this = this;
          return _this.declare ({
            title:'Static Method Tests',
            test:Uize.map (
              _staticMethodsTest,
              function (_staticMethodTest) {
                return (
                  Uize.isArray (_staticMethodTest)
                    ? _this.staticMethodTest.apply (_this,_staticMethodTest)
                    : _staticMethodTest
                );
              }
            )
          });
          /*?
            Static Methods
              Uize.Test.staticMethodsTest
                Returns a =Uize.Test= subclass, for a test that tests all the specified test cases of all the specified static methods.

                SYNTAX
                .................................................................
                testCLASS = Uize.Test.staticMethodsTest (staticMethodsTestARRAY);
                .................................................................

                The =Uize.Test.staticMethodsTest= method is a convenience method that provides a more concise way to declare static methods tests for multiple static methods in a single statement.

                staticMethodsTestARRAY
                  An array, where each element of the array specifies a test for a specific static method.

                  STRUCTURE
                  ..............................
                  [
                    staticMethodTestARRAYorOBJ,
                    staticMethodTestARRAYorOBJ,
                    ...
                    staticMethodTestARRAYorOBJ
                  ]
                  ..............................

                staticMethodTestARRAYorOBJ
                  An array, specifying the parameter values for a call to the =Uize.Test.staticMethodTest= static method, or a value that can be used for the =testOBJ= parameter of the =Uize.Test.declare= static method and that will be resolved to a =Uize.Test= subclass.

                  If an array value is specified for the =staticMethodTestARRAYorOBJ= value type, then it should have the following structure...

                  staticMethodTestARRAY
                  ...........................................................................
                  [
                    methodFullNameSTR,  // full name of static method, including module path
                    casesARRAY          // array of test cases
                  ]
                  ...........................................................................

                  When a non-array value is specified for the =staticMethodTestARRAYorOBJ= value type, then it will be resolved to a =Uize.Test= subclass using the =Uize.Test.declare= static method.

                EXAMPLE
                .................................................................................
                Uize.Test.staticMethodsTest ([
                  ['Uize.String.trimLeft',[
                    ['Test that left-trimming empty string produces empty string',
                      '',
                      ''
                    ],
                    ['Test that left-trimming string with no padding returns the same string',
                      'hello',
                      'hello'
                    ],
                    ['Test that left-trimming string with leading spaces works',
                      '   hello',
                      'hello'
                    ],
                    ['Test that left-trimming string with trailing spaces works',
                      'hello   ',
                      'hello   '
                    ],
                    ['Test that left-trimming string with leading and trailing spaces works',
                      '   hello   ',
                      'hello   '
                    ],
                    ['Test that left-trimming does not affect inner whitesapce',
                      ' hello \t there ',
                      'hello \t there '
                    ],
                    ['Test that left-trimming string with tab padding works',
                      '\t\thello\t\t',
                      'hello\t\t'
                    ]
                  ]],
                  ['Uize.String.trimRight',[
                    ['Test that right-trimming empty string produces empty string',
                      '',
                      ''
                    ],
                    ['Test that right-trimming string with no padding returns the same string',
                      'hello',
                      'hello'
                    ],
                    ['Test that right-trimming string with leading spaces works',
                      '   hello',
                      '   hello'
                    ],
                    ['Test that right-trimming string with trailing spaces works',
                      'hello   ',
                      'hello'
                    ],
                    ['Test that right-trimming string with leading and trailing spaces works',
                      '   hello   ',
                      '   hello'
                    ],
                    ['Test that right-trimming does not affect inner whitesapce',
                      ' hello \t there ',
                      ' hello \t there'
                    ],
                    ['Test that right-trimming string with tab padding works',
                      '\t\thello\t\t',
                      '\t\thello'
                    ]
                  ]]
                ]);
                .................................................................................

                In the above (rather long) example, static method tests are being declared for the =Uize.String.trimLeft= and =Uize.String.trimRight= static methods of the =Uize.String= module.

                NOTES
                - see the related =Uize.Test.staticMethodTest= static method
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

        _class.testModuleTest = function (_testModule) {
          var _loadTestModuleTest = this.requiredModulesTest (_testModule);
          _loadTestModuleTest.set ({_title:'REQUIRE TEST MODULE: ' + _testModule});
          return this.declare ({
            title:'TEST MODULE: ' + _testModule,
            test:[
              _loadTestModuleTest,
              {
                title:'RUN TEST MODULE: ' + _testModule,
                test:function (_continue) {
                  var
                    _this = this,
                    _testModuleInstance = new (eval (_testModule))
                  ;
                  _testModuleInstance.wire (
                    'Done',
                    function (_event) {
                      var _eventSource = _event.source;
                      _eventSource._reasonForFailure && _this.set ({
                        _reasonForFailure:
                          'running test module failed with the following synopsis...\n\n' +
                          _eventSource.getSynopsis ()
                      });
                      _eventSource.parent || _continue (_eventSource._result);
                    }
                  );
                  _testModuleInstance.run ();
                }
              }
            ]
          });
          /*?
            Static Methods
              Uize.Test.testModuleTest
                Returns a =Uize.Test= subclass, for a test that safely tests the loading and running of a test module.

                SYNTAX
                .....................................................
                testCLASS = Uize.Test.testModuleTest (testModuleSTR);
                .....................................................

                The test class created by this method first tests whether or not the specified test module can be successfully required (and loaded and built, if necessary). It does this using a child test created using the =Uize.Test.requiredModulesTest= static method. If the test module can be successfully required, then it is run by instantiating it and calling its =run= instance method.

                EXAMPLE
                ............................................................................
                uizeDataTestModuleRunner = Uize.Test.testModuleTest ('Uize.Test.Uize.Data');
                ............................................................................

                NOTES
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

        _class.testSuite = function (_testSuiteTitle,_testSuiteModules) {
          var _this = this;
          return _this.declare ({
            title:_testSuiteTitle,
            test:Uize.map (
              _testSuiteModules,
              function (_testSuiteModule) {return _this.testModuleTest (_testSuiteModule)}
            )
          });
          /*?
            Static Methods
              Uize.Test.testSuite
                Returns a =Uize.Test= subclass, for a test that combines multiple separate test modules into a single test suite.

                SYNTAX
                ..........................................................................
                testCLASS = Uize.Test.testSuite (testSuiteTitleSTR,testSuiteModulesARRAY);
                ..........................................................................

                The =Uize.Test.testSuite= method wraps each of the test modules specified in the =testSuiteModulesARRAY= parameter in a test module test, using the =Uize.Test.testModuleTest= static method. This ensures that the many individual test modules that make up a test suite are only loaded dynamically as needed when the test suite is run - they are not directly required by the test suite test, and they do not need to be loaded in just so that the test suite's test class can be built. This is a good thing, because many of the test modules are rather large.

                EXAMPLE
                ..........................................
                var uizeTestSuite = Uize.Test.testSuite (
                  'UIZE JavaScript Framework Unit Tests',
                  [
                    'Uize.Test.Uize.Data',
                    'Uize.Test.Uize',
                    'Uize.Test.Uize.Array',
                    'Uize.Test.Uize.Array.Order',
                    'Uize.Test.Uize.Array.Sort',
                    'Uize.Test.Uize.Data.Csv',
                    'Uize.Test.Uize.Date',
                    // ... ... ... ... ... ...
                    // more test modules here
                    // ... ... ... ... ... ...
                  ]
                );
                ..........................................

                In the above example, a test suite test class is being created to sequence execution of a series of test modules that test various modules of the UIZE JavaScript Framework.

                NOTES
                - this method is one of the many available `Test Class Factory Methods`
          */
        };

    /*** Register Properties ***/
      _class.registerProperties ({
        _duration:'duration',
          /*?
            State Properties
              duration
                A number, representing how long it took for the test instance to run, measured in milliseconds.

                Before a test instance has been run for the first time, the value of this property will be =undefined=. The value will also be reset to =undefined= each time the test is started, and will remain =undefined= while the test is in progress.

                NOTES
                - the initial value is =undefined=
          */
        _endTime:'endTime',
          /*?
            State Properties
              endTime
                An instance of JavaScript's =Date= object, that is set to the time at which running of the test instance ended.

                Before a test instance has been run for the first time, the value of this property will be =undefined=. The value will also be reset to =undefined= each time the test is started, and will remain =undefined= while the test is in progress. The value will be reset to the current time each time the test ends running.

                NOTES
                - see also the companion =startTime= and =duration= state properties
                - the initial value is =undefined=
          */
        _inProgress:{
          name:'inProgress',
          value:_false
          /*?
            State Properties
              inProgress
                A boolean, indicating whether or not the test instance is busy running its test(s).

                The value of this property is set to =true= each time the test is started, and is set back to =false= each time the test ends running.

                NOTES
                - see also the related =progress= state property
                - the initial value is =false=
          */
        },
        _isAsync:'isAsync',
          /*?
            State Properties
              isAsync
                A boolean, indicating whether or not running the test instance's test(s) is asynchronous.

                The value =undefined= is equivalent to the boolean value =false=. When a test is run in the browser context, the value of this property is coerced to =true=. For a more in-depth discussion, see the section `Asynchronous Tests` in the [[../explainers/javascript-testing-framework.html][JavaScript Testing Framework]] explainer.

                NOTES
                - see the related =Uize.Test.isAsync= static property
                - the initial value is =undefined=
          */
        _log:'log',
          /*?
            State Properties
              log
                An array, containing all of the messages logged using the =log Instance Method=.

                Before a test instance has been run for the first time, the value of this property will be =undefined=. The value will also be reset to =[]= (an empty array) each time the test is started. Each element of the =log= array is an object with the following structure...

                LOG MESSAGE OBJECT
                .................................................................................
                {
                  message   : messageSTR,  // the text of the log message
                  timestamp : dataOBJ      // the time at which the message was added to the log
                }
                .................................................................................

                NOTES
                - see the related =log Instance Method=
                - the initial value is =undefined=
          */
        _progress:{
          name:'progress',
          value:0
          /*?
            State Properties
              progress
                A floating point number in the range of =0= to =1=, indicating how far the test instance is in running its test(s).

                Before a test instance has been run for the first time, the value of this property will be =0=. The value will also be reset to =0= each time the test is started. The value will be set to the =1= when the test ends running. During running of the test, the value will be updated periodically to reflect the progress that has been made. The =progress= is calculated by dividing the number of `Subtests` that have completed running by the total number of subtests defined in the =test= state property. Importantly, the value of this property does not reflect updates in the progress of individual subtests.

                NOTES
                - see also the related =inProgress= state property
          */
        },
        _reasonForFailure:'reasonForFailure',
          /*?
            State Properties
              reasonForFailure
                A string, providing an explanation for why the test failed, or the value =undefined= if the test has not failed.

                Before a test instance has been run for the first time, the value of this property will be =undefined=. The value will also be reset to =undefined= each time the test is started, and will remain =undefined= while the test is in progress. If the test fails, the value of this property is typically set in a call to one of the `Expectation Methods`, along with the =result= state property being set to =false=.

                NOTES
                - see also the related =result= state property
                - the initial value is =undefined=
          */
        _result:'result',
          /*?
            State Properties
              result
                A boolean, indicating whether or not the test passed, or the value =undefined= or =Uize.Test.isAsync=.

                A value of =true= indicates that the test was completed and passed, while a value of =false= indicates that the test was completed and failed or was aborted with a catastrophic failure. A value of =undefined= indicates that the test result has not yet been determined, while a value of =Uize.Test.isAsync= indicates that determination of the result is waiting upon the completion of asynchronous code.

                Before a test instance has been run for the first time, the value of this property will be =undefined=. The value will also be reset to =undefined= each time the test is started, and will remain =undefined= until the result is determined, or will be set to the constant value =Uize.Test.isAsync= if the test is known to be asynchronous.

                NOTES
                - see also the related =reasonForFailure= state property
                - the initial value is =undefined=
          */
        _startTime:'startTime',
          /*?
            State Properties
              startTime
                An instance of JavaScript's =Date= object, that is set to the time at which running of the test instance started.

                Before a test instance has been run for the first time, the value of this property will be =undefined=. The value will be reset to the current time each time the test is started.

                NOTES
                - see also the companion =endTime= and =duration= state properties
                - the initial value is =undefined=
          */
        _test:{
          name:'test',
          conformer:function (_value) {
            if (Uize.isArray (_value)) {
              var _this = this;
              _value = Uize.map (_value,function (_subtest) {return new _subtest ({parent:_this})});
              /*?
                Instance Properties
                  parent
                    A reference to the =Uize.Test= instance that serves as the parent for the test instance.

                    A test instance is parented when it is instantiated by its parent test. The root test in a test tree is never parented, and so the value of the =parent= property for the root test remains =undefined=.

                    NOTES
                    - the initial value is =undefined=
              */
            }
            return _value;
          }
          /*?
            State Properties
              test
                A test function, or an array of child tests where each element is an instance of a =Uize.Test= subclass.

                The Simple Test Case
                  In the case of a simple test that has no child tests, the value of the =test= property should be a reference to the function that performs the test action.

                  This function will be executed when the test is run by calling the =run= instance method. When the function is called, it will be called as an instance method of the test instance, so it will have access to the instance for the purpose of calling any of the `Expectation Methods`, or for accessing state of the instance through its various state properties. The function should expect to receive a single parameter, being a continuation function that can be called in case the test is asynchronous (see the section on `Asynchronous Tests` in the [[../explainers/javascript-testing-framework.html][JavaScript Testing Framework]] explainer for more details). In the case of synchronous tests, the test function should return a boolean value, indicating whether the test passed or failed.

                The Child Tests Case
                  In the case of a test that is serving as a parent for a set of child tests, the value of the =test= property will be an array of child test instances.

                  In such cases, when the test is run all of its child tests contained in the =test= array will be executed in sequence. If any of the child tests fail, execution of the remaining child tests will be terminated.
          */
        },
        _title:'title'
          /*?
            State Properties
              title
                A string, representing the title of the test instance.

                The title of a test is used when generating a synopsis for a test using the =getSynopsis= instance method. The title can also be used by a test runner application whose interface provides logging for tests as they are being run.
          */
      });

    return _class;
  }
});