diff --git a/src/test/Test.winxed b/src/test/Test.winxed index f7187859..b4b6ea52 100644 --- a/src/test/Test.winxed +++ b/src/test/Test.winxed @@ -40,6 +40,17 @@ namespace Rosella.Test return result.was_successful(); } + function build_suite(var test_type) + { + var suitefactory = new Rosella.Test.SuiteFactory(); + var test_factory = new Rosella.Test.TestFactory(); + + var class_obj = Rosella.get_type_class(test_type); + var test_methods = internal_get_test_methods(class_obj, ""); + + return suitefactory.create(test_factory, test_methods); + } + // Setup and run a single test function over a sequence of data // objects. function test_vector(var func, var tests, var options [slurpy,named]) @@ -55,6 +66,14 @@ namespace Rosella.Test return result.was_successful(); } + function build_suite_vector(var func, var tests) + { + var suitefactory = new Rosella.Test.SuiteFactory.Vector(); + var test_factory = new Rosella.Test.TestFactory(); + + return suitefactory.create(test_factory, tests, func); + } + // Tests in the form of a list. The first argument is a list of callback // functions to execute as individual tests function test_list(var list, var options [slurpy,named]) @@ -70,6 +89,31 @@ namespace Rosella.Test return result.was_successful(); } + function build_suite_list(var list) + { + var suitefactory = new Rosella.Test.SuiteFactory.Vector(); + var test_factory = new Rosella.Test.TestFactory(); + + return suitefactory.create(test_factory, list); + } + + function test_suites(var suites, var options[slurpy,named]) + { + test_vector( + function(var test, var suite) { + var parent_suite = test.status.suite(); + var result = parent_suite.result.get_sub_result(); + result = suite.run(result, parent_suite.context, parent_suite.asserter); + if (!result.was_successful()) { + string msg = sprintf("Failed %d of %d subtests", [result.num_failures, result.total_tests]); + parent_suite.asserter.fail(msg, 1, null); + } + }, + suites, + options:[flat,named] + ); + } + // Get the matcher factory const string DEFAULT_MATCHER_FACTORY = "Rosella.Test.matcher_factory"; function matcher_factory() diff --git a/src/test/TestCase.winxed b/src/test/TestCase.winxed index 0790d5c9..42969769 100644 --- a/src/test/TestCase.winxed +++ b/src/test/TestCase.winxed @@ -7,22 +7,20 @@ TestCase intercepts attribute accesses. Attributes on a TestCase are read-only, and any attempt to modify them from within a running test - will cause an exception. - - By default, TestCase provides two attributes, one for the currently - executing test method object, and one for the current TestContext data - object. Subclasses of TestCase can add additional attributes or - methods which can be used from inside tests. + will cause an exception. TestCase provides four attributes standard: The + currently executing method object, the TestContext object, the TestStatus + object and the Asserter object. TestCase maps attribute names to private internal attributes. This is done to make sure attributes are "natural" for use in both NQP and - Winxed. Also, the names need to be translated anyway to allow them to - be intercepted. Here's a basic mapping: + Winxed, and also that attributes are not modified directly by test code. + Also, the names need to be translated anyway to allow them to be + intercepted. Here's a basic mapping example: "attr" -> "test_attr" "$!attr" -> "test_attr" - The attributes "context" and "$!context" both map to the attribute + The attributes "context" and "$!context" both map to the private attribute "test_context. "method" and "$!method" both map to "test_method". Subclasses of TestCase can follow this pattern to provide access to additional attributes, if needed. @@ -47,17 +45,14 @@ class Rosella.Test.TestCase // agnostic way. function get_attr_str[vtable](string attr_raw) { - var myclass = class Rosella.Test.TestCase; - var value = null; string attr = attr_raw; if (substr(attr, 0, 2) == '$!') attr = substr(attr, 2); - attr = "test_" + attr; try { - value = getattribute_private(self, myclass, attr); + return getattribute_private(self, class Rosella.Test.TestCase, "test_" + attr); } catch(e) { Rosella.Error.invalid(__FUNCTION__, "TestCase does not have an attribute '" + attr_raw + "'"); } - return value; + return null; } } diff --git a/src/test/TestContext.winxed b/src/test/TestContext.winxed index d1b135a6..fbcaf408 100644 --- a/src/test/TestContext.winxed +++ b/src/test/TestContext.winxed @@ -20,11 +20,6 @@ class Rosella.Test.TestContext for running tests. These are not required for normal running of the Suite, and can be optionally disallowed or overridden in custom Context objects. - - Notice that if you don't provide some of these things, they won't - be available to running tests. For instance, this is the only - mechanism for marking a test as todo'd, so if you take that away - you won't be able to use that. */ // Get a named data value diff --git a/src/test/suitefactory/List.winxed b/src/test/suitefactory/List.winxed index 6e86113d..17f141c2 100644 --- a/src/test/suitefactory/List.winxed +++ b/src/test/suitefactory/List.winxed @@ -8,9 +8,11 @@ class Rosella.Test.SuiteFactory.List : Rosella.Test.SuiteFactory */ // Constructor - function List(var suite_type) + function List(var suite_type [optional], int has_type [opt_flag]) { - self.SuiteFactory(suite_type); + if (has_type) + self.SuiteFactory(suite_type); + else self.SuiteFactory(); } // Get a hash of test methods, one for each item in the data aggregate diff --git a/src/test/suitefactory/Vector.winxed b/src/test/suitefactory/Vector.winxed index bece9fcc..ead584e3 100644 --- a/src/test/suitefactory/Vector.winxed +++ b/src/test/suitefactory/Vector.winxed @@ -10,9 +10,11 @@ class Rosella.Test.SuiteFactory.Vector : Rosella.Test.SuiteFactory */ // Constructor - function Vector(var suite_type) + function Vector(var suite_type [optional], int has_type [opt_flag]) { - self.SuiteFactory(suite_type); + if (has_type) + self.SuiteFactory(suite_type); + else self.SuiteFactory(); } // Get a hash of test methods, one for each item in the data aggregate