freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [freemarker] branch 3 updated: Streamlined a bit how Configuration-s are created in tests
Date Sat, 19 Jan 2019 22:28:50 GMT
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git


The following commit(s) were added to refs/heads/3 by this push:
     new b94c620  Streamlined a bit how Configuration-s are created in tests
b94c620 is described below

commit b94c620f78769e063a2a0f6d3021462962c101d9
Author: ddekany <ddekany@apache.org>
AuthorDate: Sat Jan 19 01:26:08 2019 +0100

    Streamlined a bit how Configuration-s are created in tests
---
 .../apache/freemarker/core/AttemptLoggingTest.java | 15 ++--
 .../freemarker/core/CallerTemplateNameTest.java    |  4 +-
 .../freemarker/core/CoercionToTextualTest.java     | 14 +---
 .../org/apache/freemarker/core/DateFormatTest.java | 58 ++++++--------
 .../core/EnvironmentGetTemplateVariantsTest.java   | 13 ++--
 .../freemarker/core/GetOptionalTemplateTest.java   | 13 ++--
 .../apache/freemarker/core/HeaderParsingTest.java  |  5 +-
 .../IncludeAndImportConfigurableLayersTest.java    | 38 ++++-----
 .../freemarker/core/IncludeAndImportTest.java      | 59 ++++----------
 .../freemarker/core/InterpolationSyntaxTest.java   | 32 ++------
 .../core/InterpretAndEvalTemplateNameTest.java     |  2 +-
 .../core/InterpretSettingInheritanceTest.java      | 20 ++---
 .../org/apache/freemarker/core/MinMaxBITest.java   |  4 +-
 .../freemarker/core/MiscErrorMessagesTest.java     |  2 +-
 .../core/NewBiObjectWrapperRestrictionTest.java    |  4 +-
 .../apache/freemarker/core/OutputFormatTest.java   | 91 ++++++++++------------
 .../freemarker/core/ParsingErrorMessagesTest.java  |  3 +-
 .../apache/freemarker/core/SQLTimeZoneTest.java    | 29 +++----
 .../freemarker/core/SpecialVariableTest.java       | 39 ++++------
 .../core/StringLiteralInterpolationTest.java       |  5 +-
 .../org/apache/freemarker/core/TabSizeTest.java    | 14 +---
 .../core/TemplateNameSpecialVariablesTest.java     |  4 +-
 .../freemarker/core/TruncateBuiltInTest.java       | 17 ++--
 .../freemarker/core/WhitespaceStrippingTest.java   |  5 +-
 .../core/valueformat/NumberFormatTest.java         |  2 +-
 .../impl/ExtendedDecimalFormatTest.java            |  8 +-
 .../dom/DefaultObjectWrapperExtensionTest.java     |  6 +-
 .../examples/AbsoluteTemplateNameBIExample.java    |  7 --
 .../manual/examples/AutoEscapingExample.java       |  5 --
 .../examples/ConfigureOutputFormatExamples.java    | 17 ++--
 .../manual/examples/CustomFormatsExample.java      | 16 ++--
 .../examples/TemplateConfigurationExamples.java    | 13 ++--
 .../org/apache/freemarker/test/TemplateTest.java   | 64 +++++++++++++--
 33 files changed, 268 insertions(+), 360 deletions(-)

diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/AttemptLoggingTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/AttemptLoggingTest.java
index 2b89776..9743eff 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/AttemptLoggingTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/AttemptLoggingTest.java
@@ -29,7 +29,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class AttemptLoggingTest extends TemplateTest {
@@ -40,9 +39,7 @@ public class AttemptLoggingTest extends TemplateTest {
         // Here, we should have an ERROR entry in the log that refers to an exception in an #attempt block. But we can't
         // easily assert that automatically, so it has to be checked manually...
 
-        setConfiguration(new TestConfigurationBuilder()
-                .attemptExceptionReporter(AttemptExceptionReporter.LOG_WARN)
-                .build());
+        setConfiguration(newConfigurationBuilder().attemptExceptionReporter(AttemptExceptionReporter.LOG_WARN));
         assertOutput("<#attempt>${missingVar2}<#recover>r</#attempt>", "r");
         // Again, it must be checked manually if there's a WARN entry
     }
@@ -50,9 +47,8 @@ public class AttemptLoggingTest extends TemplateTest {
     @Test
     public void customConfigTest() throws IOException, TemplateException {
         List<String> reports = new ArrayList<String>();
-        setConfiguration(new TestConfigurationBuilder()
-                .attemptExceptionReporter(new TestAttemptExceptionReporter(reports))
-                .build());
+        setConfiguration(newConfigurationBuilder()
+                .attemptExceptionReporter(new TestAttemptExceptionReporter(reports)));
 
         assertOutput(
                 "<#attempt>${missingVar1}<#recover>r</#attempt>"
@@ -66,7 +62,7 @@ public class AttemptLoggingTest extends TemplateTest {
     @Test
     public void dontReportSuppressedExceptionsTest() throws IOException, TemplateException {
         List<String> reports = new ArrayList<String>();
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .attemptExceptionReporter(new TestAttemptExceptionReporter(reports))
                 .templateExceptionHandler(new TemplateExceptionHandler() {
                     public void handleTemplateException(TemplateException te, Environment env, Writer out)
@@ -77,8 +73,7 @@ public class AttemptLoggingTest extends TemplateTest {
                             throw new TemplateException("Failed to write to the output", e, env);
                         }
                     }
-                })
-                .build());
+                }));
 
         assertOutput("<#attempt>${missingVar1}t<#recover>r</#attempt>", "[E]t");
 
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CallerTemplateNameTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CallerTemplateNameTest.java
index 39ac167..42e29c9 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CallerTemplateNameTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CallerTemplateNameTest.java
@@ -26,8 +26,8 @@ import org.junit.Test;
 public class CallerTemplateNameTest  extends TemplateTest {
 
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder().localizedTemplateLookup(true).build();
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb.localizedTemplateLookup(true);
     }
 
     @Test
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CoercionToTextualTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CoercionToTextualTest.java
index ce6a319..e94c2f3 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CoercionToTextualTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CoercionToTextualTest.java
@@ -30,7 +30,6 @@ import org.apache.freemarker.core.userpkg.PrintfGTemplateNumberFormatFactory;
 import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -54,11 +53,10 @@ public class CoercionToTextualTest extends TemplateTest {
 
     @Test
     public void testEscBuiltin() throws IOException, TemplateException {
-        setConfiguration(createDefaultConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .outputFormat(HTMLOutputFormat.INSTANCE)
                 .autoEscapingPolicy(AutoEscapingPolicy.DISABLE)
-                .booleanFormat("<y>,<n>")
-                .build());
+                .booleanFormat("<y>,<n>"));
         assertOutput("${'a<b'?esc}", "a&lt;b");
         assertOutput("${n?string?esc}", "1.50E+03");
         assertOutput("${n?esc}", "1.50*10<sup>3</sup>");
@@ -121,12 +119,8 @@ public class CoercionToTextualTest extends TemplateTest {
     }
 
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return createDefaultConfigurationBuilder().build();
-    }
-
-    private TestConfigurationBuilder createDefaultConfigurationBuilder() {
-        return new TestConfigurationBuilder()
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb
                 .customNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
                         "G", PrintfGTemplateNumberFormatFactory.INSTANCE))
                 .customDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
index 50e15bb..78954cd 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/DateFormatTest.java
@@ -43,7 +43,6 @@ import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.UndefinedCustomFormatException;
 import org.apache.freemarker.core.valueformat.impl.AliasTemplateDateFormatFactory;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 import com.google.common.collect.ImmutableMap;
@@ -53,9 +52,10 @@ public class DateFormatTest extends TemplateTest {
     /** 2015-09-06T12:00:00Z */
     private static long T = 1441540800000L;
     private static TemplateDateModel TM = new SimpleDate(new Date(T), TemplateDateModel.DATE_TIME);
-    
-    private TestConfigurationBuilder createConfigurationBuilder() {
-        return new TestConfigurationBuilder()
+
+    @Override
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb
                 .locale(Locale.US)
                 .timeZone(TimeZone.getTimeZone("GMT+01:00"))
                 .sqlDateAndTimeTimeZone(TimeZone.getTimeZone("UTC"))
@@ -67,11 +67,6 @@ public class DateFormatTest extends TemplateTest {
                         "htmlIso", HTMLISOTemplateDateFormatFactory.INSTANCE));
     }
 
-    @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return createConfigurationBuilder().build();
-    }
-
     @Test
     public void testCustomFormat() throws Exception {
         addToDataModel("d", new Date(123456789));
@@ -156,11 +151,10 @@ public class DateFormatTest extends TemplateTest {
         assertErrorContains("${.now?string('x2')}", "\"x2\"", "'x'");
         assertErrorContains("${.now?string('[wrong]')}", "format string", "[wrong]");
 
-        setConfiguration(createConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .dateFormat("[wrong d]")
                 .dateTimeFormat("[wrong dt]")
-                .timeFormat("[wrong t]")
-                .build());
+                .timeFormat("[wrong t]"));
         assertErrorContains("${.now?date}", "\"dateFormat\"", "[wrong d]");
         assertErrorContains("${.now?dateTime}", "\"dateTimeFormat\"", "[wrong dt]");
         assertErrorContains("${.now?time}", "\"timeFormat\"", "[wrong t]");
@@ -191,13 +185,13 @@ public class DateFormatTest extends TemplateTest {
             
         }
         {
-            setConfiguration(createConfigurationBuilder().dateFormat("@noSuchFormatD").build());
+            setConfiguration(newConfigurationBuilder().dateFormat("@noSuchFormatD"));
             assertErrorContains(
                     "${.now?date}",
                     "\"@noSuchFormatD\"", "\"noSuchFormatD\"", "\"dateFormat\"");
         }
         {
-            setConfiguration(createConfigurationBuilder().timeFormat("@noSuchFormatT").build());
+            setConfiguration(newConfigurationBuilder().timeFormat("@noSuchFormatT"));
             assertErrorContains(
                     "${.now?time}",
                     "\"@noSuchFormatT\"", "\"noSuchFormatT\"", "\"timeFormat\"");
@@ -212,7 +206,7 @@ public class DateFormatTest extends TemplateTest {
     }
 
     private void setConfigurationWithDateTimeFormat(String formatString) {
-        setConfiguration(createConfigurationBuilder().dateTimeFormat(formatString).build());
+        setConfiguration(newConfigurationBuilder().dateTimeFormat(formatString));
     }
 
     @Test
@@ -233,10 +227,9 @@ public class DateFormatTest extends TemplateTest {
         setConfigurationWithDateTimeFormat("@@yyyy");
         assertOutput("${d}", "@@1970");
 
-        setConfiguration(createConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .customDateFormats(Collections.<String, TemplateDateFormatFactory>emptyMap())
-                .dateTimeFormat("@epoch")
-                .build());
+                .dateTimeFormat("@epoch"));
         assertErrorContains("${d}", "custom", "\"epoch\"");
     }
 
@@ -246,11 +239,10 @@ public class DateFormatTest extends TemplateTest {
         String timeFormatStr = "HH:mm";
         String dateTimeFormatStr = "yyyy.MM.dd. HH:mm";
 
-        setConfiguration(createConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .dateFormat(dateFormatStr)
                 .timeFormat(timeFormatStr)
-                .dateTimeFormat(dateTimeFormatStr)
-                .build());
+                .dateTimeFormat(dateTimeFormatStr));
 
         Configuration cfg = getConfiguration();
 
@@ -336,7 +328,7 @@ public class DateFormatTest extends TemplateTest {
 
     @Test
     public void testAliases() throws Exception {
-        setConfiguration(createConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .customDateFormats(ImmutableMap.of(
                         "d", new AliasTemplateDateFormatFactory("yyyy-MMM-dd"),
                         "m", new AliasTemplateDateFormatFactory("yyyy-MMM"),
@@ -348,8 +340,7 @@ public class DateFormatTest extends TemplateTest {
                                         .customDateFormats(ImmutableMap.<String, TemplateDateFormatFactory>of(
                                                 "m", new AliasTemplateDateFormatFactory("yyyy-MMMM"),
                                                 "i", new AliasTemplateDateFormatFactory("@epoch")))
-                                        .build()))
-                .build());
+                                        .build())));
 
         addToDataModel("d", TM);
         String commonFtl = "${d?string.@d} ${d?string.@m} "
@@ -366,15 +357,14 @@ public class DateFormatTest extends TemplateTest {
     @Test
     public void testAliases2() throws Exception {
         setConfiguration(
-                createConfigurationBuilder()
+                newConfigurationBuilder()
                 .customDateFormats(ImmutableMap.<String, TemplateDateFormatFactory>of(
                         "d", new AliasTemplateDateFormatFactory("yyyy-MMM",
                                 ImmutableMap.of(
                                         new Locale("en"), "yyyy-MMM'_en'",
                                         Locale.UK, "yyyy-MMM'_en_GB'",
                                         Locale.FRANCE, "yyyy-MMM'_fr_FR'"))))
-                .dateTimeFormat("@d")
-                .build());
+                .dateTimeFormat("@d"));
         addToDataModel("d", TM);
         assertOutput(
                 "<#setting locale='en_US'>${d} "
@@ -391,11 +381,10 @@ public class DateFormatTest extends TemplateTest {
     @Test
     public void testZeroArgDateBI() throws IOException, TemplateException {
         setConfiguration(
-                createConfigurationBuilder()
+                newConfigurationBuilder()
                 .dateFormat("@epoch")
                 .dateTimeFormat("@epoch")
-                .timeFormat("@epoch")
-                .build());
+                .timeFormat("@epoch"));
 
         addToDataModel("t", String.valueOf(T));
         
@@ -413,11 +402,10 @@ public class DateFormatTest extends TemplateTest {
     @Test
     public void testAppMetaRoundtrip() throws IOException, TemplateException {
         setConfiguration(
-                createConfigurationBuilder()
-                .dateFormat("@appMeta")
-                .dateTimeFormat("@appMeta")
-                .timeFormat("@appMeta")
-                .build());
+                newConfigurationBuilder()
+                        .dateFormat("@appMeta")
+                        .dateTimeFormat("@appMeta")
+                        .timeFormat("@appMeta"));
 
         addToDataModel("t", String.valueOf(T) + "/foo");
         
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java
index 06e63ac..f6d8f21 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java
@@ -122,7 +122,6 @@ public class EnvironmentGetTemplateVariantsTest extends TemplateTest {
     
     @Test
     public void test() throws IOException, TemplateException {
-        setConfiguration(createConfiguration(Configuration.VERSION_3_0_0));
         assertOutputForNamed(
                 "main",
                 "<ct=main mt=main>\n"
@@ -180,17 +179,17 @@ public class EnvironmentGetTemplateVariantsTest extends TemplateTest {
 
     @Test
     public void testNotStarted() throws IOException, TemplateException {
-        Template t = new Template("foo", "", createConfiguration(Configuration.VERSION_3_0_0));
+        Template t = new Template("foo", "", getConfiguration());
         final Environment env = t.createProcessingEnvironment(null, null);
         assertSame(t, env.getMainTemplate());
         assertSame(t, env.getCurrentTemplate());
     }
-    
-    private Configuration createConfiguration(Version iciVersion) {
-        return new TestConfigurationBuilder(iciVersion)
+
+    @Override
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb
                 .templateLoader(TEMPLATES)
-                .whitespaceStripping(false)
-                .build();
+                .whitespaceStripping(false);
     }
 
     @Override
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
index f6c973e..e9e1003 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
@@ -10,14 +10,13 @@ import org.junit.Test;
 public class GetOptionalTemplateTest extends TemplateTest {
 
     private ByteArrayTemplateLoader byteArrayTemplateLoader = new ByteArrayTemplateLoader();
-    
+
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new Configuration.Builder(Configuration.VERSION_3_0_0)
-                .templateLoader(
-                        new MultiTemplateLoader(new TemplateLoader[] {
-                                new StringTemplateLoader(), byteArrayTemplateLoader
-                        })).build();
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb.templateLoader(
+                new MultiTemplateLoader(new TemplateLoader[] {
+                        new StringTemplateLoader(), byteArrayTemplateLoader
+                }));
     }
 
     @Test
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/HeaderParsingTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/HeaderParsingTest.java
index 6f8851d..1262834 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/HeaderParsingTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/HeaderParsingTest.java
@@ -22,13 +22,12 @@ package org.apache.freemarker.core;
 import java.io.IOException;
 
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class HeaderParsingTest extends TemplateTest {
 
-    private final Configuration cfgStripWS = new TestConfigurationBuilder().build();
-    private final Configuration cfgNoStripWS = new TestConfigurationBuilder().whitespaceStripping(false).build();
+    private final Configuration cfgStripWS = newConfigurationBuilder().build();
+    private final Configuration cfgNoStripWS = newConfigurationBuilder().whitespaceStripping(false).build();
 
     @Test
     public void test() throws IOException, TemplateException {
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportConfigurableLayersTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportConfigurableLayersTest.java
index 90ec941..1d9d259 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportConfigurableLayersTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportConfigurableLayersTest.java
@@ -32,9 +32,21 @@ import com.google.common.collect.ImmutableMap;
 
 public class IncludeAndImportConfigurableLayersTest {
 
+    private static final StringTemplateLoader TEMPLATE_LOADER = new StringTemplateLoader();
+    static {
+        TEMPLATE_LOADER.putTemplate("main.f3ah", "In main: ${loaded}");
+        TEMPLATE_LOADER.putTemplate("main2.f3ah", "In main2: ${loaded}");
+        TEMPLATE_LOADER.putTemplate("t1.f3ah", "<#global loaded = (loaded!) + 't1;'>T1;");
+        TEMPLATE_LOADER.putTemplate("t2.f3ah", "<#global loaded = (loaded!) + 't2;'>T2;");
+        TEMPLATE_LOADER.putTemplate("t3.f3ah", "<#global loaded = (loaded!) + 't3;'>T3;");
+        TEMPLATE_LOADER.putTemplate("t1b.f3ah", "<#global loaded = (loaded!) + 't1b;'>T1b;");
+        TEMPLATE_LOADER.putTemplate("t2b.f3ah", "<#global loaded = (loaded!) + 't2b;'>T2b;");
+        TEMPLATE_LOADER.putTemplate("t3b.f3ah", "<#global loaded = (loaded!) + 't3b;'>T3b;");
+    }
+
     @Test
     public void test3LayerImportNoClashes() throws Exception {
-        TestConfigurationBuilder cfgB = createConfigurationBuilder()
+        TestConfigurationBuilder cfgB = newConfigurationBuilder()
                 .autoImports(ImmutableMap.of("t1", "t1.f3ah"))
                 .templateConfigurations(
                         new ConditionalTemplateConfigurationFactory(
@@ -73,7 +85,7 @@ public class IncludeAndImportConfigurableLayersTest {
     
     @Test
     public void test3LayerImportClashes() throws Exception {
-        Configuration cfg = createConfigurationBuilder()
+        Configuration cfg = newConfigurationBuilder()
                 .autoImports(ImmutableMap.of(
                         "t1", "t1.f3ah",
                         "t2", "t2.f3ah",
@@ -115,7 +127,7 @@ public class IncludeAndImportConfigurableLayersTest {
 
     @Test
     public void test3LayerIncludesNoClashes() throws Exception {
-        Configuration cfg = createConfigurationBuilder()
+        Configuration cfg = newConfigurationBuilder()
                 .autoIncludes("t1.f3ah")
                 .templateConfigurations(
                         new ConditionalTemplateConfigurationFactory(
@@ -154,7 +166,7 @@ public class IncludeAndImportConfigurableLayersTest {
 
     @Test
     public void test3LayerIncludeClashes() throws Exception {
-        Configuration cfg = createConfigurationBuilder()
+        Configuration cfg = newConfigurationBuilder()
                 .autoIncludes("t1.f3ah", "t2.f3ah", "t3.f3ah")
                 .templateConfigurations(new ConditionalTemplateConfigurationFactory(
                         new FileNameGlobMatcher("main.f3ah"),
@@ -201,7 +213,7 @@ public class IncludeAndImportConfigurableLayersTest {
     
     @Test
     public void test3LayerIncludesClashes2() throws Exception {
-        Configuration cfg = createConfigurationBuilder()
+        Configuration cfg = newConfigurationBuilder()
                 .autoIncludes("t1.f3ah", "t1.f3ah")
                 .templateConfigurations(
                         new ConditionalTemplateConfigurationFactory(
@@ -249,7 +261,7 @@ public class IncludeAndImportConfigurableLayersTest {
             throws Exception {
         Configuration cfg;
         {
-            TestConfigurationBuilder cfgB = createConfigurationBuilder()
+            TestConfigurationBuilder cfgB = newConfigurationBuilder()
                     .autoImports(ImmutableMap.of("t1", "t1.f3ah"));
             if (layer == Configuration.class) {
                 setLazinessOfConfigurable(cfgB, lazyImports, lazyAutoImports, setLazyAutoImports);
@@ -288,19 +300,9 @@ public class IncludeAndImportConfigurableLayersTest {
             cfg.setLazyAutoImports(lazyAutoImports);
         }
     }
-    
-    private TestConfigurationBuilder createConfigurationBuilder() {
-        StringTemplateLoader loader = new StringTemplateLoader();
-        loader.putTemplate("main.f3ah", "In main: ${loaded}");
-        loader.putTemplate("main2.f3ah", "In main2: ${loaded}");
-        loader.putTemplate("t1.f3ah", "<#global loaded = (loaded!) + 't1;'>T1;");
-        loader.putTemplate("t2.f3ah", "<#global loaded = (loaded!) + 't2;'>T2;");
-        loader.putTemplate("t3.f3ah", "<#global loaded = (loaded!) + 't3;'>T3;");
-        loader.putTemplate("t1b.f3ah", "<#global loaded = (loaded!) + 't1b;'>T1b;");
-        loader.putTemplate("t2b.f3ah", "<#global loaded = (loaded!) + 't2b;'>T2b;");
-        loader.putTemplate("t3b.f3ah", "<#global loaded = (loaded!) + 't3b;'>T3b;");
 
-        return new TestConfigurationBuilder().templateLoader(loader);
+    private TestConfigurationBuilder newConfigurationBuilder() {
+        return new TestConfigurationBuilder().templateLoader(TEMPLATE_LOADER);
     }
 
 }
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportTest.java
index b2dbf59..7f5c6e9 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/IncludeAndImportTest.java
@@ -29,7 +29,6 @@ import org.apache.freemarker.core.Environment.LazilyInitializedNamespace;
 import org.apache.freemarker.core.Environment.Namespace;
 import org.apache.freemarker.core.model.WrappingTemplateModel;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 import com.google.common.collect.ImmutableMap;
@@ -92,13 +91,12 @@ public class IncludeAndImportTest extends TemplateTest {
      */
     @Test
     public void autoIncludeAndAutoImport() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .autoImports(ImmutableMap.of(
                         "lib1", "lib1.f3ah",
                         "lib2", "lib2CallsLib1.f3ah"
                 ))
-                .autoIncludes("inc1.f3ah", "inc2.f3ah")
-                .build());
+                .autoIncludes("inc1.f3ah", "inc2.f3ah"));
         assertOutput(
                 "<#include 'inc3.f3ah'>[main] ${inc1Cnt}, ${history}, <@lib1.m/>, <@lib2.m/>",
                 "[inc1][inc2][inc3][main] 1, L1L2I, In lib1, In lib2 (In lib1)");
@@ -135,7 +133,7 @@ public class IncludeAndImportTest extends TemplateTest {
         
         assertOutput(ftl, "In lib2, In lib1; L1L2L3");
         
-        setConfiguration(new TestConfigurationBuilder().lazyImports(true).build());
+        setConfiguration(newConfigurationBuilder().lazyImports(true));
         assertOutput(ftl, "In lib2, In lib1; L2L1");
         
         assertOutput(ftlImports + "<@l3.m/>, " + ftlCalls, "In lib3 (In lib1), In lib2, In lib1; L3L1L2");
@@ -143,7 +141,7 @@ public class IncludeAndImportTest extends TemplateTest {
 
     @Test
     public void lazyImportAndLocale() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder().lazyImports(true).build());
+        setConfiguration(newConfigurationBuilder().lazyImports(true));
         assertOutput("<#setting locale = 'de_DE'><#import 'lib.f3ah' as lib>"
                 + "[${history!}] "
                 + "<#setting locale = 'en'>"
@@ -162,43 +160,23 @@ public class IncludeAndImportTest extends TemplateTest {
         String expectedEagerOutput = "In lib2, In lib1; L1L2L3";
         String expecedLazyOutput = "In lib2, In lib1; L2L1";
 
-        setConfiguration(new TestConfigurationBuilder()
-                .autoImports(autoImports)
-                .build());
+        setConfiguration(newConfigurationBuilder().autoImports(autoImports));
         assertOutput(ftl, expectedEagerOutput);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .autoImports(autoImports)
-                .lazyImports(true)
-                .build());
+        setConfiguration(newConfigurationBuilder().autoImports(autoImports).lazyImports(true));
         assertNull(getConfiguration().getLazyAutoImports());
         assertOutput(ftl, expecedLazyOutput);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .autoImports(autoImports)
-                .lazyImports(false)
-                .build());
+        setConfiguration(newConfigurationBuilder().autoImports(autoImports).lazyImports(false));
         assertOutput(ftl, expectedEagerOutput);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .autoImports(autoImports)
-                .lazyImports(false)
-                .lazyAutoImports(true)
-                .build());
+        setConfiguration(newConfigurationBuilder().autoImports(autoImports).lazyImports(false).lazyAutoImports(true));
         assertOutput(ftl, expecedLazyOutput);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .autoImports(autoImports)
-                .lazyImports(false)
-                .lazyAutoImports(null)
-                .build());
+        setConfiguration(newConfigurationBuilder().autoImports(autoImports).lazyImports(false).lazyAutoImports(null));
         assertOutput(ftl, expectedEagerOutput);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .autoImports(autoImports)
-                .lazyImports(true)
-                .lazyAutoImports(false)
-                .build());
+        setConfiguration(newConfigurationBuilder().autoImports(autoImports).lazyImports(true).lazyAutoImports(false));
         assertOutput(ftl, expectedEagerOutput);
     }
     
@@ -212,21 +190,19 @@ public class IncludeAndImportTest extends TemplateTest {
         String expectOutputWithoutHistory = "In lib2, In lib1; ";
         String expecedOutput = expectOutputWithoutHistory + "L2L1";
 
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .autoImports(autoImports)
-                .lazyAutoImports(true)
-                .build());
+                .lazyAutoImports(true));
         assertOutput(ftl, expecedOutput);
         assertOutput("<#import 'lib1.f3ah' as l1>" + ftl, expectOutputWithoutHistory + "L1L2");
         assertOutput("<#import './x/../lib1.f3ah' as l1>" + ftl, expectOutputWithoutHistory + "L1L2");
         assertOutput("<#import 'lib2.f3ah' as l2>" + ftl, expecedOutput);
         assertOutput("<#import 'lib3.f3ah' as l3>" + ftl, expectOutputWithoutHistory + "L3L2L1");
 
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .autoImports(autoImports)
                 .lazyAutoImports(true)
-                .lazyImports(true)
-                .build());
+                .lazyImports(true));
         assertOutput("<#import 'lib1.f3ah' as l1>" + ftl, expecedOutput);
         assertOutput("<#import './x/../lib1.f3ah' as l1>" + ftl, expecedOutput);
         assertOutput("<#import 'lib2.f3ah' as l2>" + ftl, expecedOutput);
@@ -235,15 +211,14 @@ public class IncludeAndImportTest extends TemplateTest {
 
     @Test
     public void lazyImportErrors() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .lazyImports(true)
                 .build());
         assertOutput("<#import 'noSuchTemplate.f3ah' as wrong>x", "x");
         
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .lazyImports(true)
-                .autoImports(ImmutableMap.of("wrong", "noSuchTemplate.f3ah"))
-                .build());
+                .autoImports(ImmutableMap.of("wrong", "noSuchTemplate.f3ah")));
         assertOutput("x", "x");
 
         try {
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
index 9865c18..1b6268b 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
@@ -65,18 +65,14 @@ public class InterpolationSyntaxTest extends TemplateTest {
         assertOutput("${'\"${1} #{1} [=1]\"'?eval}", "1 #{1} [=1]");
         
         assertOutput("<#setting booleanFormat='y,n'>${2>1}", "y"); // Not an error since 2.3.28
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(F3SDU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(F3SDU));
         assertOutput("[#setting booleanFormat='y,n']${2>1}", "y"); // Not an error since 2.3.28
     }
 
     @Test
     public void squareBracketInterpolationSyntaxTest() throws Exception {
         
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(F3ASU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(F3ASU));
         
         assertOutput("${1} #{1} [=1]", "${1} #{1} 1");
         assertOutput(
@@ -89,14 +85,10 @@ public class InterpolationSyntaxTest extends TemplateTest {
         
         assertErrorContains("<#if [true][0]]></#if>", "\"]\"", "nothing open");
 
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3SU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3SU));
         assertOutput("[#if [true][0]]>[/#if]", ">");
         assertOutput("[=1][=2]${3}", "12${3}");
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(F3ASU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(F3ASU));
         assertOutput("[#ftl][#if [true][0]]>[/#if]", ">");
         assertOutput("[#ftl][=1][=2]${3}", "12${3}");
          
@@ -126,9 +118,7 @@ public class InterpolationSyntaxTest extends TemplateTest {
     @Test
     public void squareBracketTagSyntaxStillWorks() throws Exception {
         for (TemplateLanguage tempLang : new TemplateLanguage[] { F3SDU, DefaultTemplateLanguage.F3SU }) {
-            setConfiguration(new TestConfigurationBuilder()
-                    .templateLanguage(tempLang)
-                    .build());
+            setConfiguration(newConfigurationBuilder().templateLanguage(tempLang));
             
             assertOutput("[#if [true][0]]t[#else]f[/#if]", "t");
             assertOutput("[@r'[#if [true][0]]t[#else]f[/#if]'?interpret /]", "t");
@@ -142,17 +132,13 @@ public class InterpolationSyntaxTest extends TemplateTest {
         String badFtl3 = "<#assign x = 'OK'/]${x}";
         String badFtl4 = " <#t/]OK\n";
         
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3AU)
-                .build());
+        setConfiguration(new TestConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3AU));
         assertErrorContains(badFtl1, "\"]\"");
         assertErrorContains(badFtl2, "\"]\"");
         assertErrorContains(badFtl3, "\"]\"");
         assertErrorContains(badFtl4, "\"]\"");
         
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(F3ASU)
-                .build());
+        setConfiguration(new TestConfigurationBuilder().templateLanguage(F3ASU));
         assertErrorContains(badFtl1, "\"]\"");
         assertErrorContains(badFtl2, "\"]\"");
         assertErrorContains(badFtl3, "\"]\"");
@@ -169,9 +155,7 @@ public class InterpolationSyntaxTest extends TemplateTest {
     public void unclosedSyntaxErrorTest() throws Exception {
         assertErrorContains("${1", "unclosed \"{\"");
         
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3SU)
-                .build());
+        setConfiguration(new TestConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3SU));
         assertErrorContains("[=1", "unclosed \"[\"");
     }
     
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretAndEvalTemplateNameTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretAndEvalTemplateNameTest.java
index a07d929..545f5aa 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretAndEvalTemplateNameTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretAndEvalTemplateNameTest.java
@@ -50,7 +50,7 @@ public class InterpretAndEvalTemplateNameTest extends TemplateTest {
             tl.putTemplate("sub/a.f3au", "In sub/a.f3au, " + getTemplateNames);
             tl.putTemplate("a.f3au", "In a.f3au");
 
-            setConfiguration(new TestConfigurationBuilder().templateLoader(tl).build());
+            setConfiguration(newConfigurationBuilder().templateLoader(tl));
             
             assertOutputForNamed("main.f3au",
                     "c=main.f3au, m=main.f3au "
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
index 3e17c2f..248d7bb 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
@@ -41,17 +41,13 @@ public class InterpretSettingInheritanceTest  extends TemplateTest {
 
     @Test
     public void tagSyntaxTest() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3AU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3AU));
         assertOutput(FTL_S_A_S, OUT_A_S_WHEN_SYNTAX_IS_A);
         assertOutput(FTL_S_S_A, OUT_S_A_WHEN_SYNTAX_IS_A);
         assertOutput(FTL_A_A_S, OUT_A_S_WHEN_SYNTAX_IS_A);
         assertOutput(FTL_A_S_A, OUT_S_A_WHEN_SYNTAX_IS_A);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3SU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3SU));
         assertOutput(FTL_S_A_S, OUT_A_S_WHEN_SYNTAX_IS_S);
         assertOutput(FTL_S_S_A, OUT_S_A_WHEN_SYNTAX_IS_S);
         assertOutput(FTL_A_A_S, OUT_A_S_WHEN_SYNTAX_IS_S);
@@ -69,9 +65,7 @@ public class InterpretSettingInheritanceTest  extends TemplateTest {
         assertOutput("<#ftl stripWhitespace=false><#assign x = 1>\nX<@'<#assign x = 1>\\nY'?interpret />", "\nXY");
         assertOutput("<#assign x = 1>\nX<@'<#ftl stripWhitespace=false><#assign x = 1>\\nY'?interpret />", "X\nY");
 
-        setConfiguration(new TestConfigurationBuilder()
-                .whitespaceStripping(false)
-                .build());
+        setConfiguration(newConfigurationBuilder().whitespaceStripping(false));
         assertOutput("<#assign x = 1>\nX<@'<#assign x = 1>\\nY'?interpret />", "\nX\nY");
         assertOutput("<#ftl stripWhitespace=true><#assign x = 1>\nX<@'<#assign x = 1>\\nY'?interpret />", "X\nY");
         assertOutput("<#assign x = 1>\nX<@'<#ftl stripWhitespace=true><#assign x = 1>\\nY'?interpret />", "\nXY");
@@ -79,15 +73,11 @@ public class InterpretSettingInheritanceTest  extends TemplateTest {
 
     @Test
     public void evalTest() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3AU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3AU));
         assertOutput("<@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval />", OUT_S_A_WHEN_SYNTAX_IS_A);
         assertOutput("[#ftl][@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval /]", OUT_S_A_WHEN_SYNTAX_IS_A);
 
-        setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3SU)
-                .build());
+        setConfiguration(newConfigurationBuilder().templateLanguage(DefaultTemplateLanguage.F3SU));
         assertOutput("[@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval /]", OUT_S_A_WHEN_SYNTAX_IS_S);
         assertOutput("<#ftl><@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval />", OUT_S_A_WHEN_SYNTAX_IS_S);
     }
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MinMaxBITest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MinMaxBITest.java
index 8a681d2..14b5578 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MinMaxBITest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MinMaxBITest.java
@@ -36,8 +36,8 @@ import com.google.common.collect.ImmutableList;
 public class MinMaxBITest extends TemplateTest {
     
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder().sqlDateAndTimeTimeZone(_DateUtils.UTC).timeFormat("HH:mm:ss").build();
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb.sqlDateAndTimeTimeZone(_DateUtils.UTC).timeFormat("HH:mm:ss");
     }
 
     @Test
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MiscErrorMessagesTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MiscErrorMessagesTest.java
index 81b9710..5aae785 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MiscErrorMessagesTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MiscErrorMessagesTest.java
@@ -36,7 +36,7 @@ public class MiscErrorMessagesTest extends TemplateTest {
     
     @Test
     public void wrongTemplateNameFormat() {
-        setConfiguration(new TestConfigurationBuilder().templateNameFormat(DefaultTemplateNameFormat.INSTANCE).build());
+        setConfiguration(newConfigurationBuilder().templateNameFormat(DefaultTemplateNameFormat.INSTANCE));
 
         assertErrorContains("<#include 'foo:/bar:baaz'>", "Malformed template name", "':'");
         assertErrorContains("<#include '../baaz'>", "Malformed template name", "root");
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java
index 1ee9f45..508f43e 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java
@@ -43,8 +43,8 @@ import org.junit.Test;
 public class NewBiObjectWrapperRestrictionTest extends TemplateTest {
 
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder().objectWrapper(new EntirelyCustomObjectWrapper()).build();
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb.objectWrapper(new EntirelyCustomObjectWrapper());
     }
 
     @Test
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
index 1a3e65c..5992a6e 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
@@ -40,7 +40,6 @@ import org.apache.freemarker.core.userpkg.CustomHTMLOutputFormat;
 import org.apache.freemarker.core.userpkg.DummyOutputFormat;
 import org.apache.freemarker.core.userpkg.SeldomEscapedOutputFormat;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -56,11 +55,11 @@ public class OutputFormatTest extends TemplateTest {
         
         for (OutputFormat cfgOutputFormat
                 : new OutputFormat[] { UndefinedOutputFormat.INSTANCE, RTFOutputFormat.INSTANCE } ) {
-            TestConfigurationBuilder cfgB = createDefaultConfigurationBuilder();
+            Configuration.ExtendableBuilder<?> cfgB = newConfigurationBuilder();
             if (!cfgOutputFormat.equals(UndefinedOutputFormat.INSTANCE)) {
                 cfgB.setOutputFormat(cfgOutputFormat);
             }
-            setConfiguration(cfgB.build());
+            setConfiguration(cfgB);
 
             assertEquals(cfgOutputFormat, getConfiguration().getOutputFormat());
             
@@ -100,7 +99,7 @@ public class OutputFormatTest extends TemplateTest {
         addTemplate("tWithHeader.f3ax", "<#ftl outputFormat='HTML'>" + commonContent);
         
         for (int setupNumber = 1; setupNumber <= 3; setupNumber++) {
-            TestConfigurationBuilder cfgB = createDefaultConfigurationBuilder();
+            Configuration.ExtendableBuilder<?> cfgB = newConfigurationBuilder();
             final OutputFormat cfgOutputFormat;
             final OutputFormat ftlhOutputFormat;
             final OutputFormat ftlxOutputFormat;
@@ -135,7 +134,7 @@ public class OutputFormatTest extends TemplateTest {
                 throw new AssertionError();
             }
 
-            setConfiguration(cfgB.build());
+            setConfiguration(cfgB);
             assertEquals(cfgOutputFormat, getConfiguration().getOutputFormat());
             
             {
@@ -192,37 +191,37 @@ public class OutputFormatTest extends TemplateTest {
                         .build());
 
         {
-            setConfiguration(createDefaultConfigurationBuilder().outputFormat(HTMLOutputFormat.INSTANCE).build());
+            setConfiguration(newConfigurationBuilder().outputFormat(HTMLOutputFormat.INSTANCE));
             assertOutputForNamed("t.f3ax", "&apos; &apos; '");  // Can't override it
-            setConfiguration(createDefaultConfigurationBuilder().templateConfigurations(tcfHTML).build());
+            setConfiguration(newConfigurationBuilder().templateConfigurations(tcfHTML));
             assertOutputForNamed("t.f3ax", "&apos; &apos; '");  // Can't override it
-            setConfiguration(createDefaultConfigurationBuilder().templateConfigurations(tcfNoAutoEsc).build());
+            setConfiguration(newConfigurationBuilder().templateConfigurations(tcfNoAutoEsc));
             assertOutputForNamed("t.f3ax", "&apos; &apos; '");  // Can't override it
         }
 
         {
-            setConfiguration(createDefaultConfigurationBuilder().recognizeStandardFileExtensions(false).build());
+            setConfiguration(newConfigurationBuilder().recognizeStandardFileExtensions(false));
             assertErrorContainsForNamed("t.f3ax", UndefinedOutputFormat.INSTANCE.getName());
 
-            setConfiguration(createDefaultConfigurationBuilder()
+            setConfiguration(newConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
-                    .outputFormat(HTMLOutputFormat.INSTANCE).build());
+                    .outputFormat(HTMLOutputFormat.INSTANCE));
             assertOutputForNamed("t.f3ax", "&#39; &#39; '");
 
-            setConfiguration(createDefaultConfigurationBuilder()
+            setConfiguration(newConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
-                    .outputFormat(XMLOutputFormat.INSTANCE).build());
+                    .outputFormat(XMLOutputFormat.INSTANCE));
             assertOutputForNamed("t.f3ax", "&apos; &apos; '");
 
-            setConfiguration(createDefaultConfigurationBuilder()
+            setConfiguration(newConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
-                    .templateConfigurations(tcfHTML).build());
+                    .templateConfigurations(tcfHTML));
             assertOutputForNamed("t.f3ax", "&#39; &#39; '");
 
-            setConfiguration(createDefaultConfigurationBuilder()
+            setConfiguration(newConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
                     .templateConfigurations(tcfNoAutoEsc)
-                    .outputFormat(XMLOutputFormat.INSTANCE).build());
+                    .outputFormat(XMLOutputFormat.INSTANCE));
             assertOutputForNamed("t.f3ax", "' &apos; '");
         }
     }
@@ -260,14 +259,12 @@ public class OutputFormatTest extends TemplateTest {
 
         assertOutputForNamed("t.f3ah", "a&amp;x");
 
-        setConfiguration(new TestConfigurationBuilder()
-                .registeredCustomOutputFormats(Collections.<OutputFormat>singleton(CustomHTMLOutputFormat.INSTANCE))
-                .build());
+        setConfiguration(newConfigurationBuilder()
+                .registeredCustomOutputFormats(Collections.<OutputFormat>singleton(CustomHTMLOutputFormat.INSTANCE)));
         assertOutputForNamed("t.f3ah", "a&amp;X");
 
-        setConfiguration(new TestConfigurationBuilder()
-                .registeredCustomOutputFormats(Collections.<OutputFormat>emptyList())
-                .build());
+        setConfiguration(newConfigurationBuilder()
+                .registeredCustomOutputFormats(Collections.<OutputFormat>emptyList()));
         assertOutputForNamed("t.f3ah", "a&amp;x");
     }
     
@@ -278,13 +275,13 @@ public class OutputFormatTest extends TemplateTest {
         addTemplate("tWithHeaderTrue", "<#ftl autoEsc=true>${'a&b'}");
         
         for (boolean cfgAutoEscaping : new boolean[] { true, false }) {
-            TestConfigurationBuilder cfgB = createDefaultConfigurationBuilder().outputFormat(XMLOutputFormat.INSTANCE);
+            Configuration.ExtendableBuilder<?> cfgB = newConfigurationBuilder().outputFormat(XMLOutputFormat.INSTANCE);
             assertEquals(ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
 
             if (!cfgAutoEscaping) {
                 cfgB.setAutoEscapingPolicy(DISABLE);
             }
-            setConfiguration(cfgB.build());
+            setConfiguration(cfgB);
 
             {
                 Template t = getConfiguration().getTemplate("t");
@@ -336,9 +333,7 @@ public class OutputFormatTest extends TemplateTest {
                 // Cfg default is autoEscaping true
                 assertOutput(commonAutoEscFtl, "&amp;");
             } else {
-                setConfiguration(createDefaultConfigurationBuilder()
-                        .autoEscapingPolicy(DISABLE)
-                        .build());
+                setConfiguration(newConfigurationBuilder().autoEscapingPolicy(DISABLE));
                 assertOutput(commonAutoEscFtl, "&");
             }
             
@@ -414,7 +409,7 @@ public class OutputFormatTest extends TemplateTest {
             assertEquals(UndefinedOutputFormat.INSTANCE, t.getOutputFormat());
         }
         {
-            setConfiguration(new TestConfigurationBuilder().outputFormat(HTMLOutputFormat.INSTANCE).build());
+            setConfiguration(newConfigurationBuilder().outputFormat(HTMLOutputFormat.INSTANCE));
             Template t = new Template("x", content, getConfiguration(), tc);
             Writer sw = new StringWriter();
             t.process(null, sw);
@@ -628,9 +623,8 @@ public class OutputFormatTest extends TemplateTest {
         assertErrorContains(
                 "<#outputFormat 'dummy'></#outputFormat>",
                 "dummy", "nregistered");
-        setConfiguration(new TestConfigurationBuilder()
-                .registeredCustomOutputFormats(Collections.<OutputFormat>singleton(DummyOutputFormat.INSTANCE))
-                .build());
+        setConfiguration(newConfigurationBuilder()
+                .registeredCustomOutputFormats(Collections.<OutputFormat>singleton(DummyOutputFormat.INSTANCE)));
         assertOutput(
                 "<#outputFormat 'dummy'>${.outputFormat}</#outputFormat>",
                 "dummy");
@@ -693,9 +687,8 @@ public class OutputFormatTest extends TemplateTest {
                 "<#noautoEsc></#noautoEsc>",
                 "Unknown directive");
 
-        setConfiguration(new TestConfigurationBuilder()
-                .outputFormat(XMLOutputFormat.INSTANCE)
-                .build());
+        setConfiguration(newConfigurationBuilder()
+                .outputFormat(XMLOutputFormat.INSTANCE));
         
         // Empty block:
         assertOutput(
@@ -734,7 +727,7 @@ public class OutputFormatTest extends TemplateTest {
 
     @Test
     public void testAutoEscPolicy() throws Exception {
-        assertEquals(ENABLE_IF_DEFAULT, createDefaultConfigurationBuilder().getAutoEscapingPolicy());
+        assertEquals(ENABLE_IF_DEFAULT, newConfigurationBuilder().getAutoEscapingPolicy());
         
         String commonFTL = "${'.'} ${.autoEsc?c}";
         String notEsced = ". false";
@@ -810,7 +803,7 @@ public class OutputFormatTest extends TemplateTest {
     private Configuration testAutoEscPolicy_createCfg(AutoEscapingPolicy autoEscPolicy,
             OutputFormat outpoutFormat)
             throws TemplateException {
-        return createDefaultConfigurationBuilder()
+        return super.newConfigurationBuilder()
                 .registeredCustomOutputFormats(ImmutableList.<OutputFormat>of(
                         SeldomEscapedOutputFormat.INSTANCE, DummyOutputFormat.INSTANCE))
                 .autoEscapingPolicy(autoEscPolicy)
@@ -994,17 +987,6 @@ public class OutputFormatTest extends TemplateTest {
         assertOutput("${m1?isMarkupOutput?c} ${m2?isMarkupOutput?c} ${s?isMarkupOutput?c}", "true true false");
     }
 
-    private TestConfigurationBuilder createDefaultConfigurationBuilder() throws TemplateException {
-        return new TestConfigurationBuilder()
-                .templateConfigurations(
-                        new ConditionalTemplateConfigurationFactory(
-                                new FileNameGlobMatcher("*.xml"),
-                                new TemplateConfiguration.Builder()
-                                        .outputFormat(XMLOutputFormat.INSTANCE)
-                                        .build()))
-                .templateCacheStorage(NullCacheStorage.INSTANCE); // Prevent caching as we change the cfgB between build().
-    }
-
     @Before
     public void addCommonDataModelVariables() throws TemplateException {
         addToDataModel("rtfPlain", RTFOutputFormat.INSTANCE.fromPlainTextByEscaping("\\par a & b"));
@@ -1016,8 +998,15 @@ public class OutputFormatTest extends TemplateTest {
     }
 
     @Override
-    protected Configuration createDefaultConfiguration() throws TemplateException {
-        return createDefaultConfigurationBuilder().build();
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb
+                .templateConfigurations(
+                        new ConditionalTemplateConfigurationFactory(
+                                new FileNameGlobMatcher("*.xml"),
+                                new TemplateConfiguration.Builder()
+                                        .outputFormat(XMLOutputFormat.INSTANCE)
+                                        .build()))
+                .templateCacheStorage(NullCacheStorage.INSTANCE); // Prevent caching as we change the cfgB between build().
     }
-    
+
 }
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
index 7bcdfd0..76b9c71 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
@@ -35,8 +35,7 @@ public class ParsingErrorMessagesTest extends TemplateTest {
         assertErrorContainsAS("<@foo ${x == 3} />", "instead of ${");
         
         setConfiguration(new TestConfigurationBuilder()
-                .templateLanguage(DefaultTemplateLanguage.F3SU)
-                .build());
+                .templateLanguage(DefaultTemplateLanguage.F3SU));
         assertErrorContains("[@foo [= x == 3] /]", "instead of [=");
     }
 
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java
index b91a020..68f71e2 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java
@@ -141,7 +141,7 @@ public class SQLTimeZoneTest extends TemplateTest {
             Configuration.ExtendableBuilder<?> cfgB = createConfigurationBuilder();
             cfgB.setSQLDateAndTimeTimeZone(null);
             cfgB.unsetTimeZone();
-            setConfiguration(cfgB.build());
+            setConfiguration(cfgB);
 
             assertNull(getConfiguration().getSQLDateAndTimeTimeZone());
             assertEquals(TimeZone.getDefault(), getConfiguration().getTimeZone());
@@ -159,7 +159,7 @@ public class SQLTimeZoneTest extends TemplateTest {
         try {
             Configuration.ExtendableBuilder<?> cfgB = createConfigurationBuilder();
             cfgB.sqlDateAndTimeTimeZone(GMT_P02).unsetTimeZone();
-            setConfiguration(cfgB.build());
+            setConfiguration(cfgB);
 
             assertOutput(FTL, OUTPUT_BEFORE_SETTING_GMT_CFG_GMT2 + OUTPUT_AFTER_SETTING_GMT_CFG_SQL_DIFFERENT);
         } finally {
@@ -171,8 +171,7 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testWithGMT1AndNullSQL() throws Exception {
         setConfiguration(createConfigurationBuilder()
                 .timeZone(TimeZone.getTimeZone("GMT+01:00"))
-                .sqlDateAndTimeTimeZone(null)
-                .build());
+                .sqlDateAndTimeTimeZone(null));
         assertNull(getConfiguration().getSQLDateAndTimeTimeZone());
 
         assertOutput(FTL, OUTPUT_BEFORE_SETTING_GMT_CFG_GMT1_SQL_SAME + OUTPUT_AFTER_SETTING_GMT_CFG_SQL_SAME);
@@ -182,8 +181,7 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testWithGMT1AndGMT2SQL() throws Exception {
         setConfiguration(createConfigurationBuilder()
                 .sqlDateAndTimeTimeZone(GMT_P02)
-                .timeZone(TimeZone.getTimeZone("GMT+01:00"))
-                .build());
+                .timeZone(TimeZone.getTimeZone("GMT+01:00")));
 
         assertOutput(FTL, OUTPUT_BEFORE_SETTING_GMT_CFG_GMT1_SQL_DIFFERENT + OUTPUT_AFTER_SETTING_GMT_CFG_SQL_DIFFERENT);
     }
@@ -192,8 +190,7 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testWithGMT2AndNullSQL() throws Exception {
         setConfiguration(createConfigurationBuilder()
                 .timeZone(TimeZone.getTimeZone("GMT+02"))
-                .sqlDateAndTimeTimeZone(null)
-                .build());
+                .sqlDateAndTimeTimeZone(null));
         assertNull(getConfiguration().getSQLDateAndTimeTimeZone());
 
         assertOutput(FTL, OUTPUT_BEFORE_SETTING_GMT_CFG_GMT2 + OUTPUT_AFTER_SETTING_GMT_CFG_SQL_SAME);
@@ -203,15 +200,14 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testWithGMT2AndGMT2SQL() throws Exception {
         setConfiguration(createConfigurationBuilder()
             .sqlDateAndTimeTimeZone(GMT_P02)
-            .timeZone(TimeZone.getTimeZone("GMT+02"))
-            .build());
+            .timeZone(TimeZone.getTimeZone("GMT+02")));
         
         assertOutput(FTL, OUTPUT_BEFORE_SETTING_GMT_CFG_GMT2 + OUTPUT_AFTER_SETTING_GMT_CFG_SQL_DIFFERENT);
     }
     
     @Test
     public void testCacheFlushings() throws Exception {
-        setConfiguration(testCacheFlushing_createBuilder().build());
+        setConfiguration(testCacheFlushing_createBuilder());
         assertOutput(
                 "${sqlDate}, ${sqlTime}, ${sqlTimestamp}, ${javaDate?dateTime}, ${javaDate?date}, ${javaDate?time}\n"
                 + "<#setting locale='hu'>\n"
@@ -237,7 +233,7 @@ public class SQLTimeZoneTest extends TemplateTest {
                 "2014-07-11 Fri, 10:30:05 Thu, 2014-07-12T10:30:05 Sat, 2014-07-12T10:30:05 Sat, 2014-07-12 Sat, 10:30:05 Sat\n"
                 + "2014-07-11 Fri, 10:30:05 Thu, 2014-07-12T10:30:05, 2014-07-12T10:30:05, 2014-07-12 Sat, 10:30:05 Sat\n");
 
-        setConfiguration(testCacheFlushing_createBuilder().sqlDateAndTimeTimeZone(GMT_P02).build());
+        setConfiguration(testCacheFlushing_createBuilder().sqlDateAndTimeTimeZone(GMT_P02));
         assertOutput(
                 "${sqlDate}, ${sqlTime}, ${sqlTimestamp}, ${javaDate?dateTime}, ${javaDate?date}, ${javaDate?time}\n"
                 + "<#setting locale='hu'>\n"
@@ -277,8 +273,7 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testDateAndTimeBuiltInsHasNoEffect() throws Exception {
         setConfiguration(createConfigurationBuilder()
                 .timeZone(_DateUtils.UTC)
-                .sqlDateAndTimeTimeZone(GMT_P02)
-                .build());
+                .sqlDateAndTimeTimeZone(GMT_P02));
 
         assertOutput(
                 "${javaDayErrorDate?date} ${javaDayErrorDate?time} ${sqlTimestamp?date} ${sqlTimestamp?time} "
@@ -298,8 +293,7 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testChangeSettingInTemplate() throws Exception {
         setConfiguration(createConfigurationBuilder()
                 .timeZone(_DateUtils.UTC)
-                .sqlDateAndTimeTimeZone(null)
-                .build());
+                .sqlDateAndTimeTimeZone(null));
 
         assertOutput(
                 "${sqlDate}, ${sqlTime}, ${sqlTimestamp}, ${javaDate?dateTime}\n"
@@ -334,8 +328,7 @@ public class SQLTimeZoneTest extends TemplateTest {
     public void testFormatUTCFlagHasNoEffect() throws Exception {
         setConfiguration(createConfigurationBuilder()
                 .sqlDateAndTimeTimeZone(GMT_P02)
-                .timeZone(TimeZone.getTimeZone("GMT-01"))
-                .build());
+                .timeZone(TimeZone.getTimeZone("GMT-01")));
         
         assertOutput(
                 "<#setting dateFormat='xs fz'><#setting timeFormat='xs fz'>\n"
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/SpecialVariableTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/SpecialVariableTest.java
index 270701a..e281706 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/SpecialVariableTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/SpecialVariableTest.java
@@ -49,12 +49,7 @@ public class SpecialVariableTest extends TemplateTest {
 
     @Test
     public void testIncompationImprovements() throws Exception {
-        setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0).build());
-        assertOutput(
-                "${.incompatibleImprovements}",
-                getConfiguration().getIncompatibleImprovements().toString());
-        
-        setConfiguration(new Configuration.Builder(Configuration.getVersion()).build());
+        setConfiguration(newConfigurationBuilder());
         assertOutput(
                 "${.incompatibleImprovements}",
                 getConfiguration().getIncompatibleImprovements().toString());
@@ -64,49 +59,43 @@ public class SpecialVariableTest extends TemplateTest {
     public void testAutoEsc() throws Exception {
         for (AutoEscapingPolicy autoEscaping : new AutoEscapingPolicy[] {
                 AutoEscapingPolicy.ENABLE_IF_DEFAULT, AutoEscapingPolicy.ENABLE_IF_SUPPORTED }) {
-            setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+            setConfiguration(newConfigurationBuilder()
                     .autoEscapingPolicy(autoEscaping)
-                    .outputFormat(HTMLOutputFormat.INSTANCE)
-                    .build());
+                    .outputFormat(HTMLOutputFormat.INSTANCE));
             assertOutput("${.autoEsc?c}", "true");
             assertOutput("<#ftl autoEsc=false>${.autoEsc?c}", "false");
 
-            setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+            setConfiguration(newConfigurationBuilder()
                     .autoEscapingPolicy(autoEscaping)
-                    .outputFormat(PlainTextOutputFormat.INSTANCE)
-                    .build());
+                    .outputFormat(PlainTextOutputFormat.INSTANCE));
             assertOutput("${.autoEsc?c}", "false");
 
-            setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+            setConfiguration(newConfigurationBuilder()
                     .autoEscapingPolicy(autoEscaping)
-                    .outputFormat(UndefinedOutputFormat.INSTANCE)
-                    .build());
+                    .outputFormat(UndefinedOutputFormat.INSTANCE));
             assertOutput("${.autoEsc?c}", "false");
         }
         
-        setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+        setConfiguration(newConfigurationBuilder()
                 .autoEscapingPolicy(AutoEscapingPolicy.DISABLE)
-                .outputFormat(HTMLOutputFormat.INSTANCE)
-                .build());
+                .outputFormat(HTMLOutputFormat.INSTANCE));
         assertOutput("${.autoEsc?c}", "false");
         assertOutput("<#ftl autoEsc=true>${.autoEsc?c}", "true");
 
-        setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+        setConfiguration(newConfigurationBuilder()
                 .autoEscapingPolicy(AutoEscapingPolicy.DISABLE)
-                .outputFormat(PlainTextOutputFormat.INSTANCE)
-                .build());
+                .outputFormat(PlainTextOutputFormat.INSTANCE));
         assertOutput("${.autoEsc?c}", "false");
 
-        setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+        setConfiguration(newConfigurationBuilder()
                 .autoEscapingPolicy(AutoEscapingPolicy.DISABLE)
                 .outputFormat(UndefinedOutputFormat.INSTANCE)
                 .build());
         assertOutput("${.autoEsc?c}", "false");
 
-        setConfiguration(new Configuration.Builder(Configuration.VERSION_3_0_0)
+        setConfiguration(newConfigurationBuilder()
                 .autoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_DEFAULT)
-                .outputFormat(UndefinedOutputFormat.INSTANCE)
-                .build());
+                .outputFormat(UndefinedOutputFormat.INSTANCE));
         assertOutput(
                 "${.autoEsc?c} "
                 + "<#outputFormat 'HTML'>${.autoEsc?c}</#outputFormat> "
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/StringLiteralInterpolationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/StringLiteralInterpolationTest.java
index 13b9bff..e8fc4fa 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/StringLiteralInterpolationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/StringLiteralInterpolationTest.java
@@ -102,11 +102,10 @@ public class StringLiteralInterpolationTest extends TemplateTest {
     
     @Test
     public void markup() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .customNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
                         "G", PrintfGTemplateNumberFormatFactory.INSTANCE))
-                .numberFormat("@G 3")
-                .build());
+                .numberFormat("@G 3"));
 
         assertOutput("${\"${1000}\"}", "1.00*10<sup>3</sup>");
         assertOutput("${\"&_${1000}\"}", "&amp;_1.00*10<sup>3</sup>");
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TabSizeTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TabSizeTest.java
index 7945b5e..d094837 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TabSizeTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TabSizeTest.java
@@ -23,16 +23,10 @@ import static org.junit.Assert.*;
 import java.io.IOException;
 
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class TabSizeTest extends TemplateTest {
 
-    @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return super.createDefaultConfiguration();
-    }
-
     @Test
     public void testBasics() throws Exception {
         assertErrorColumnNumber(3, "${*}");
@@ -40,7 +34,7 @@ public class TabSizeTest extends TemplateTest {
         assertErrorColumnNumber(16 + 3, "\t\t${*}");
         assertErrorColumnNumber(16 + 3, "  \t  \t${*}");
 
-        setConfiguration(new TestConfigurationBuilder().tabSize(1).build());
+        setConfiguration(newConfigurationBuilder().tabSize(1));
         assertErrorColumnNumber(3, "${*}");
         assertErrorColumnNumber(1 + 3, "\t${*}");
         assertErrorColumnNumber(2 + 3, "\t\t${*}");
@@ -50,14 +44,14 @@ public class TabSizeTest extends TemplateTest {
     @Test
     public void testEvalBI() throws Exception {
         assertErrorContains("${r'\t~'?eval}", "column 9");
-        setConfiguration(new TestConfigurationBuilder().tabSize(4).build());
+        setConfiguration(newConfigurationBuilder().tabSize(4));
         assertErrorContains("${r'\t~'?eval}", "column 5");
     }
 
     @Test
     public void testInterpretBI() throws Exception {
         assertErrorContains("<@'\\t$\\{*}'?interpret />", "column 11");
-        setConfiguration(new TestConfigurationBuilder().tabSize(4).build());
+        setConfiguration(newConfigurationBuilder().tabSize(4));
         assertErrorContains("<@'\\t$\\{*}'?interpret />", "column 7");
     }
     
@@ -65,7 +59,7 @@ public class TabSizeTest extends TemplateTest {
     public void testStringLiteralInterpolation() throws Exception {
         assertErrorColumnNumber(6, "${'${*}'}");
         assertErrorColumnNumber(9, "${'${\t*}'}");
-        setConfiguration(new TestConfigurationBuilder().tabSize(16).build());
+        setConfiguration(newConfigurationBuilder().tabSize(16));
         assertErrorColumnNumber(17, "${'${\t*}'}");
     }
 
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateNameSpecialVariablesTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateNameSpecialVariablesTest.java
index f800f9f..f20ad05 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateNameSpecialVariablesTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateNameSpecialVariablesTest.java
@@ -152,8 +152,8 @@ public class TemplateNameSpecialVariablesTest extends TemplateTest {
     }
 
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder().whitespaceStripping(false).build();
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb.whitespaceStripping(false);
     }
 
 }
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TruncateBuiltInTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TruncateBuiltInTest.java
index 33ddd3f..365f472 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TruncateBuiltInTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TruncateBuiltInTest.java
@@ -5,7 +5,6 @@ import java.io.IOException;
 import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
 import org.apache.freemarker.core.pluggablebuiltin.impl.DefaultTruncateBuiltinAlgorithm;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -14,12 +13,8 @@ public class TruncateBuiltInTest extends TemplateTest {
     private static final String M_TERM_SRC = "<span class=trunc>&hellips;</span>";
 
     @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return createConfigurationBuilder().build();
-    }
-
-    private TestConfigurationBuilder createConfigurationBuilder() {
-        return new TestConfigurationBuilder().outputFormat(HTMLOutputFormat.INSTANCE);
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        cb.outputFormat(HTMLOutputFormat.INSTANCE);
     }
 
     @Before
@@ -116,7 +111,8 @@ public class TruncateBuiltInTest extends TemplateTest {
     public void testSettingHasEffect() throws IOException, TemplateException {
         assertOutput("${t?truncate(20)}", "Some text for [...]");
         assertOutput("${t?truncateC(20)}", "Some text for t[...]");
-        setConfiguration(createConfigurationBuilder().truncateBuiltinAlgorithm(DefaultTruncateBuiltinAlgorithm.UNICODE_INSTANCE).build());
+        setConfiguration(newConfigurationBuilder().truncateBuiltinAlgorithm(
+                DefaultTruncateBuiltinAlgorithm.UNICODE_INSTANCE));
         assertOutput("${t?truncate(20)}", "Some text for [\u2026]");
         assertOutput("${t?truncateC(20)}", "Some text for tru[\u2026]");
     }
@@ -125,9 +121,8 @@ public class TruncateBuiltInTest extends TemplateTest {
     public void testDifferentMarkupSeparatorSetting() throws IOException, TemplateException {
         assertOutput("${t?truncate(20)}", "Some text for [...]");
         assertOutput("${t?truncateM(20)}", "Some text for <span class='truncateTerminator'>[&#8230;]</span>");
-        setConfiguration(createConfigurationBuilder().truncateBuiltinAlgorithm(
-                new DefaultTruncateBuiltinAlgorithm("|...", HTMLOutputFormat.INSTANCE.fromMarkup(M_TERM_SRC), true))
-                .build());
+        setConfiguration(newConfigurationBuilder().truncateBuiltinAlgorithm(
+                new DefaultTruncateBuiltinAlgorithm("|...", HTMLOutputFormat.INSTANCE.fromMarkup(M_TERM_SRC), true)));
         assertOutput("${t?truncate(20)}", "Some text for |...");
         assertOutput("${t?truncateM(20)}", "Some text for " + M_TERM_SRC);
     }
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/WhitespaceStrippingTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/WhitespaceStrippingTest.java
index 8e5b52e..91aecdb 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/WhitespaceStrippingTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/WhitespaceStrippingTest.java
@@ -22,7 +22,6 @@ package org.apache.freemarker.core;
 import java.io.IOException;
 
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class WhitespaceStrippingTest extends TemplateTest {
@@ -53,10 +52,10 @@ public class WhitespaceStrippingTest extends TemplateTest {
     
     private void assertOutput(String ftl, String expectedOutStripped, String expectedOutNonStripped)
             throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder().build());
+        setConfiguration(newConfigurationBuilder());
         assertOutput(ftl, expectedOutStripped);
         
-        setConfiguration(new TestConfigurationBuilder().whitespaceStripping(false).build());
+        setConfiguration(newConfigurationBuilder().whitespaceStripping(false));
         assertOutput(ftl, expectedOutNonStripped);
     }
 
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
index 2cea282..5ff0d6e 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java
@@ -339,7 +339,7 @@ public class NumberFormatTest extends TemplateTest {
             cfgB.setTemplateConfigurations(templateConfigurationFactory);
         }
 
-        setConfiguration(cfgB.build());
+        setConfiguration(cfgB);
     }
 
     private void setConfigurationWithNumberFormat(String numberFormat) {
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/impl/ExtendedDecimalFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/impl/ExtendedDecimalFormatTest.java
index 9637205..68ab147 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/impl/ExtendedDecimalFormatTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/impl/ExtendedDecimalFormatTest.java
@@ -276,14 +276,14 @@ public class ExtendedDecimalFormatTest extends TemplateTest {
     
     @Test
     public void testTemplates() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder().numberFormat(",000.#").build());
+        setConfiguration(newConfigurationBuilder().numberFormat(",000.#"));
         assertOutput("${1000.15} ${1000.25}", "1,000.2 1,000.2");
         String numberFormat = ",000.#;; roundingMode=halfUp groupingSeparator=_";
-        setConfiguration(new TestConfigurationBuilder().numberFormat(numberFormat).build());;
+        setConfiguration(newConfigurationBuilder().numberFormat(numberFormat));;
         assertOutput("${1000.15} ${1000.25}", "1_000.2 1_000.3");
-        setConfiguration(new TestConfigurationBuilder().numberFormat(numberFormat).locale(Locale.GERMANY).build());;
+        setConfiguration(newConfigurationBuilder().numberFormat(numberFormat).locale(Locale.GERMANY));;
         assertOutput("${1000.15} ${1000.25}", "1_000,2 1_000,3");
-        setConfiguration(new TestConfigurationBuilder().numberFormat(numberFormat).locale(Locale.US).build());;
+        setConfiguration(newConfigurationBuilder().numberFormat(numberFormat).locale(Locale.US));;
         assertOutput(
                 "${1000.15}; "
                 + "${1000.15?string(',##.#;;groupingSeparator=\" \"')}; "
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
index 347980d..fa26e5e 100644
--- a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
@@ -30,7 +30,6 @@ import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.dom.test.DOMLoader;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Before;
 import org.junit.Test;
 import org.xml.sax.SAXException;
@@ -44,13 +43,12 @@ public class DefaultObjectWrapperExtensionTest extends TemplateTest {
 
     @Test
     public void testWithExtensions() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder()
+        setConfiguration(newConfigurationBuilder()
                 .objectWrapper(
                         new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0)
                                 .extensions(DOMDefaultObjectWrapperExtension.INSTANCE)
                                 .build()
-                )
-                .build());
+                ));
         assertOutput("${doc.title}", "test");
     }
 
diff --git a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
index d64b36b..0ac7d01 100644
--- a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
+++ b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
@@ -27,13 +27,6 @@ import org.junit.Test;
 
 public class AbsoluteTemplateNameBIExample extends TemplateTest {
 
-    @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder()
-                .templateLoader(new ClassTemplateLoader(AbsoluteTemplateNameBIExample.class, ""))
-                .build();
-    }
-
     @Test
     public void test() throws Exception {
         assertOutputForNamed("dir/AbsoluteTemplateNameBIExample-main.f3ah");
diff --git a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AutoEscapingExample.java b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AutoEscapingExample.java
index 0718626..bfd3d69 100644
--- a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AutoEscapingExample.java
+++ b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AutoEscapingExample.java
@@ -64,9 +64,4 @@ public class AutoEscapingExample extends TemplateTest {
     public void testStringConcat() throws Exception {
         assertOutputForNamed("AutoEscapingExample-stringConcat.f3ah");
     }
-
-    @Override
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder(AutoEscapingExample.class).build();
-    }
 }
diff --git a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/ConfigureOutputFormatExamples.java b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/ConfigureOutputFormatExamples.java
index 23d4c8b..46b241c 100644
--- a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/ConfigureOutputFormatExamples.java
+++ b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/ConfigureOutputFormatExamples.java
@@ -32,7 +32,6 @@ import org.apache.freemarker.core.templateresolver.FirstMatchTemplateConfigurati
 import org.apache.freemarker.core.templateresolver.OrMatcher;
 import org.apache.freemarker.core.templateresolver.PathGlobMatcher;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class ConfigureOutputFormatExamples extends TemplateTest {
@@ -54,24 +53,22 @@ public class ConfigureOutputFormatExamples extends TemplateTest {
     private void example2(boolean javaCfg) throws IOException {
         setConfiguration(
                 javaCfg
-                        ? new TestConfigurationBuilder()
+                        ? newConfigurationBuilder()
                                 .templateConfigurations(
                                         new ConditionalTemplateConfigurationFactory(
                                                 new PathGlobMatcher("mail/**"),
                                                 new TemplateConfiguration.Builder()
                                                         .outputFormat(HTMLOutputFormat.INSTANCE)
                                                         .build()))
-                                .build()
-                        : new TestConfigurationBuilder()
-                                .settings(loadPropertiesFile("ConfigureOutputFormatExamples1.properties"))
-                                .build());
+                        : newConfigurationBuilder()
+                                .settings(loadPropertiesFile("ConfigureOutputFormatExamples1.properties")));
         assertEquals(HTMLOutputFormat.INSTANCE, getConfiguration().getTemplate("mail/news").getOutputFormat());
     }
 
     private void example3(boolean javaCfg) throws IOException {
         setConfiguration(
                 javaCfg
-                        ? new TestConfigurationBuilder()
+                        ? newConfigurationBuilder()
                                 .templateConfigurations(
                                         new FirstMatchTemplateConfigurationFactory(
                                                 new ConditionalTemplateConfigurationFactory(
@@ -92,10 +89,8 @@ public class ConfigureOutputFormatExamples extends TemplateTest {
                                                                 .outputFormat(RTFOutputFormat.INSTANCE)
                                                                 .build()))
                                         .allowNoMatch(true))
-                                .build()
-                        : new TestConfigurationBuilder()
-                                .settings(loadPropertiesFile("ConfigureOutputFormatExamples2.properties"))
-                                .build());
+                        : newConfigurationBuilder()
+                                .settings(loadPropertiesFile("ConfigureOutputFormatExamples2.properties")));
         assertEquals(HTMLOutputFormat.INSTANCE, getConfiguration().getTemplate("t.html").getOutputFormat());
         assertEquals(HTMLOutputFormat.INSTANCE, getConfiguration().getTemplate("t.htm").getOutputFormat());
         assertEquals(XMLOutputFormat.INSTANCE, getConfiguration().getTemplate("t.xml").getOutputFormat());
diff --git a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/CustomFormatsExample.java b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/CustomFormatsExample.java
index 1e38cdb..b003515 100644
--- a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/CustomFormatsExample.java
+++ b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/CustomFormatsExample.java
@@ -28,7 +28,6 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
 import org.apache.freemarker.core.valueformat.impl.AliasTemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.impl.AliasTemplateNumberFormatFactory;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 import com.google.common.collect.ImmutableMap;
@@ -38,15 +37,14 @@ public class CustomFormatsExample extends TemplateTest {
 
     @Test
     public void aliases1() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder(this.getClass())
+        setConfiguration(newConfigurationBuilder()
             .customNumberFormats(ImmutableMap.<String, TemplateNumberFormatFactory>of(
                     "price", new AliasTemplateNumberFormatFactory(",000.00"),
                     "weight", new AliasTemplateNumberFormatFactory("0.##;; roundingMode=halfUp")))
             .customDateFormats(ImmutableMap.<String, TemplateDateFormatFactory>of(
                     "fileDate", new AliasTemplateDateFormatFactory("dd/MMM/yy hh:mm a"),
                     "logEventTime", new AliasTemplateDateFormatFactory("iso ms u")
-                    ))
-            .build());
+                    )));
 
         addToDataModel("p", 10000);
         addToDataModel("w", new BigDecimal("10.305"));
@@ -58,22 +56,20 @@ public class CustomFormatsExample extends TemplateTest {
 
     @Test
     public void aliases2() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder(this.getClass())
+        setConfiguration(newConfigurationBuilder()
                 .customNumberFormats(ImmutableMap.of(
                         "base", BaseNTemplateNumberFormatFactory.INSTANCE,
-                        "oct", new AliasTemplateNumberFormatFactory("@base 8")))
-                .build());
+                        "oct", new AliasTemplateNumberFormatFactory("@base 8"))));
 
         assertOutputForNamed("CustomFormatsExample-alias2.f3ah");
     }
 
     @Test
     public void modelAware() throws IOException, TemplateException {
-        setConfiguration(new TestConfigurationBuilder(this.getClass())
+        setConfiguration(newConfigurationBuilder()
                 .customNumberFormats(ImmutableMap.<String, TemplateNumberFormatFactory>of(
                         "ua", UnitAwareTemplateNumberFormatFactory.INSTANCE))
-                .numberFormat("@ua 0.####;; roundingMode=halfUp")
-                .build());
+                .numberFormat("@ua 0.####;; roundingMode=halfUp"));
 
         addToDataModel("weight", new UnitAwareTemplateNumberModel(1.5, "kg"));
         
diff --git a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/TemplateConfigurationExamples.java b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/TemplateConfigurationExamples.java
index 03dc3b1..3f6b011 100644
--- a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/TemplateConfigurationExamples.java
+++ b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/TemplateConfigurationExamples.java
@@ -39,7 +39,6 @@ import org.apache.freemarker.core.templateresolver.OrMatcher;
 import org.apache.freemarker.core.templateresolver.PathGlobMatcher;
 import org.apache.freemarker.core.util._DateUtils;
 import org.apache.freemarker.test.TemplateTest;
-import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class TemplateConfigurationExamples extends TemplateTest {
@@ -55,7 +54,7 @@ public class TemplateConfigurationExamples extends TemplateTest {
     }
 
     private void example1(boolean javaCfg) throws Exception {
-        TestConfigurationBuilder cfgB = new TestConfigurationBuilder(this.getClass());
+        Configuration.ExtendableBuilder<?> cfgB = newConfigurationBuilder();
         if (javaCfg) {
             cfgB.setTemplateConfigurations(new ConditionalTemplateConfigurationFactory(
                     new FileExtensionMatcher("xml"),
@@ -68,7 +67,7 @@ public class TemplateConfigurationExamples extends TemplateTest {
             cfgB.setTemplateConfigurations(null);
             cfgB.setSettings(loadPropertiesFile("TemplateConfigurationExamples1.properties"));
         }
-        setConfiguration(cfgB.build());
+        setConfiguration(cfgB);
 
         addTemplate("t.xml", "");
 
@@ -88,7 +87,7 @@ public class TemplateConfigurationExamples extends TemplateTest {
     }
 
     private void example2(boolean javaCfg) throws Exception {
-        TestConfigurationBuilder cfgB = new TestConfigurationBuilder(this.getClass());
+        Configuration.ExtendableBuilder<?> cfgB = newConfigurationBuilder();
         if (javaCfg) {
             cfgB.setTemplateConfigurations(
                     new ConditionalTemplateConfigurationFactory(
@@ -110,7 +109,7 @@ public class TemplateConfigurationExamples extends TemplateTest {
         } else{
             cfgB.setSettings(loadPropertiesFile("TemplateConfigurationExamples2.properties"));
         }
-        setConfiguration(cfgB.build());
+        setConfiguration(cfgB);
 
         addTemplate("t.subject.t", "");
         addTemplate("mail/t.subject.t", "");
@@ -133,7 +132,7 @@ public class TemplateConfigurationExamples extends TemplateTest {
     }
 
     private void example3(boolean javaCfg) throws Exception {
-        TestConfigurationBuilder cfgB = new TestConfigurationBuilder(this.getClass())
+        Configuration.ExtendableBuilder<?> cfgB = newConfigurationBuilder()
                 .sourceEncoding(StandardCharsets.ISO_8859_1);
         if (javaCfg) {
             cfgB.setTemplateConfigurations(
@@ -168,7 +167,7 @@ public class TemplateConfigurationExamples extends TemplateTest {
         } else {
             cfgB.setSettings(loadPropertiesFile("TemplateConfigurationExamples3.properties"));
         }
-        setConfiguration(cfgB.build());
+        setConfiguration(cfgB);
 
         addTemplate("t.stats.html", "${ts?dateTime} ${ts?date} ${ts?time}");
         addTemplate("t.html", "");
diff --git a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
index 5915ae3..747fa60 100644
--- a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
+++ b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
@@ -41,6 +41,7 @@ import org.apache.freemarker.core.Template;
 import org.apache.freemarker.core.TemplateConfiguration;
 import org.apache.freemarker.core.TemplateConfiguration.Builder;
 import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.Version;
 import org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader;
 import org.apache.freemarker.core.templateresolver.impl.MultiTemplateLoader;
@@ -63,12 +64,13 @@ public abstract class TemplateTest {
     private LinkedList<TemplateConfiguration> tcStack = new LinkedList<>();
 
     /**
-     * Gets the {@link Configuration} used, automatically creating and setting if it wasn't yet.
+     * Gets the {@link Configuration} used, automatically creating and setting if it wasn't yet. Automatic creation
+     * happens via {@link #newConfigurationBuilder()}.
      */
     protected final Configuration getConfiguration() {
         if (configuration == null) {
             try {
-                setConfiguration(createDefaultConfiguration());
+                setConfiguration(newConfigurationBuilder());
             } catch (Exception e) {
                 throw new RuntimeException("Failed to create configuration", e);
             }
@@ -77,8 +79,11 @@ public abstract class TemplateTest {
     }
 
     /**
-     * @param configuration Usually should be built using {@link TestConfigurationBuilder}; not {@code null}.
-     * 
+     * Set the {@link Configuration} used.
+     *
+     * @param configuration The {@link Configuration} used from now on; not {@code null}. Usually built with
+     * {@link #newConfigurationBuilder()}.
+     *
      * @see #pushNamelessTemplateConfiguraitonSettings(TemplateConfiguration)
      */
     protected final void setConfiguration(Configuration configuration) {
@@ -91,6 +96,14 @@ public abstract class TemplateTest {
         afterConfigurationSet();
     }
 
+    /**
+     * Convenience overload, that calls {@link #setConfiguration(Configuration)} after calling
+     * with the result of {@link Configuration.ExtendableBuilder#build()}.
+     */
+    protected final void setConfiguration(Configuration.ExtendableBuilder<?> configurationBuilder) {
+        setConfiguration(configurationBuilder.build());
+    }
+
     protected void assertOutput(String ftl, String expectedOut) throws IOException, TemplateException {
         assertOutput(createTemplate(ftl), expectedOut, false);
     }
@@ -177,9 +190,46 @@ public abstract class TemplateTest {
         });
         return out.toString();
     }
-    
-    protected Configuration createDefaultConfiguration() throws Exception {
-        return new TestConfigurationBuilder().build();
+
+    /**
+     * Same as {@link #newConfigurationBuilderBeforeSetup(Version)} with {@code null} parameter.
+     */
+    protected final Configuration.ExtendableBuilder<?> newConfigurationBuilder() {
+        return newConfigurationBuilder(null);
+    }
+
+    /**
+     * Return a new {@link TestConfigurationBuilder} that you can pass to {@link #setConfiguration(Configuration)}.
+     * This is also called automatically when {@link #getConfiguration()} is called for the first time, and
+     * #setConfiguration(Configuration)} wasn't called before.
+     * The instance will be created with {@link #newConfigurationBuilderBeforeSetup(Version)}, and then set up with
+     * {@link #setupConfigurationBuilder(Configuration.ExtendableBuilder)}.
+     *
+     * @param incompatibleImprovements Can be {@code null}, in which case a default value is used (normally the
+     *                                 lowest supported value).
+     */
+    protected final Configuration.ExtendableBuilder<?> newConfigurationBuilder(Version incompatibleImprovements) {
+        Configuration.ExtendableBuilder<?> cb = newConfigurationBuilderBeforeSetup(incompatibleImprovements);
+        setupConfigurationBuilder(cb);
+        return cb;
+    }
+
+    /**
+     * Override this only if the {@link TestConfigurationBuilder} <em>class</em> is not appropriate for the test.
+     * Otherwise you probably should override {@link #setupConfigurationBuilder(Configuration.ExtendableBuilder)} instead.
+     *
+     * @param incompatibleImprovements {@code null} if wasn't explicitly specified in the test.
+     */
+    protected Configuration.ExtendableBuilder<?> newConfigurationBuilderBeforeSetup(Version incompatibleImprovements) {
+        return new TestConfigurationBuilder(incompatibleImprovements, this.getClass());
+    }
+
+    /**
+     * Override this if you want change the configuration settings for all tests in a test class.
+     * The default implementation in {@link TemplateTest} does nothing.
+     */
+    protected void setupConfigurationBuilder(Configuration.ExtendableBuilder<?> cb) {
+        // No op
     }
 
     private void afterConfigurationSet() {


Mime
View raw message