You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2013/05/28 19:47:37 UTC

[lucy-commits] [04/19] Rework Clownfish test harness

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestHighlightWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.c b/core/Lucy/Test/Index/TestHighlightWriter.c
index 791da1b..9e7dcc5 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.c
+++ b/core/Lucy/Test/Index/TestHighlightWriter.c
@@ -18,26 +18,20 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestHighlightWriter.h"
 #include "Lucy/Index/HighlightWriter.h"
 
 TestHighlightWriter*
-TestHLWriter_new(TestFormatter *formatter) {
-    TestHighlightWriter *self = (TestHighlightWriter*)VTable_Make_Obj(TESTHIGHLIGHTWRITER);
-    return TestHLWriter_init(self, formatter);
-}
-
-TestHighlightWriter*
-TestHLWriter_init(TestHighlightWriter *self, TestFormatter *formatter) {
-    return (TestHighlightWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestHLWriter_new() {
+    return (TestHighlightWriter*)VTable_Make_Obj(TESTHIGHLIGHTWRITER);
 }
 
 void
-TestHLWriter_run_tests(TestHighlightWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "Placeholder");
+TestHLWriter_run(TestHighlightWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "Placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestHighlightWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.cfh b/core/Lucy/Test/Index/TestHighlightWriter.cfh
index d761e38..cb8ce9f 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.cfh
+++ b/core/Lucy/Test/Index/TestHighlightWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestHighlightWriter cnick TestHLWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHighlightWriter*
-    new(TestFormatter *formatter);
-
-    inert TestHighlightWriter*
-    init(TestHighlightWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestHighlightWriter *self);
+    Run(TestHighlightWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestIndexManager.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.c b/core/Lucy/Test/Index/TestIndexManager.c
index a856300..f878381 100644
--- a/core/Lucy/Test/Index/TestIndexManager.c
+++ b/core/Lucy/Test/Index/TestIndexManager.c
@@ -17,24 +17,18 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestIndexManager.h"
 #include "Lucy/Index/IndexManager.h"
 
 TestIndexManager*
-TestIxManager_new(TestFormatter *formatter) {
-    TestIndexManager *self = (TestIndexManager*)VTable_Make_Obj(TESTINDEXMANAGER);
-    return TestIxManager_init(self, formatter);
-}
-
-TestIndexManager*
-TestIxManager_init(TestIndexManager *self, TestFormatter *formatter) {
-    return (TestIndexManager*)TestBatch_init((TestBatch*)self, 34, formatter);
+TestIxManager_new() {
+    return (TestIndexManager*)VTable_Make_Obj(TESTINDEXMANAGER);
 }
 
 static void
-test_Choose_Sparse(TestBatch *batch) {
+test_Choose_Sparse(TestBatchRunner *runner) {
     IndexManager *manager = IxManager_new(NULL, NULL);
 
     for (uint32_t num_segs = 2; num_segs < 20; num_segs++) {
@@ -43,14 +37,14 @@ test_Choose_Sparse(TestBatch *batch) {
             I32Arr_Set(doc_counts, j, 1000);
         }
         uint32_t threshold = IxManager_Choose_Sparse(manager, doc_counts);
-        TEST_TRUE(batch, threshold != 1,
+        TEST_TRUE(runner, threshold != 1,
                   "Either don't merge, or merge two segments: %u segs, thresh %u",
                   (unsigned)num_segs, (unsigned)threshold);
 
         if (num_segs != 12 && num_segs != 13) {  // when 2 is correct
             I32Arr_Set(doc_counts, 0, 1);
             threshold = IxManager_Choose_Sparse(manager, doc_counts);
-            TEST_TRUE(batch, threshold != 2,
+            TEST_TRUE(runner, threshold != 2,
                       "Don't include big next seg: %u segs, thresh %u",
                       (unsigned)num_segs, (unsigned)threshold);
         }
@@ -62,8 +56,8 @@ test_Choose_Sparse(TestBatch *batch) {
 }
 
 void
-TestIxManager_run_tests(TestIndexManager *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Choose_Sparse(batch);
+TestIxManager_run(TestIndexManager *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 34);
+    test_Choose_Sparse(runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestIndexManager.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.cfh b/core/Lucy/Test/Index/TestIndexManager.cfh
index 105b833..5b2c2e1 100644
--- a/core/Lucy/Test/Index/TestIndexManager.cfh
+++ b/core/Lucy/Test/Index/TestIndexManager.cfh
@@ -20,12 +20,9 @@ class Lucy::Test::Index::TestIndexManager cnick TestIxManager
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIndexManager*
-    new(TestFormatter *formatter);
-
-    inert TestIndexManager*
-    init(TestIndexManager *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestIndexManager *self);
+    Run(TestIndexManager *self, TestBatchRunner *runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestPolyReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.c b/core/Lucy/Test/Index/TestPolyReader.c
index 2f8dfc5..21e3cf1 100644
--- a/core/Lucy/Test/Index/TestPolyReader.c
+++ b/core/Lucy/Test/Index/TestPolyReader.c
@@ -18,24 +18,18 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestPolyReader.h"
 #include "Lucy/Index/PolyReader.h"
 
 TestPolyReader*
-TestPolyReader_new(TestFormatter *formatter) {
-    TestPolyReader *self = (TestPolyReader*)VTable_Make_Obj(TESTPOLYREADER);
-    return TestPolyReader_init(self, formatter);
-}
-
-TestPolyReader*
-TestPolyReader_init(TestPolyReader *self, TestFormatter *formatter) {
-    return (TestPolyReader*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestPolyReader_new() {
+    return (TestPolyReader*)VTable_Make_Obj(TESTPOLYREADER);
 }
 
 static void
-test_sub_tick(TestBatch *batch) {
+test_sub_tick(TestBatchRunner *runner) {
     size_t num_segs = 255;
     int32_t *ints = (int32_t*)MALLOCATE(num_segs * sizeof(int32_t));
     size_t i;
@@ -46,14 +40,14 @@ test_sub_tick(TestBatch *batch) {
     for (i = 1; i < num_segs; i++) {
         if (PolyReader_sub_tick(offsets, i) != i - 1) { break; }
     }
-    TEST_INT_EQ(batch, i, num_segs, "got all sub_tick() calls right");
+    TEST_INT_EQ(runner, i, num_segs, "got all sub_tick() calls right");
     DECREF(offsets);
     FREEMEM(ints);
 }
 
 void
-TestPolyReader_run_tests(TestPolyReader *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_sub_tick(batch);
+TestPolyReader_run(TestPolyReader *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    test_sub_tick(runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestPolyReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.cfh b/core/Lucy/Test/Index/TestPolyReader.cfh
index 36c957e..6c1c409 100644
--- a/core/Lucy/Test/Index/TestPolyReader.cfh
+++ b/core/Lucy/Test/Index/TestPolyReader.cfh
@@ -20,12 +20,9 @@ class Lucy::Test::Index::TestPolyReader
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPolyReader*
-    new(TestFormatter *formatter);
-
-    inert TestPolyReader*
-    init(TestPolyReader *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPolyReader *self);
+    Run(TestPolyReader *self, TestBatchRunner *runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestPostingListWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.c b/core/Lucy/Test/Index/TestPostingListWriter.c
index f393665..0b559dc 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.c
+++ b/core/Lucy/Test/Index/TestPostingListWriter.c
@@ -18,25 +18,19 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestPostingListWriter.h"
 
 TestPostingListWriter*
-TestPListWriter_new(TestFormatter *formatter) {
-    TestPostingListWriter *self = (TestPostingListWriter*)VTable_Make_Obj(TESTPOSTINGLISTWRITER);
-    return TestPListWriter_init(self, formatter);
-}
-
-TestPostingListWriter*
-TestPListWriter_init(TestPostingListWriter *self, TestFormatter *formatter) {
-    return (TestPostingListWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestPListWriter_new() {
+    return (TestPostingListWriter*)VTable_Make_Obj(TESTPOSTINGLISTWRITER);
 }
 
 void
-TestPListWriter_run_tests(TestPostingListWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "Placeholder");
+TestPListWriter_run(TestPostingListWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "Placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestPostingListWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.cfh b/core/Lucy/Test/Index/TestPostingListWriter.cfh
index 5c460bf..14ef955 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.cfh
+++ b/core/Lucy/Test/Index/TestPostingListWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestPostingListWriter cnick TestPListWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPostingListWriter*
-    new(TestFormatter *formatter);
-
-    inert TestPostingListWriter*
-    init(TestPostingListWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPostingListWriter *self);
+    Run(TestPostingListWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestSegWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.c b/core/Lucy/Test/Index/TestSegWriter.c
index 1e26311..d67e866 100644
--- a/core/Lucy/Test/Index/TestSegWriter.c
+++ b/core/Lucy/Test/Index/TestSegWriter.c
@@ -18,26 +18,20 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSegWriter.h"
 #include "Lucy/Index/SegWriter.h"
 
 TestSegWriter*
-TestSegWriter_new(TestFormatter *formatter) {
-    TestSegWriter *self = (TestSegWriter*)VTable_Make_Obj(TESTSEGWRITER);
-    return TestSegWriter_init(self, formatter);
-}
-
-TestSegWriter*
-TestSegWriter_init(TestSegWriter *self, TestFormatter *formatter) {
-    return (TestSegWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestSegWriter_new() {
+    return (TestSegWriter*)VTable_Make_Obj(TESTSEGWRITER);
 }
 
 void
-TestSegWriter_run_tests(TestSegWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "placeholder");
+TestSegWriter_run(TestSegWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestSegWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.cfh b/core/Lucy/Test/Index/TestSegWriter.cfh
index 1ca9eaa..1a6cf18 100644
--- a/core/Lucy/Test/Index/TestSegWriter.cfh
+++ b/core/Lucy/Test/Index/TestSegWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestSegWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSegWriter*
-    new(TestFormatter *formatter);
-
-    inert TestSegWriter*
-    init(TestSegWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSegWriter *self);
+    Run(TestSegWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestSegment.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.c b/core/Lucy/Test/Index/TestSegment.c
index f0a3596..f8547c9 100644
--- a/core/Lucy/Test/Index/TestSegment.c
+++ b/core/Lucy/Test/Index/TestSegment.c
@@ -18,25 +18,19 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSegment.h"
 #include "Lucy/Index/Segment.h"
 #include "Lucy/Store/RAMFolder.h"
 
 TestSegment*
-TestSeg_new(TestFormatter *formatter) {
-    TestSegment *self = (TestSegment*)VTable_Make_Obj(TESTSEGMENT);
-    return TestSeg_init(self, formatter);
-}
-
-TestSegment*
-TestSeg_init(TestSegment *self, TestFormatter *formatter) {
-    return (TestSegment*)TestBatch_init((TestBatch*)self, 21, formatter);
+TestSeg_new() {
+    return (TestSegment*)VTable_Make_Obj(TESTSEGMENT);
 }
 
 static void
-test_fields(TestBatch *batch) {
+test_fields(TestBatchRunner *runner) {
     Segment *segment = Seg_new(1);
     ZombieCharBuf *foo = ZCB_WRAP_STR("foo", 3);
     ZombieCharBuf *bar = ZCB_WRAP_STR("bar", 3);
@@ -44,34 +38,34 @@ test_fields(TestBatch *batch) {
     int32_t field_num;
 
     field_num = Seg_Add_Field(segment, (CharBuf*)foo);
-    TEST_TRUE(batch, field_num == 1,
+    TEST_TRUE(runner, field_num == 1,
               "Add_Field returns field number, and field numbers start at 1");
     field_num = Seg_Add_Field(segment, (CharBuf*)bar);
-    TEST_TRUE(batch, field_num == 2, "add a second field");
+    TEST_TRUE(runner, field_num == 2, "add a second field");
     field_num = Seg_Add_Field(segment, (CharBuf*)foo);
-    TEST_TRUE(batch, field_num == 1,
+    TEST_TRUE(runner, field_num == 1,
               "Add_Field returns existing field number if field is already known");
 
-    TEST_TRUE(batch, ZCB_Equals(bar, (Obj*)Seg_Field_Name(segment, 2)),
+    TEST_TRUE(runner, ZCB_Equals(bar, (Obj*)Seg_Field_Name(segment, 2)),
               "Field_Name");
-    TEST_TRUE(batch, Seg_Field_Name(segment, 3) == NULL,
+    TEST_TRUE(runner, Seg_Field_Name(segment, 3) == NULL,
               "Field_Name returns NULL for unknown field number");
-    TEST_TRUE(batch, Seg_Field_Num(segment, (CharBuf*)bar) == 2,
+    TEST_TRUE(runner, Seg_Field_Num(segment, (CharBuf*)bar) == 2,
               "Field_Num");
-    TEST_TRUE(batch, Seg_Field_Num(segment, (CharBuf*)baz) == 0,
+    TEST_TRUE(runner, Seg_Field_Num(segment, (CharBuf*)baz) == 0,
               "Field_Num returns 0 for unknown field name");
 
     DECREF(segment);
 }
 
 static void
-test_metadata_storage(TestBatch *batch) {
+test_metadata_storage(TestBatchRunner *runner) {
     Segment *segment = Seg_new(1);
     CharBuf *got;
 
     Seg_Store_Metadata_Str(segment, "foo", 3, (Obj*)CB_newf("bar"));
     got = (CharBuf*)Seg_Fetch_Metadata_Str(segment, "foo", 3);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               got
               && CB_Is_A(got, CHARBUF)
               && CB_Equals_Str(got, "bar", 3),
@@ -81,44 +75,44 @@ test_metadata_storage(TestBatch *batch) {
 }
 
 static void
-test_seg_name_and_num(TestBatch *batch) {
+test_seg_name_and_num(TestBatchRunner *runner) {
     Segment *segment_z = Seg_new(35);
     CharBuf *seg_z_name = Seg_num_to_name(35);
-    TEST_TRUE(batch, Seg_Get_Number(segment_z) == INT64_C(35), "Get_Number");
-    TEST_TRUE(batch, CB_Equals_Str(Seg_Get_Name(segment_z), "seg_z", 5),
+    TEST_TRUE(runner, Seg_Get_Number(segment_z) == INT64_C(35), "Get_Number");
+    TEST_TRUE(runner, CB_Equals_Str(Seg_Get_Name(segment_z), "seg_z", 5),
               "Get_Name");
-    TEST_TRUE(batch, CB_Equals_Str(seg_z_name, "seg_z", 5),
+    TEST_TRUE(runner, CB_Equals_Str(seg_z_name, "seg_z", 5),
               "num_to_name");
     DECREF(seg_z_name);
     DECREF(segment_z);
 }
 
 static void
-test_count(TestBatch *batch) {
+test_count(TestBatchRunner *runner) {
     Segment *segment = Seg_new(100);
 
-    TEST_TRUE(batch, Seg_Get_Count(segment) == 0, "count starts off at 0");
+    TEST_TRUE(runner, Seg_Get_Count(segment) == 0, "count starts off at 0");
     Seg_Set_Count(segment, 120);
-    TEST_TRUE(batch, Seg_Get_Count(segment) == 120, "Set_Count");
-    TEST_TRUE(batch, Seg_Increment_Count(segment, 10) == 130,
+    TEST_TRUE(runner, Seg_Get_Count(segment) == 120, "Set_Count");
+    TEST_TRUE(runner, Seg_Increment_Count(segment, 10) == 130,
               "Increment_Count");
 
     DECREF(segment);
 }
 
 static void
-test_Compare_To(TestBatch *batch) {
+test_Compare_To(TestBatchRunner *runner) {
     Segment *segment_1      = Seg_new(1);
     Segment *segment_2      = Seg_new(2);
     Segment *also_segment_2 = Seg_new(2);
 
-    TEST_TRUE(batch, Seg_Compare_To(segment_1, (Obj*)segment_2) < 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_1, (Obj*)segment_2) < 0,
               "Compare_To 1 < 2");
-    TEST_TRUE(batch, Seg_Compare_To(segment_2, (Obj*)segment_1) > 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_2, (Obj*)segment_1) > 0,
               "Compare_To 1 < 2");
-    TEST_TRUE(batch, Seg_Compare_To(segment_1, (Obj*)segment_1) == 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_1, (Obj*)segment_1) == 0,
               "Compare_To identity");
-    TEST_TRUE(batch, Seg_Compare_To(segment_2, (Obj*)also_segment_2) == 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_2, (Obj*)also_segment_2) == 0,
               "Compare_To 2 == 2");
 
     DECREF(segment_1);
@@ -127,7 +121,7 @@ test_Compare_To(TestBatch *batch) {
 }
 
 static void
-test_Write_File_and_Read_File(TestBatch *batch) {
+test_Write_File_and_Read_File(TestBatchRunner *runner) {
     RAMFolder *folder  = RAMFolder_new(NULL);
     Segment   *segment = Seg_new(100);
     Segment   *got     = Seg_new(100);
@@ -144,13 +138,13 @@ test_Write_File_and_Read_File(TestBatch *batch) {
     Seg_Write_File(segment, (Folder*)folder);
     Seg_Read_File(got, (Folder*)folder);
 
-    TEST_TRUE(batch, Seg_Get_Count(got) == Seg_Get_Count(segment),
+    TEST_TRUE(runner, Seg_Get_Count(got) == Seg_Get_Count(segment),
               "Round-trip count through file");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               Seg_Field_Num(got, jetsam) == Seg_Field_Num(segment, jetsam),
               "Round trip field names through file");
     meta = (CharBuf*)Seg_Fetch_Metadata_Str(got, "foo", 3);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               meta
               && CB_Is_A(meta, CHARBUF)
               && CB_Equals_Str(meta, "bar", 3),
@@ -162,14 +156,14 @@ test_Write_File_and_Read_File(TestBatch *batch) {
 }
 
 void
-TestSeg_run_tests(TestSegment *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_fields(batch);
-    test_metadata_storage(batch);
-    test_seg_name_and_num(batch);
-    test_count(batch);
-    test_Compare_To(batch);
-    test_Write_File_and_Read_File(batch);
+TestSeg_run(TestSegment *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 21);
+    test_fields(runner);
+    test_metadata_storage(runner);
+    test_seg_name_and_num(runner);
+    test_count(runner);
+    test_Compare_To(runner);
+    test_Write_File_and_Read_File(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestSegment.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.cfh b/core/Lucy/Test/Index/TestSegment.cfh
index 9af7b60..609a961 100644
--- a/core/Lucy/Test/Index/TestSegment.cfh
+++ b/core/Lucy/Test/Index/TestSegment.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestSegment cnick TestSeg
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSegment*
-    new(TestFormatter *formatter);
-
-    inert TestSegment*
-    init(TestSegment *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSegment *self);
+    Run(TestSegment *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestSnapshot.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.c b/core/Lucy/Test/Index/TestSnapshot.c
index 2d204aa..56577fa 100644
--- a/core/Lucy/Test/Index/TestSnapshot.c
+++ b/core/Lucy/Test/Index/TestSnapshot.c
@@ -17,25 +17,19 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSnapshot.h"
 #include "Lucy/Index/Snapshot.h"
 #include "Lucy/Store/RAMFolder.h"
 
 TestSnapshot*
-TestSnapshot_new(TestFormatter *formatter) {
-    TestSnapshot *self = (TestSnapshot*)VTable_Make_Obj(TESTSNAPSHOT);
-    return TestSnapshot_init(self, formatter);
-}
-
-TestSnapshot*
-TestSnapshot_init(TestSnapshot *self, TestFormatter *formatter) {
-    return (TestSnapshot*)TestBatch_init((TestBatch*)self, 9, formatter);
+TestSnapshot_new() {
+    return (TestSnapshot*)VTable_Make_Obj(TESTSNAPSHOT);
 }
 
 static void
-test_Add_and_Delete(TestBatch *batch) {
+test_Add_and_Delete(TestBatchRunner *runner) {
     Snapshot *snapshot = Snapshot_new();
     CharBuf *foo = (CharBuf*)ZCB_WRAP_STR("foo", 3);
     CharBuf *bar = (CharBuf*)ZCB_WRAP_STR("bar", 3);
@@ -43,38 +37,38 @@ test_Add_and_Delete(TestBatch *batch) {
     Snapshot_Add_Entry(snapshot, foo);
     Snapshot_Add_Entry(snapshot, foo); // redundant
     VArray *entries = Snapshot_List(snapshot);
-    TEST_INT_EQ(batch, Snapshot_Num_Entries(snapshot), 1,
+    TEST_INT_EQ(runner, Snapshot_Num_Entries(snapshot), 1,
                 "One entry added");
-    TEST_TRUE(batch, CB_Equals(foo, VA_Fetch(entries, 0)), "correct entry");
+    TEST_TRUE(runner, CB_Equals(foo, VA_Fetch(entries, 0)), "correct entry");
     DECREF(entries);
 
     Snapshot_Add_Entry(snapshot, bar);
-    TEST_INT_EQ(batch, Snapshot_Num_Entries(snapshot), 2,
+    TEST_INT_EQ(runner, Snapshot_Num_Entries(snapshot), 2,
                 "second entry added");
     Snapshot_Delete_Entry(snapshot, foo);
-    TEST_INT_EQ(batch, Snapshot_Num_Entries(snapshot), 1, "Delete_Entry");
+    TEST_INT_EQ(runner, Snapshot_Num_Entries(snapshot), 1, "Delete_Entry");
 
     DECREF(snapshot);
 }
 
 static void
-test_path_handling(TestBatch *batch) {
+test_path_handling(TestBatchRunner *runner) {
     Snapshot *snapshot = Snapshot_new();
     Folder   *folder   = (Folder*)RAMFolder_new(NULL);
     CharBuf  *snap     = (CharBuf*)ZCB_WRAP_STR("snap", 4);
     CharBuf  *crackle  = (CharBuf*)ZCB_WRAP_STR("crackle", 7);
 
     Snapshot_Write_File(snapshot, folder, snap);
-    TEST_TRUE(batch, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
+    TEST_TRUE(runner, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
               "Write_File() sets path as a side effect");
 
     Folder_Rename(folder, snap, crackle);
     Snapshot_Read_File(snapshot, folder, crackle);
-    TEST_TRUE(batch, CB_Equals(crackle, (Obj*)Snapshot_Get_Path(snapshot)),
+    TEST_TRUE(runner, CB_Equals(crackle, (Obj*)Snapshot_Get_Path(snapshot)),
               "Read_File() sets path as a side effect");
 
     Snapshot_Set_Path(snapshot, snap);
-    TEST_TRUE(batch, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
+    TEST_TRUE(runner, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
               "Set_Path()");
 
     DECREF(folder);
@@ -82,7 +76,7 @@ test_path_handling(TestBatch *batch) {
 }
 
 static void
-test_Read_File_and_Write_File(TestBatch *batch) {
+test_Read_File_and_Write_File(TestBatchRunner *runner) {
     Snapshot *snapshot = Snapshot_new();
     Folder   *folder   = (Folder*)RAMFolder_new(NULL);
     CharBuf  *snap     = (CharBuf*)ZCB_WRAP_STR("snap", 4);
@@ -93,11 +87,11 @@ test_Read_File_and_Write_File(TestBatch *batch) {
 
     Snapshot *dupe = Snapshot_new();
     Snapshot *read_retval = Snapshot_Read_File(dupe, folder, snap);
-    TEST_TRUE(batch, dupe == read_retval, "Read_File() returns the object");
+    TEST_TRUE(runner, dupe == read_retval, "Read_File() returns the object");
 
     VArray *orig_list = Snapshot_List(snapshot);
     VArray *dupe_list = Snapshot_List(dupe);
-    TEST_TRUE(batch, VA_Equals(orig_list, (Obj*)dupe_list),
+    TEST_TRUE(runner, VA_Equals(orig_list, (Obj*)dupe_list),
               "Round trip through Write_File() and Read_File()");
 
     DECREF(orig_list);
@@ -108,11 +102,11 @@ test_Read_File_and_Write_File(TestBatch *batch) {
 }
 
 void
-TestSnapshot_run_tests(TestSnapshot *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Add_and_Delete(batch);
-    test_path_handling(batch);
-    test_Read_File_and_Write_File(batch);
+TestSnapshot_run(TestSnapshot *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 9);
+    test_Add_and_Delete(runner);
+    test_path_handling(runner);
+    test_Read_File_and_Write_File(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestSnapshot.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.cfh b/core/Lucy/Test/Index/TestSnapshot.cfh
index cb9f316..3016a42 100644
--- a/core/Lucy/Test/Index/TestSnapshot.cfh
+++ b/core/Lucy/Test/Index/TestSnapshot.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestSnapshot
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnapshot*
-    new(TestFormatter *formatter);
-
-    inert TestSnapshot*
-    init(TestSnapshot *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSnapshot *self);
+    Run(TestSnapshot *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestTermInfo.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.c b/core/Lucy/Test/Index/TestTermInfo.c
index 9872671..bf92990 100644
--- a/core/Lucy/Test/Index/TestTermInfo.c
+++ b/core/Lucy/Test/Index/TestTermInfo.c
@@ -18,24 +18,18 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestTermInfo.h"
 #include "Lucy/Index/TermInfo.h"
 
 TestTermInfo*
-TestTermInfo_new(TestFormatter *formatter) {
-    TestTermInfo *self = (TestTermInfo*)VTable_Make_Obj(TESTTERMINFO);
-    return TestTermInfo_init(self, formatter);
-}
-
-TestTermInfo*
-TestTermInfo_init(TestTermInfo *self, TestFormatter *formatter) {
-    return (TestTermInfo*)TestBatch_init((TestBatch*)self, 11, formatter);
+TestTermInfo_new() {
+    return (TestTermInfo*)VTable_Make_Obj(TESTTERMINFO);
 }
 
 void 
-test_freqfilepos(TestBatch *batch) {
+test_freqfilepos(TestBatchRunner *runner) {
     TermInfo* tinfo = TInfo_new(10);
     TInfo_Set_Post_FilePos(tinfo, 20);
     TInfo_Set_Skip_FilePos(tinfo, 40);
@@ -43,32 +37,32 @@ test_freqfilepos(TestBatch *batch) {
 
     TermInfo* cloned_tinfo = TInfo_Clone(tinfo);
 
-    TEST_FALSE(batch, Lucy_TInfo_Equals(tinfo, (Obj*)cloned_tinfo),"the clone should be a separate C struct");
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 10, "new sets doc_freq correctly" );
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 10, "... doc_freq cloned" );
-    TEST_INT_EQ(batch, TInfo_Get_Post_FilePos(tinfo), 20, "... post_filepos cloned" );
-    TEST_INT_EQ(batch, TInfo_Get_Skip_FilePos(tinfo), 40, "... skip_filepos cloned" );
-    TEST_INT_EQ(batch, TInfo_Get_Lex_FilePos(tinfo),  50, "... lex_filepos cloned" );
+    TEST_FALSE(runner, Lucy_TInfo_Equals(tinfo, (Obj*)cloned_tinfo),"the clone should be a separate C struct");
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(tinfo), 10, "new sets doc_freq correctly" );
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(tinfo), 10, "... doc_freq cloned" );
+    TEST_INT_EQ(runner, TInfo_Get_Post_FilePos(tinfo), 20, "... post_filepos cloned" );
+    TEST_INT_EQ(runner, TInfo_Get_Skip_FilePos(tinfo), 40, "... skip_filepos cloned" );
+    TEST_INT_EQ(runner, TInfo_Get_Lex_FilePos(tinfo),  50, "... lex_filepos cloned" );
 
     TInfo_Set_Doc_Freq(tinfo, 5);
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 5,  "set/get doc_freq" );
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(cloned_tinfo), 10, "setting orig doesn't affect clone" );
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(tinfo), 5,  "set/get doc_freq" );
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(cloned_tinfo), 10, "setting orig doesn't affect clone" );
 
     TInfo_Set_Post_FilePos(tinfo, 15);
-    TEST_INT_EQ(batch, TInfo_Get_Post_FilePos(tinfo), 15, "set/get post_filepos" );
+    TEST_INT_EQ(runner, TInfo_Get_Post_FilePos(tinfo), 15, "set/get post_filepos" );
 
     TInfo_Set_Skip_FilePos(tinfo, 35);
-    TEST_INT_EQ(batch, TInfo_Get_Skip_FilePos(tinfo), 35, "set/get skip_filepos" );
+    TEST_INT_EQ(runner, TInfo_Get_Skip_FilePos(tinfo), 35, "set/get skip_filepos" );
 
     TInfo_Set_Lex_FilePos(tinfo, 45);
-    TEST_INT_EQ(batch, TInfo_Get_Lex_FilePos(tinfo), 45, "set/get lex_filepos" );
+    TEST_INT_EQ(runner, TInfo_Get_Lex_FilePos(tinfo), 45, "set/get lex_filepos" );
 
     DECREF(tinfo);
     DECREF(cloned_tinfo);
 }
 
 void
-TestTermInfo_run_tests(TestTermInfo *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_freqfilepos(batch);
+TestTermInfo_run(TestTermInfo *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 11);
+    test_freqfilepos(runner);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Index/TestTermInfo.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.cfh b/core/Lucy/Test/Index/TestTermInfo.cfh
index 69e9ee9..4a7d5a3 100644
--- a/core/Lucy/Test/Index/TestTermInfo.cfh
+++ b/core/Lucy/Test/Index/TestTermInfo.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestTermInfo
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestTermInfo*
-    new(TestFormatter *formatter);
-
-    inert TestTermInfo*
-    init(TestTermInfo *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestTermInfo *self);
+    Run(TestTermInfo *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Object/TestBitVector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.c b/core/Lucy/Test/Object/TestBitVector.c
index 669ae67..6e87020 100644
--- a/core/Lucy/Test/Object/TestBitVector.c
+++ b/core/Lucy/Test/Object/TestBitVector.c
@@ -18,71 +18,65 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Object/TestBitVector.h"
 
 TestBitVector*
-TestBitVector_new(TestFormatter *formatter) {
-    TestBitVector *self = (TestBitVector*)VTable_Make_Obj(TESTBITVECTOR);
-    return TestBitVector_init(self, formatter);
-}
-
-TestBitVector*
-TestBitVector_init(TestBitVector *self, TestFormatter *formatter) {
-    return (TestBitVector*)TestBatch_init((TestBatch*)self, 1029, formatter);
+TestBitVector_new() {
+    return (TestBitVector*)VTable_Make_Obj(TESTBITVECTOR);
 }
 
 static void
-test_Set_and_Get(TestBatch *batch) {
+test_Set_and_Get(TestBatchRunner *runner) {
     unsigned i, max;
     const uint32_t  three     = 3;
     const uint32_t  seventeen = 17;
     BitVector      *bit_vec   = BitVec_new(8);
 
     BitVec_Set(bit_vec, three);
-    TEST_TRUE(batch, BitVec_Get_Capacity(bit_vec) < seventeen,
+    TEST_TRUE(runner, BitVec_Get_Capacity(bit_vec) < seventeen,
               "set below cap");
     BitVec_Set(bit_vec, seventeen);
-    TEST_TRUE(batch, BitVec_Get_Capacity(bit_vec) > seventeen,
+    TEST_TRUE(runner, BitVec_Get_Capacity(bit_vec) > seventeen,
               "set above cap causes BitVector to grow");
 
     for (i = 0, max = BitVec_Get_Capacity(bit_vec); i < max; i++) {
         if (i == three || i == seventeen) {
-            TEST_TRUE(batch, BitVec_Get(bit_vec, i), "set/get %d", i);
+            TEST_TRUE(runner, BitVec_Get(bit_vec, i), "set/get %d", i);
         }
         else {
-            TEST_FALSE(batch, BitVec_Get(bit_vec, i), "get %d", i);
+            TEST_FALSE(runner, BitVec_Get(bit_vec, i), "get %d", i);
         }
     }
-    TEST_FALSE(batch, BitVec_Get(bit_vec, i), "out of range get");
+    TEST_FALSE(runner, BitVec_Get(bit_vec, i), "out of range get");
 
     DECREF(bit_vec);
 }
 
 static void
-test_Flip(TestBatch *batch) {
+test_Flip(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(0);
     int i;
 
     for (i = 0; i <= 20; i++) { BitVec_Flip(bit_vec, i); }
     for (i = 0; i <= 20; i++) {
-        TEST_TRUE(batch, BitVec_Get(bit_vec, i), "flip on %d", i);
+        TEST_TRUE(runner, BitVec_Get(bit_vec, i), "flip on %d", i);
     }
-    TEST_FALSE(batch, BitVec_Get(bit_vec, i), "no flip %d", i);
+    TEST_FALSE(runner, BitVec_Get(bit_vec, i), "no flip %d", i);
     for (i = 0; i <= 20; i++) { BitVec_Flip(bit_vec, i); }
     for (i = 0; i <= 20; i++) {
-        TEST_FALSE(batch, BitVec_Get(bit_vec, i), "flip off %d", i);
+        TEST_FALSE(runner, BitVec_Get(bit_vec, i), "flip off %d", i);
     }
-    TEST_FALSE(batch, BitVec_Get(bit_vec, i), "still no flip %d", i);
+    TEST_FALSE(runner, BitVec_Get(bit_vec, i), "still no flip %d", i);
 
     DECREF(bit_vec);
 }
 
 static void
-test_Flip_Block_ascending(TestBatch *batch) {
+test_Flip_Block_ascending(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(0);
     int i;
 
@@ -92,11 +86,11 @@ test_Flip_Block_ascending(TestBatch *batch) {
 
     for (i = 0; i <= 20; i++) {
         if (i % 2 == 0) {
-            TEST_TRUE(batch, BitVec_Get(bit_vec, i),
+            TEST_TRUE(runner, BitVec_Get(bit_vec, i),
                       "Flip_Block ascending %d", i);
         }
         else {
-            TEST_FALSE(batch, BitVec_Get(bit_vec, i),
+            TEST_FALSE(runner, BitVec_Get(bit_vec, i),
                        "Flip_Block ascending %d", i);
         }
     }
@@ -105,7 +99,7 @@ test_Flip_Block_ascending(TestBatch *batch) {
 }
 
 static void
-test_Flip_Block_descending(TestBatch *batch) {
+test_Flip_Block_descending(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(0);
     int i;
 
@@ -115,11 +109,11 @@ test_Flip_Block_descending(TestBatch *batch) {
 
     for (i = 0; i <= 20; i++) {
         if (i % 2) {
-            TEST_TRUE(batch, BitVec_Get(bit_vec, i),
+            TEST_TRUE(runner, BitVec_Get(bit_vec, i),
                       "Flip_Block descending %d", i);
         }
         else {
-            TEST_FALSE(batch, BitVec_Get(bit_vec, i),
+            TEST_FALSE(runner, BitVec_Get(bit_vec, i),
                        "Flip_Block descending %d", i);
         }
     }
@@ -128,7 +122,7 @@ test_Flip_Block_descending(TestBatch *batch) {
 }
 
 static void
-test_Flip_Block_bulk(TestBatch *batch) {
+test_Flip_Block_bulk(TestBatchRunner *runner) {
     int32_t offset;
 
     for (offset = 0; offset <= 17; offset++) {
@@ -147,7 +141,7 @@ test_Flip_Block_bulk(TestBatch *batch) {
                     if (BitVec_Get(bit_vec, i)) { break; }
                 }
             }
-            TEST_INT_EQ(batch, i, 18, "Flip_Block(%d, %d)", offset, len);
+            TEST_INT_EQ(runner, i, 18, "Flip_Block(%d, %d)", offset, len);
 
             DECREF(bit_vec);
         }
@@ -155,7 +149,7 @@ test_Flip_Block_bulk(TestBatch *batch) {
 }
 
 static void
-test_Mimic(TestBatch *batch) {
+test_Mimic(TestBatchRunner *runner) {
     int foo;
 
     for (foo = 0; foo <= 17; foo++) {
@@ -172,7 +166,7 @@ test_Mimic(TestBatch *batch) {
             for (i = 0; i <= 17; i++) {
                 if (BitVec_Get(foo_vec, i) && i != bar) { break; }
             }
-            TEST_INT_EQ(batch, i, 18, "Mimic(%d, %d)", foo, bar);
+            TEST_INT_EQ(runner, i, 18, "Mimic(%d, %d)", foo, bar);
 
             DECREF(foo_vec);
             DECREF(bar_vec);
@@ -232,17 +226,17 @@ S_verify_logical_op(BitVector *bit_vec, BitVector *set_1, BitVector *set_2,
 }
 
 static void
-test_Or(TestBatch *batch) {
+test_Or(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_Or(smaller, set_2);
-    TEST_INT_EQ(batch, S_verify_logical_op(smaller, set_1, set_2, OP_OR),
+    TEST_INT_EQ(runner, S_verify_logical_op(smaller, set_1, set_2, OP_OR),
                 50, "OR with self smaller than other");
     BitVec_Or(larger, set_1);
-    TEST_INT_EQ(batch, S_verify_logical_op(larger, set_1, set_2, OP_OR),
+    TEST_INT_EQ(runner, S_verify_logical_op(larger, set_1, set_2, OP_OR),
                 50, "OR with other smaller than self");
 
     DECREF(smaller);
@@ -252,17 +246,17 @@ test_Or(TestBatch *batch) {
 }
 
 static void
-test_Xor(TestBatch *batch) {
+test_Xor(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_Xor(smaller, set_2);
-    TEST_INT_EQ(batch, S_verify_logical_op(smaller, set_1, set_2, OP_XOR),
+    TEST_INT_EQ(runner, S_verify_logical_op(smaller, set_1, set_2, OP_XOR),
                 50, "XOR with self smaller than other");
     BitVec_Xor(larger, set_1);
-    TEST_INT_EQ(batch, S_verify_logical_op(larger, set_1, set_2, OP_XOR),
+    TEST_INT_EQ(runner, S_verify_logical_op(larger, set_1, set_2, OP_XOR),
                 50, "XOR with other smaller than self");
 
     DECREF(smaller);
@@ -272,17 +266,17 @@ test_Xor(TestBatch *batch) {
 }
 
 static void
-test_And(TestBatch *batch) {
+test_And(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_And(smaller, set_2);
-    TEST_INT_EQ(batch, S_verify_logical_op(smaller, set_1, set_2, OP_AND),
+    TEST_INT_EQ(runner, S_verify_logical_op(smaller, set_1, set_2, OP_AND),
                 50, "AND with self smaller than other");
     BitVec_And(larger, set_1);
-    TEST_INT_EQ(batch, S_verify_logical_op(larger, set_1, set_2, OP_AND),
+    TEST_INT_EQ(runner, S_verify_logical_op(larger, set_1, set_2, OP_AND),
                 50, "AND with other smaller than self");
 
     DECREF(smaller);
@@ -292,18 +286,18 @@ test_And(TestBatch *batch) {
 }
 
 static void
-test_And_Not(TestBatch *batch) {
+test_And_Not(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_And_Not(smaller, set_2);
-    TEST_INT_EQ(batch,
+    TEST_INT_EQ(runner,
                 S_verify_logical_op(smaller, set_1, set_2, OP_AND_NOT),
                 50, "AND_NOT with self smaller than other");
     BitVec_And_Not(larger, set_1);
-    TEST_INT_EQ(batch,
+    TEST_INT_EQ(runner,
                 S_verify_logical_op(larger, set_2, set_1, OP_AND_NOT),
                 50, "AND_NOT with other smaller than self");
 
@@ -314,7 +308,7 @@ test_And_Not(TestBatch *batch) {
 }
 
 static void
-test_Count(TestBatch *batch) {
+test_Count(TestBatchRunner *runner) {
     int i;
     int shuffled[64];
     BitVector *bit_vec = BitVec_new(64);
@@ -330,29 +324,29 @@ test_Count(TestBatch *batch) {
         BitVec_Set(bit_vec, shuffled[i]);
         if (BitVec_Count(bit_vec) != (uint32_t)(i + 1)) { break; }
     }
-    TEST_INT_EQ(batch, i, 64, "Count() returns the right number of bits");
+    TEST_INT_EQ(runner, i, 64, "Count() returns the right number of bits");
 
     DECREF(bit_vec);
 }
 
 static void
-test_Next_Hit(TestBatch *batch) {
+test_Next_Hit(TestBatchRunner *runner) {
     int i;
 
     for (i = 24; i <= 33; i++) {
         int probe;
         BitVector *bit_vec = BitVec_new(64);
         BitVec_Set(bit_vec, i);
-        TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, 0), i,
+        TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), i,
                     "Next_Hit for 0 is %d", i);
-        TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, 0), i,
+        TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), i,
                     "Next_Hit for 1 is %d", i);
         for (probe = 15; probe <= i; probe++) {
-            TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, probe), i,
+            TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, probe), i,
                         "Next_Hit for %d is %d", probe, i);
         }
         for (probe = i + 1; probe <= i + 9; probe++) {
-            TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, probe), -1,
+            TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, probe), -1,
                         "no Next_Hit for %d when max is %d", probe, i);
         }
         DECREF(bit_vec);
@@ -360,16 +354,16 @@ test_Next_Hit(TestBatch *batch) {
 }
 
 static void
-test_Clear_All(TestBatch *batch) {
+test_Clear_All(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(64);
     BitVec_Flip_Block(bit_vec, 0, 63);
     BitVec_Clear_All(bit_vec);
-    TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, 0), -1, "Clear_All");
+    TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), -1, "Clear_All");
     DECREF(bit_vec);
 }
 
 static void
-test_Clone(TestBatch *batch) {
+test_Clone(TestBatchRunner *runner) {
     int i;
     BitVector *self = BitVec_new(30);
     BitVector *twin;
@@ -383,8 +377,8 @@ test_Clone(TestBatch *batch) {
     for (i = 0; i < 50; i++) {
         if (BitVec_Get(self, i) != BitVec_Get(twin, i)) { break; }
     }
-    TEST_INT_EQ(batch, i, 50, "Clone");
-    TEST_INT_EQ(batch, BitVec_Count(twin), 4, "clone Count");
+    TEST_INT_EQ(runner, i, 50, "Clone");
+    TEST_INT_EQ(runner, BitVec_Count(twin), 4, "clone Count");
 
     DECREF(self);
     DECREF(twin);
@@ -399,7 +393,7 @@ S_compare_u64s(void *context, const void *va, const void *vb) {
 }
 
 static void
-test_To_Array(TestBatch *batch) {
+test_To_Array(TestBatchRunner *runner) {
     uint64_t  *source_ints = TestUtils_random_u64s(NULL, 20, 0, 200);
     BitVector *bit_vec = BitVec_new(0);
     I32Array  *array;
@@ -426,7 +420,7 @@ test_To_Array(TestBatch *batch) {
     for (i = 0; i < num_unique; i++) {
         if (I32Arr_Get(array, i) != (int32_t)source_ints[i]) { break; }
     }
-    TEST_INT_EQ(batch, i, num_unique, "To_Array (%ld == %ld)", i,
+    TEST_INT_EQ(runner, i, num_unique, "To_Array (%ld == %ld)", i,
                 num_unique);
 
     DECREF(array);
@@ -447,23 +441,23 @@ test_off_by_one_error() {
 }
 
 void
-TestBitVector_run_tests(TestBitVector *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Set_and_Get(batch);
-    test_Flip(batch);
-    test_Flip_Block_ascending(batch);
-    test_Flip_Block_descending(batch);
-    test_Flip_Block_bulk(batch);
-    test_Mimic(batch);
-    test_Or(batch);
-    test_Xor(batch);
-    test_And(batch);
-    test_And_Not(batch);
-    test_Count(batch);
-    test_Next_Hit(batch);
-    test_Clear_All(batch);
-    test_Clone(batch);
-    test_To_Array(batch);
+TestBitVector_run(TestBitVector *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1029);
+    test_Set_and_Get(runner);
+    test_Flip(runner);
+    test_Flip_Block_ascending(runner);
+    test_Flip_Block_descending(runner);
+    test_Flip_Block_bulk(runner);
+    test_Mimic(runner);
+    test_Or(runner);
+    test_Xor(runner);
+    test_And(runner);
+    test_And_Not(runner);
+    test_Count(runner);
+    test_Next_Hit(runner);
+    test_Clear_All(runner);
+    test_Clone(runner);
+    test_To_Array(runner);
     test_off_by_one_error();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Object/TestBitVector.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.cfh b/core/Lucy/Test/Object/TestBitVector.cfh
index b7f53bc..e38c66d 100644
--- a/core/Lucy/Test/Object/TestBitVector.cfh
+++ b/core/Lucy/Test/Object/TestBitVector.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Object::TestBitVector
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBitVector*
-    new(TestFormatter *formatter);
-
-    inert TestBitVector*
-    init(TestBitVector *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestBitVector *self);
+    Run(TestBitVector *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Object/TestI32Array.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.c b/core/Lucy/Test/Object/TestI32Array.c
index 2b66430..cc704d2 100644
--- a/core/Lucy/Test/Object/TestI32Array.c
+++ b/core/Lucy/Test/Object/TestI32Array.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Object/TestI32Array.h"
 
@@ -26,18 +26,12 @@ static int32_t source_ints[] = { -1, 0, INT32_MIN, INT32_MAX, 1 };
 static size_t num_ints = sizeof(source_ints) / sizeof(int32_t);
 
 TestI32Array*
-TestI32Arr_new(TestFormatter *formatter) {
-    TestI32Array *self = (TestI32Array*)VTable_Make_Obj(TESTI32ARRAY);
-    return TestI32Arr_init(self, formatter);
-}
-
-TestI32Array*
-TestI32Arr_init(TestI32Array *self, TestFormatter *formatter) {
-    return (TestI32Array*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestI32Arr_new() {
+    return (TestI32Array*)VTable_Make_Obj(TESTI32ARRAY);
 }
 
 static void
-test_all(TestBatch *batch) {
+test_all(TestBatchRunner *runner) {
     I32Array *i32_array = I32Arr_new(source_ints, num_ints);
     int32_t  *ints_copy = (int32_t*)malloc(num_ints * sizeof(int32_t));
     I32Array *stolen    = I32Arr_new_steal(ints_copy, num_ints);
@@ -45,9 +39,9 @@ test_all(TestBatch *batch) {
 
     memcpy(ints_copy, source_ints, num_ints * sizeof(int32_t));
 
-    TEST_TRUE(batch, I32Arr_Get_Size(i32_array) == num_ints,
+    TEST_TRUE(runner, I32Arr_Get_Size(i32_array) == num_ints,
               "Get_Size");
-    TEST_TRUE(batch, I32Arr_Get_Size(stolen) == num_ints,
+    TEST_TRUE(runner, I32Arr_Get_Size(stolen) == num_ints,
               "Get_Size for stolen");
 
     for (num_matched = 0; num_matched < num_ints; num_matched++) {
@@ -55,7 +49,7 @@ test_all(TestBatch *batch) {
             break;
         }
     }
-    TEST_INT_EQ(batch, num_matched, num_ints,
+    TEST_INT_EQ(runner, num_matched, num_ints,
                 "Matched all source ints with Get()");
 
     for (num_matched = 0; num_matched < num_ints; num_matched++) {
@@ -63,7 +57,7 @@ test_all(TestBatch *batch) {
             break;
         }
     }
-    TEST_INT_EQ(batch, num_matched, num_ints,
+    TEST_INT_EQ(runner, num_matched, num_ints,
                 "Matched all source ints in stolen I32Array with Get()");
 
     DECREF(i32_array);
@@ -71,9 +65,9 @@ test_all(TestBatch *batch) {
 }
 
 void
-TestI32Arr_run_tests(TestI32Array *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_all(batch);
+TestI32Arr_run(TestI32Array *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_all(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Object/TestI32Array.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.cfh b/core/Lucy/Test/Object/TestI32Array.cfh
index 8211d07..c6411aa 100644
--- a/core/Lucy/Test/Object/TestI32Array.cfh
+++ b/core/Lucy/Test/Object/TestI32Array.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Object::TestI32Array cnick TestI32Arr
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestI32Array*
-    new(TestFormatter *formatter);
-
-    inert TestI32Array*
-    init(TestI32Array *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestI32Array *self);
+    Run(TestI32Array *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestBlobType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.c b/core/Lucy/Test/Plan/TestBlobType.c
index 03ecf10..f4532b5 100644
--- a/core/Lucy/Test/Plan/TestBlobType.c
+++ b/core/Lucy/Test/Plan/TestBlobType.c
@@ -18,34 +18,28 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestBlobType.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Plan/BlobType.h"
 
 TestBlobType*
-TestBlobType_new(TestFormatter *formatter) {
-    TestBlobType *self = (TestBlobType*)VTable_Make_Obj(TESTBLOBTYPE);
-    return TestBlobType_init(self, formatter);
-}
-
-TestBlobType*
-TestBlobType_init(TestBlobType *self, TestFormatter *formatter) {
-    return (TestBlobType*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestBlobType_new() {
+    return (TestBlobType*)VTable_Make_Obj(TESTBLOBTYPE);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     BlobType *type            = BlobType_new(true);
     Obj      *dump            = (Obj*)BlobType_Dump(type);
     Obj      *clone           = Obj_Load(dump, dump);
     Obj      *another_dump    = (Obj*)BlobType_Dump_For_Schema(type);
     BlobType *another_clone   = BlobType_load(type, another_dump);
 
-    TEST_TRUE(batch, BlobType_Equals(type, (Obj*)clone),
+    TEST_TRUE(runner, BlobType_Equals(type, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch, BlobType_Equals(type, (Obj*)another_clone),
+    TEST_TRUE(runner, BlobType_Equals(type, (Obj*)another_clone),
               "Dump_For_Schema => Load round trip");
 
     DECREF(type);
@@ -56,9 +50,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestBlobType_run_tests(TestBlobType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestBlobType_run(TestBlobType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestBlobType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.cfh b/core/Lucy/Test/Plan/TestBlobType.cfh
index ade91fe..a0ffc79 100644
--- a/core/Lucy/Test/Plan/TestBlobType.cfh
+++ b/core/Lucy/Test/Plan/TestBlobType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestBlobType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBlobType*
-    new(TestFormatter *formatter);
-
-    inert TestBlobType*
-    init(TestBlobType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestBlobType *self);
+    Run(TestBlobType *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestFieldMisc.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.c b/core/Lucy/Test/Plan/TestFieldMisc.c
index a4bbf99..d69e622 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.c
+++ b/core/Lucy/Test/Plan/TestFieldMisc.c
@@ -17,7 +17,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFieldMisc.h"
 
@@ -44,14 +44,8 @@ static CharBuf *unindexed_unanalyzed_cb;
 static CharBuf *united_states_cb;
 
 TestFieldMisc*
-TestFieldMisc_new(TestFormatter *formatter) {
-    TestFieldMisc *self = (TestFieldMisc*)VTable_Make_Obj(TESTFIELDMISC);
-    return TestFieldMisc_init(self, formatter);
-}
-
-TestFieldMisc*
-TestFieldMisc_init(TestFieldMisc *self, TestFormatter *formatter) {
-    return (TestFieldMisc*)TestBatch_init((TestBatch*)self, 20, formatter);
+TestFieldMisc_new() {
+    return (TestFieldMisc*)VTable_Make_Obj(TESTFIELDMISC);
 }
 
 static void
@@ -127,13 +121,13 @@ S_add_doc(Indexer *indexer, CharBuf *field_name) {
 }
 
 static void
-S_check(TestBatch *batch, RAMFolder *folder, CharBuf *field,
+S_check(TestBatchRunner *runner, RAMFolder *folder, CharBuf *field,
         CharBuf *query_text, uint32_t expected_num_hits) {
     TermQuery *query = TermQuery_new(field, (Obj*)query_text);
     IndexSearcher *searcher = IxSearcher_new((Obj*)folder);
     Hits *hits = IxSearcher_Hits(searcher, (Obj*)query, 0, 10, NULL);
 
-    TEST_TRUE(batch, Hits_Total_Hits(hits) == expected_num_hits,
+    TEST_TRUE(runner, Hits_Total_Hits(hits) == expected_num_hits,
               "%s correct num hits", CB_Get_Ptr8(field));
 
     // Don't check the contents of the hit if there aren't any.
@@ -141,7 +135,7 @@ S_check(TestBatch *batch, RAMFolder *folder, CharBuf *field,
         HitDoc *hit = Hits_Next(hits);
         ViewCharBuf *value = (ViewCharBuf*)ZCB_BLANK();
         HitDoc_Extract(hit, field, value);
-        TEST_TRUE(batch, CB_Equals(united_states_cb, (Obj*)value),
+        TEST_TRUE(runner, CB_Equals(united_states_cb, (Obj*)value),
                   "%s correct doc returned", CB_Get_Ptr8(field));
         DECREF(hit);
     }
@@ -152,7 +146,7 @@ S_check(TestBatch *batch, RAMFolder *folder, CharBuf *field,
 }
 
 static void
-test_spec_field(TestBatch *batch) {
+test_spec_field(TestBatchRunner *runner) {
     RAMFolder *folder  = RAMFolder_new(NULL);
     Schema    *schema  = S_create_schema();
     Indexer   *indexer = Indexer_new(schema, (Obj*)folder, NULL, 0);
@@ -165,13 +159,13 @@ test_spec_field(TestBatch *batch) {
 
     Indexer_Commit(indexer);
 
-    S_check(batch, folder, analyzed_cb,               states_cb,        1);
-    S_check(batch, folder, easy_analyzed_cb,          state_cb,         1);
-    S_check(batch, folder, string_cb,                 united_states_cb, 1);
-    S_check(batch, folder, unindexed_but_analyzed_cb, state_cb,         0);
-    S_check(batch, folder, unindexed_but_analyzed_cb, united_states_cb, 0);
-    S_check(batch, folder, unindexed_unanalyzed_cb,   state_cb,         0);
-    S_check(batch, folder, unindexed_unanalyzed_cb,   united_states_cb, 0);
+    S_check(runner, folder, analyzed_cb,               states_cb,        1);
+    S_check(runner, folder, easy_analyzed_cb,          state_cb,         1);
+    S_check(runner, folder, string_cb,                 united_states_cb, 1);
+    S_check(runner, folder, unindexed_but_analyzed_cb, state_cb,         0);
+    S_check(runner, folder, unindexed_but_analyzed_cb, united_states_cb, 0);
+    S_check(runner, folder, unindexed_unanalyzed_cb,   state_cb,         0);
+    S_check(runner, folder, unindexed_unanalyzed_cb,   united_states_cb, 0);
 
     DECREF(indexer);
     DECREF(schema);
@@ -191,7 +185,7 @@ S_add_many_fields_doc(Indexer *indexer, CharBuf *content, int num_fields) {
 }
 
 static void
-test_many_fields(TestBatch *batch) {
+test_many_fields(TestBatchRunner *runner) {
     Schema            *schema    = Schema_new();
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     FullTextType      *type      = FullTextType_new((Analyzer*)tokenizer);
@@ -223,7 +217,7 @@ test_many_fields(TestBatch *batch) {
         // See if our search results match as expected.
         IndexSearcher *searcher = IxSearcher_new((Obj*)folder);
         Hits *hits = IxSearcher_Hits(searcher, (Obj*)query, 0, 100, NULL);
-        TEST_TRUE(batch, Hits_Total_Hits(hits) == 2,
+        TEST_TRUE(runner, Hits_Total_Hits(hits) == 2,
                   "correct number of hits for %d fields", num_fields);
         HitDoc *top_hit = Hits_Next(hits);
 
@@ -242,11 +236,11 @@ test_many_fields(TestBatch *batch) {
 }
 
 void
-TestFieldMisc_run_tests(TestFieldMisc *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestFieldMisc_run(TestFieldMisc *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 20);
     S_init_strings();
-    test_spec_field(batch);
-    test_many_fields(batch);
+    test_spec_field(runner);
+    test_many_fields(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestFieldMisc.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.cfh b/core/Lucy/Test/Plan/TestFieldMisc.cfh
index 7673b5d..f3f686a 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.cfh
+++ b/core/Lucy/Test/Plan/TestFieldMisc.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestFieldMisc
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFieldMisc*
-    new(TestFormatter *formatter);
-
-    inert TestFieldMisc*
-    init(TestFieldMisc *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFieldMisc *self);
+    Run(TestFieldMisc *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestFieldType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.c b/core/Lucy/Test/Plan/TestFieldType.c
index 7979aca..1e6c270 100644
--- a/core/Lucy/Test/Plan/TestFieldType.c
+++ b/core/Lucy/Test/Plan/TestFieldType.c
@@ -19,20 +19,14 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFieldType.h"
 #include "Lucy/Test/TestUtils.h"
 
 TestFieldType*
-TestFType_new(TestFormatter *formatter) {
-    TestFieldType *self = (TestFieldType*)VTable_Make_Obj(TESTFIELDTYPE);
-    return TestFType_init(self, formatter);
-}
-
-TestFieldType*
-TestFType_init(TestFieldType *self, TestFormatter *formatter) {
-    return (TestFieldType*)TestBatch_init((TestBatch*)self, 9, formatter);
+TestFType_new() {
+    return (TestFieldType*)VTable_Make_Obj(TESTFIELDTYPE);
 }
 
 DummyFieldType*
@@ -50,7 +44,7 @@ S_alt_field_type() {
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     FieldType   *type          = (FieldType*)DummyFieldType_new();
     FieldType   *other         = (FieldType*)DummyFieldType_new();
     FieldType   *class_differs = S_alt_field_type();
@@ -66,17 +60,17 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     FType_Set_Indexed(indexed, true);
     FType_Set_Stored(stored, true);
 
-    TEST_TRUE(batch, FType_Equals(type, (Obj*)other),
+    TEST_TRUE(runner, FType_Equals(type, (Obj*)other),
               "Equals() true with identical stats");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)class_differs),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)class_differs),
                "Equals() false with subclass");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)class_differs),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)class_differs),
                "Equals() false with super class");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)boost_differs),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)indexed),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)indexed),
                "Equals() false with indexed => true");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)stored),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)stored),
                "Equals() false with stored => true");
 
     DECREF(stored);
@@ -87,18 +81,18 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_Compare_Values(TestBatch *batch) {
+test_Compare_Values(TestBatchRunner *runner) {
     FieldType     *type = (FieldType*)DummyFieldType_new();
     ZombieCharBuf *a    = ZCB_WRAP_STR("a", 1);
     ZombieCharBuf *b    = ZCB_WRAP_STR("b", 1);
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FType_Compare_Values(type, (Obj*)a, (Obj*)b) < 0,
               "a less than b");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FType_Compare_Values(type, (Obj*)b, (Obj*)a) > 0,
               "b greater than a");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FType_Compare_Values(type, (Obj*)b, (Obj*)b) == 0,
               "b equals b");
 
@@ -106,10 +100,10 @@ test_Compare_Values(TestBatch *batch) {
 }
 
 void
-TestFType_run_tests(TestFieldType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_Compare_Values(batch);
+TestFType_run(TestFieldType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 9);
+    test_Dump_Load_and_Equals(runner);
+    test_Compare_Values(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestFieldType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.cfh b/core/Lucy/Test/Plan/TestFieldType.cfh
index 2632b6f..473e5a0 100644
--- a/core/Lucy/Test/Plan/TestFieldType.cfh
+++ b/core/Lucy/Test/Plan/TestFieldType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestFieldType cnick TestFType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFieldType*
-    new(TestFormatter *formatter);
-
-    inert TestFieldType*
-    init(TestFieldType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFieldType *self);
+    Run(TestFieldType *self, TestBatchRunner *runner);
 }
 
 class Lucy::Test::Plan::DummyFieldType inherits Lucy::Plan::FieldType {

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestFullTextType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.c b/core/Lucy/Test/Plan/TestFullTextType.c
index 8a3a336..c3b5fe5 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.c
+++ b/core/Lucy/Test/Plan/TestFullTextType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFullTextType.h"
 #include "Lucy/Test/TestUtils.h"
@@ -27,18 +27,12 @@
 #include "Lucy/Analysis/StandardTokenizer.h"
 
 TestFullTextType*
-TestFullTextType_new(TestFormatter *formatter) {
-    TestFullTextType *self = (TestFullTextType*)VTable_Make_Obj(TESTFULLTEXTTYPE);
-    return TestFullTextType_init(self, formatter);
-}
-
-TestFullTextType*
-TestFullTextType_init(TestFullTextType *self, TestFormatter *formatter) {
-    return (TestFullTextType*)TestBatch_init((TestBatch*)self, 10, formatter);
+TestFullTextType_new() {
+    return (TestFullTextType*)VTable_Make_Obj(TESTFULLTEXTTYPE);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     StandardTokenizer *tokenizer     = StandardTokenizer_new();
     Normalizer        *normalizer    = Normalizer_new(NULL, true, false);
     FullTextType      *type          = FullTextType_new((Analyzer*)tokenizer);
@@ -60,19 +54,19 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Hash_Store_Str((Hash*)another_dump, "analyzer", 8, INCREF(tokenizer));
     FullTextType *another_clone = FullTextType_load(type, another_dump);
 
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)boost_differs),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)other),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)other),
                "Equals() false with different Analyzer");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)not_indexed),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)not_indexed),
                "Equals() false with indexed => false");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)not_stored),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)not_stored),
                "Equals() false with stored => false");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)highlightable),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)highlightable),
                "Equals() false with highlightable => true");
-    TEST_TRUE(batch, FullTextType_Equals(type, (Obj*)clone),
+    TEST_TRUE(runner, FullTextType_Equals(type, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch, FullTextType_Equals(type, (Obj*)another_clone),
+    TEST_TRUE(runner, FullTextType_Equals(type, (Obj*)another_clone),
               "Dump_For_Schema => Load round trip");
 
     DECREF(another_clone);
@@ -90,19 +84,19 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_Compare_Values(TestBatch *batch) {
+test_Compare_Values(TestBatchRunner *runner) {
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     FullTextType      *type      = FullTextType_new((Analyzer*)tokenizer);
     ZombieCharBuf     *a         = ZCB_WRAP_STR("a", 1);
     ZombieCharBuf     *b         = ZCB_WRAP_STR("b", 1);
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FullTextType_Compare_Values(type, (Obj*)a, (Obj*)b) < 0,
               "a less than b");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FullTextType_Compare_Values(type, (Obj*)b, (Obj*)a) > 0,
               "b greater than a");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FullTextType_Compare_Values(type, (Obj*)b, (Obj*)b) == 0,
               "b equals b");
 
@@ -111,10 +105,10 @@ test_Compare_Values(TestBatch *batch) {
 }
 
 void
-TestFullTextType_run_tests(TestFullTextType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_Compare_Values(batch);
+TestFullTextType_run(TestFullTextType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 10);
+    test_Dump_Load_and_Equals(runner);
+    test_Compare_Values(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestFullTextType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.cfh b/core/Lucy/Test/Plan/TestFullTextType.cfh
index 47b9592..cfdbf7c 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.cfh
+++ b/core/Lucy/Test/Plan/TestFullTextType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestFullTextType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFullTextType*
-    new(TestFormatter *formatter);
-
-    inert TestFullTextType*
-    init(TestFullTextType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFullTextType *self);
+    Run(TestFullTextType *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestNumericType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.c b/core/Lucy/Test/Plan/TestNumericType.c
index 48ef96c..354f796 100644
--- a/core/Lucy/Test/Plan/TestNumericType.c
+++ b/core/Lucy/Test/Plan/TestNumericType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestNumericType.h"
 #include "Lucy/Test/TestUtils.h"
@@ -26,47 +26,41 @@
 #include "Lucy/Plan/NumericType.h"
 
 TestNumericType*
-TestNumericType_new(TestFormatter *formatter) {
-    TestNumericType *self = (TestNumericType*)VTable_Make_Obj(TESTNUMERICTYPE);
-    return TestNumericType_init(self, formatter);
-}
-
-TestNumericType*
-TestNumericType_init(TestNumericType *self, TestFormatter *formatter) {
-    return (TestNumericType*)TestBatch_init((TestBatch*)self, 12, formatter);
+TestNumericType_new() {
+    return (TestNumericType*)VTable_Make_Obj(TESTNUMERICTYPE);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     Int32Type   *i32 = Int32Type_new();
     Int64Type   *i64 = Int64Type_new();
     Float32Type *f32 = Float32Type_new();
     Float64Type *f64 = Float64Type_new();
 
-    TEST_FALSE(batch, Int32Type_Equals(i32, (Obj*)i64),
+    TEST_FALSE(runner, Int32Type_Equals(i32, (Obj*)i64),
                "Int32Type_Equals() false for different type");
-    TEST_FALSE(batch, Int32Type_Equals(i32, NULL),
+    TEST_FALSE(runner, Int32Type_Equals(i32, NULL),
                "Int32Type_Equals() false for NULL");
 
-    TEST_FALSE(batch, Int64Type_Equals(i64, (Obj*)i32),
+    TEST_FALSE(runner, Int64Type_Equals(i64, (Obj*)i32),
                "Int64Type_Equals() false for different type");
-    TEST_FALSE(batch, Int64Type_Equals(i64, NULL),
+    TEST_FALSE(runner, Int64Type_Equals(i64, NULL),
                "Int64Type_Equals() false for NULL");
 
-    TEST_FALSE(batch, Float32Type_Equals(f32, (Obj*)f64),
+    TEST_FALSE(runner, Float32Type_Equals(f32, (Obj*)f64),
                "Float32Type_Equals() false for different type");
-    TEST_FALSE(batch, Float32Type_Equals(f32, NULL),
+    TEST_FALSE(runner, Float32Type_Equals(f32, NULL),
                "Float32Type_Equals() false for NULL");
 
-    TEST_FALSE(batch, Float64Type_Equals(f64, (Obj*)f32),
+    TEST_FALSE(runner, Float64Type_Equals(f64, (Obj*)f32),
                "Float64Type_Equals() false for different type");
-    TEST_FALSE(batch, Float64Type_Equals(f64, NULL),
+    TEST_FALSE(runner, Float64Type_Equals(f64, NULL),
                "Float64Type_Equals() false for NULL");
 
     {
         Obj *dump = (Obj*)Int32Type_Dump(i32);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Int32Type_Equals(i32, other),
+        TEST_TRUE(runner, Int32Type_Equals(i32, other),
                   "Dump => Load round trip for Int32Type");
         DECREF(dump);
         DECREF(other);
@@ -75,7 +69,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     {
         Obj *dump = (Obj*)Int64Type_Dump(i64);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Int64Type_Equals(i64, other),
+        TEST_TRUE(runner, Int64Type_Equals(i64, other),
                   "Dump => Load round trip for Int64Type");
         DECREF(dump);
         DECREF(other);
@@ -84,7 +78,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     {
         Obj *dump = (Obj*)Float32Type_Dump(f32);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Float32Type_Equals(f32, other),
+        TEST_TRUE(runner, Float32Type_Equals(f32, other),
                   "Dump => Load round trip for Float32Type");
         DECREF(dump);
         DECREF(other);
@@ -93,7 +87,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     {
         Obj *dump = (Obj*)Float64Type_Dump(f64);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Float64Type_Equals(f64, other),
+        TEST_TRUE(runner, Float64Type_Equals(f64, other),
                   "Dump => Load round trip for Float64Type");
         DECREF(dump);
         DECREF(other);
@@ -106,9 +100,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestNumericType_run_tests(TestNumericType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestNumericType_run(TestNumericType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 12);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Plan/TestNumericType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.cfh b/core/Lucy/Test/Plan/TestNumericType.cfh
index 21c4b31..e3d952e 100644
--- a/core/Lucy/Test/Plan/TestNumericType.cfh
+++ b/core/Lucy/Test/Plan/TestNumericType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestNumericType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNumericType*
-    new(TestFormatter *formatter);
-
-    inert TestNumericType*
-    init(TestNumericType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNumericType *self);
+    Run(TestNumericType *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestLeafQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.c b/core/Lucy/Test/Search/TestLeafQuery.c
index ba7db58..0fe2b61 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.c
+++ b/core/Lucy/Test/Search/TestLeafQuery.c
@@ -19,25 +19,19 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestLeafQuery.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Search/LeafQuery.h"
 
 TestLeafQuery*
-TestLeafQuery_new(TestFormatter *formatter) {
-    TestLeafQuery *self = (TestLeafQuery*)VTable_Make_Obj(TESTLEAFQUERY);
-    return TestLeafQuery_init(self, formatter);
-}
-
-TestLeafQuery*
-TestLeafQuery_init(TestLeafQuery *self, TestFormatter *formatter) {
-    return (TestLeafQuery*)TestBatch_init((TestBatch*)self, 5, formatter);
+TestLeafQuery_new() {
+    return (TestLeafQuery*)VTable_Make_Obj(TESTLEAFQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     LeafQuery *query         = TestUtils_make_leaf_query("content", "foo");
     LeafQuery *field_differs = TestUtils_make_leaf_query("stuff", "foo");
     LeafQuery *null_field    = TestUtils_make_leaf_query(NULL, "foo");
@@ -46,16 +40,16 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Obj       *dump          = (Obj*)LeafQuery_Dump(query);
     LeafQuery *clone         = (LeafQuery*)LeafQuery_Load(term_differs, dump);
 
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)field_differs),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)field_differs),
                "Equals() false with different field");
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)null_field),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)null_field),
                "Equals() false with null field");
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)term_differs),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)term_differs),
                "Equals() false with different term");
     LeafQuery_Set_Boost(boost_differs, 0.5);
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_TRUE(batch, LeafQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, LeafQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(query);
@@ -68,9 +62,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestLeafQuery_run_tests(TestLeafQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestLeafQuery_run(TestLeafQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 5);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestLeafQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.cfh b/core/Lucy/Test/Search/TestLeafQuery.cfh
index 19a9da3..3750b6e 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.cfh
+++ b/core/Lucy/Test/Search/TestLeafQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestLeafQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestLeafQuery*
-    new(TestFormatter *formatter);
-
-    inert TestLeafQuery*
-    init(TestLeafQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestLeafQuery *self);
+    Run(TestLeafQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestMatchAllQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.c b/core/Lucy/Test/Search/TestMatchAllQuery.c
index b70c8f2..4977d6e 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.c
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.c
@@ -19,32 +19,26 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestMatchAllQuery.h"
 #include "Lucy/Search/MatchAllQuery.h"
 
 TestMatchAllQuery*
-TestMatchAllQuery_new(TestFormatter *formatter) {
-    TestMatchAllQuery *self = (TestMatchAllQuery*)VTable_Make_Obj(TESTMATCHALLQUERY);
-    return TestMatchAllQuery_init(self, formatter);
-}
-
-TestMatchAllQuery*
-TestMatchAllQuery_init(TestMatchAllQuery *self, TestFormatter *formatter) {
-    return (TestMatchAllQuery*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestMatchAllQuery_new() {
+    return (TestMatchAllQuery*)VTable_Make_Obj(TESTMATCHALLQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     MatchAllQuery *query = MatchAllQuery_new();
     Obj           *dump  = (Obj*)MatchAllQuery_Dump(query);
     MatchAllQuery *clone = (MatchAllQuery*)MatchAllQuery_Load(query, dump);
 
-    TEST_TRUE(batch, MatchAllQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, MatchAllQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_FALSE(batch, MatchAllQuery_Equals(query, (Obj*)CFISH_TRUE),
+    TEST_FALSE(runner, MatchAllQuery_Equals(query, (Obj*)CFISH_TRUE),
                "Equals");
 
     DECREF(query);
@@ -54,9 +48,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 
 
 void
-TestMatchAllQuery_run_tests(TestMatchAllQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestMatchAllQuery_run(TestMatchAllQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestMatchAllQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.cfh b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
index 1d2a3f5..c4232ff 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.cfh
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestMatchAllQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMatchAllQuery*
-    new(TestFormatter *formatter);
-
-    inert TestMatchAllQuery*
-    init(TestMatchAllQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestMatchAllQuery *self);
+    Run(TestMatchAllQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestNOTQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.c b/core/Lucy/Test/Search/TestNOTQuery.c
index c6b7246..ddac353 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.c
+++ b/core/Lucy/Test/Search/TestNOTQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestNOTQuery.h"
@@ -27,18 +27,12 @@
 #include "Lucy/Search/LeafQuery.h"
 
 TestNOTQuery*
-TestNOTQuery_new(TestFormatter *formatter) {
-    TestNOTQuery *self = (TestNOTQuery*)VTable_Make_Obj(TESTNOTQUERY);
-    return TestNOTQuery_init(self, formatter);
-}
-
-TestNOTQuery*
-TestNOTQuery_init(TestNOTQuery *self, TestFormatter *formatter) {
-    return (TestNOTQuery*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestNOTQuery_new() {
+    return (TestNOTQuery*)VTable_Make_Obj(TESTNOTQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     Query    *a_leaf        = (Query*)TestUtils_make_leaf_query(NULL, "a");
     Query    *b_leaf        = (Query*)TestUtils_make_leaf_query(NULL, "b");
     NOTQuery *query         = NOTQuery_new(a_leaf);
@@ -47,14 +41,14 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Obj      *dump          = (Obj*)NOTQuery_Dump(query);
     NOTQuery *clone         = (NOTQuery*)Obj_Load(dump, dump);
 
-    TEST_FALSE(batch, NOTQuery_Equals(query, (Obj*)kids_differ),
+    TEST_FALSE(runner, NOTQuery_Equals(query, (Obj*)kids_differ),
                "Different kids spoil Equals");
-    TEST_TRUE(batch, NOTQuery_Equals(query, (Obj*)boost_differs),
+    TEST_TRUE(runner, NOTQuery_Equals(query, (Obj*)boost_differs),
               "Equals with identical boosts");
     NOTQuery_Set_Boost(boost_differs, 1.5);
-    TEST_FALSE(batch, NOTQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, NOTQuery_Equals(query, (Obj*)boost_differs),
                "Different boost spoils Equals");
-    TEST_TRUE(batch, NOTQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, NOTQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(a_leaf);
@@ -67,9 +61,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestNOTQuery_run_tests(TestNOTQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestNOTQuery_run(TestNOTQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestNOTQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.cfh b/core/Lucy/Test/Search/TestNOTQuery.cfh
index a2549d3..bc432ff 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.cfh
+++ b/core/Lucy/Test/Search/TestNOTQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestNOTQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNOTQuery*
-    new(TestFormatter *formatter);
-
-    inert TestNOTQuery*
-    init(TestNOTQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNOTQuery *self);
+    Run(TestNOTQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestNoMatchQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.c b/core/Lucy/Test/Search/TestNoMatchQuery.c
index 76a738e..d85c417 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.c
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.c
@@ -19,32 +19,26 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestNoMatchQuery.h"
 #include "Lucy/Search/NoMatchQuery.h"
 
 TestNoMatchQuery*
-TestNoMatchQuery_new(TestFormatter *formatter) {
-    TestNoMatchQuery *self = (TestNoMatchQuery*)VTable_Make_Obj(TESTNOMATCHQUERY);
-    return TestNoMatchQuery_init(self, formatter);
-}
-
-TestNoMatchQuery*
-TestNoMatchQuery_init(TestNoMatchQuery *self, TestFormatter *formatter) {
-    return (TestNoMatchQuery*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestNoMatchQuery_new() {
+    return (TestNoMatchQuery*)VTable_Make_Obj(TESTNOMATCHQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     NoMatchQuery *query = NoMatchQuery_new();
     Obj          *dump  = (Obj*)NoMatchQuery_Dump(query);
     NoMatchQuery *clone = (NoMatchQuery*)NoMatchQuery_Load(query, dump);
 
-    TEST_TRUE(batch, NoMatchQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, NoMatchQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_FALSE(batch, NoMatchQuery_Equals(query, (Obj*)CFISH_TRUE),
+    TEST_FALSE(runner, NoMatchQuery_Equals(query, (Obj*)CFISH_TRUE),
                "Equals");
 
     DECREF(query);
@@ -54,9 +48,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 
 
 void
-TestNoMatchQuery_run_tests(TestNoMatchQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestNoMatchQuery_run(TestNoMatchQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestNoMatchQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.cfh b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
index 9b2344d..cb3420e 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.cfh
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestNoMatchQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNoMatchQuery*
-    new(TestFormatter *formatter);
-
-    inert TestNoMatchQuery*
-    init(TestNoMatchQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNoMatchQuery *self);
+    Run(TestNoMatchQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/40220b9e/core/Lucy/Test/Search/TestPhraseQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.c b/core/Lucy/Test/Search/TestPhraseQuery.c
index d350f95..3fe0182 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.c
+++ b/core/Lucy/Test/Search/TestPhraseQuery.c
@@ -19,30 +19,24 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestPhraseQuery.h"
 #include "Lucy/Search/PhraseQuery.h"
 
 TestPhraseQuery*
-TestPhraseQuery_new(TestFormatter *formatter) {
-    TestPhraseQuery *self = (TestPhraseQuery*)VTable_Make_Obj(TESTPHRASEQUERY);
-    return TestPhraseQuery_init(self, formatter);
-}
-
-TestPhraseQuery*
-TestPhraseQuery_init(TestPhraseQuery *self, TestFormatter *formatter) {
-    return (TestPhraseQuery*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestPhraseQuery_new() {
+    return (TestPhraseQuery*)VTable_Make_Obj(TESTPHRASEQUERY);
 }
 
 static void
-test_Dump_And_Load(TestBatch *batch) {
+test_Dump_And_Load(TestBatchRunner *runner) {
     PhraseQuery *query
         = TestUtils_make_phrase_query("content", "a", "b", "c", NULL);
     Obj         *dump  = (Obj*)PhraseQuery_Dump(query);
     PhraseQuery *twin = (PhraseQuery*)Obj_Load(dump, dump);
-    TEST_TRUE(batch, PhraseQuery_Equals(query, (Obj*)twin),
+    TEST_TRUE(runner, PhraseQuery_Equals(query, (Obj*)twin),
               "Dump => Load round trip");
     DECREF(query);
     DECREF(dump);
@@ -50,9 +44,9 @@ test_Dump_And_Load(TestBatch *batch) {
 }
 
 void
-TestPhraseQuery_run_tests(TestPhraseQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_And_Load(batch);
+TestPhraseQuery_run(TestPhraseQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    test_Dump_And_Load(runner);
 }