diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 7909f4fa60e7b4135016253271c9878c3eb420a3..a89de0a6a441b21f95d635cf3b382fd036c44e00 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -853,6 +853,7 @@ public class TestBase {
         microTestInfo.expression = input;
         String result;
         try {
+            beforeEval();
             result = fastROutputManager.fastRSession.eval(this, input, contextInfo, longTimeout);
         } catch (Throwable e) {
             String clazz;
@@ -900,7 +901,7 @@ public class TestBase {
      * Evaluate expected output from {@code input}. By default the lookup is based on {@code input}
      * but can be overridden by providing a non-null {@code testIdOrNull}.
      */
-    protected static String expectedEval(String input, TestTrait... traits) {
+    protected String expectedEval(String input, TestTrait... traits) {
         if (generatingExpected()) {
             // generation mode
             return genTestResult(input, traits);
@@ -920,8 +921,8 @@ public class TestBase {
         }
     }
 
-    private static String genTestResult(String input, TestTrait... traits) {
-        return expectedOutputManager.genTestResult(testElementName, input, localDiagnosticHandler, expectedOutputManager.checkOnly, keepTrailingWhiteSpace, traits);
+    private String genTestResult(String input, TestTrait... traits) {
+        return expectedOutputManager.genTestResult(this, testElementName, input, localDiagnosticHandler, expectedOutputManager.checkOnly, keepTrailingWhiteSpace, traits);
     }
 
     /**
@@ -1027,6 +1028,12 @@ public class TestBase {
                 System.out.printf("    failed: %6d | %6d%n", failedTestCount, failedInputCount);
             }
         });
+    }
 
+    /**
+     * Called before an actual evaluation happens.
+     */
+    public void beforeEval() {
+        // empty
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java
index da01131596867aa995cec32575a0fe560592ad15..1bfcae0799319dfb90ad71c300d5919b36e177d8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java
@@ -40,6 +40,7 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.test.TestBase;
 import com.oracle.truffle.r.test.TestBase.Context;
 import com.oracle.truffle.r.test.TestBase.Ignored;
 import com.oracle.truffle.r.test.TestBase.Output;
@@ -401,7 +402,7 @@ public class TestOutputManager {
      * @param keepTrailingWhiteSpace if {@code true} preserve trailing white space, otherwise trim
      * @return the GnuR output
      */
-    public String genTestResult(String testElementName, String test, DiagnosticHandler d, boolean checkOnly, boolean keepTrailingWhiteSpace, TestTrait... traits) {
+    public String genTestResult(TestBase testClass, String testElementName, String test, DiagnosticHandler d, boolean checkOnly, boolean keepTrailingWhiteSpace, TestTrait... traits) {
         Map<String, TestInfo> testMap = getTestMap(testElementName);
         TestInfo testInfo = testMap.get(test);
         if (testInfo != null) {
@@ -418,7 +419,8 @@ public class TestOutputManager {
             String expected = null;
             if (!checkOnly) {
                 try {
-                    expected = rSession.eval(null, test, null, false);
+                    testClass.beforeEval();
+                    expected = rSession.eval(testClass, test, null, false);
                 } catch (Throwable e) {
                     throw RInternalError.shouldNotReachHere("unexpected exception thrown by GNUR session: " + e);
                 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
index 372f4a1f906ef6f4df0f67c57524e0142e8729ca..58fc5690fd0f93b2ae38869dcdea351fc5ad632c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
@@ -41,7 +41,7 @@ public class TestRFFIPackage extends TestRPackages {
 
     @AfterClass
     public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages(TEST_PACKAGES);
+        tearDownUninstallTestPackages();
     }
 
     /**
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
index e25c359840854577f5b7270e2a7e2d44c68a29a6..c2d69dba114f009e9c7ea096d4c1c68cacfb888c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
@@ -59,6 +59,10 @@ public abstract class TestRPackages extends TestBase {
 
     private static final String SYSTEM2_COMMAND = "system2('%s', c('CMD', 'INSTALL', '%s'), env='R_LIBS=%s', stdout=T, stderr=T)";
 
+    private static String[] installedPackages;
+    private static Resolver resolver;
+    private static boolean needsInstall;
+
     private static final class PackagePath {
         /**
          * The path containing the package distributions as tar files.
@@ -124,10 +128,6 @@ public abstract class TestRPackages extends TestBase {
         return result;
     }
 
-    protected static void setupInstallTestPackages(String[] testPackages) {
-        setupInstallTestPackages(testPackages, new Resolver());
-    }
-
     private static boolean installPackage(PackagePath packagePath) {
         String cmd;
         Path binBase;
@@ -164,12 +164,28 @@ public abstract class TestRPackages extends TestBase {
         }
     }
 
+    protected static void setupInstallTestPackages(String[] testPackages) {
+        setupInstallTestPackages(testPackages, new Resolver());
+    }
+
     protected static void setupInstallTestPackages(String[] testPackages, Resolver resolver) {
         if (!checkOnly()) {
+            assert installedPackages == null && TestRPackages.resolver == null : "inconsistent calls to setupInstallTestPackages / tearDownUninstallTestPackages " + installedPackages + " " + resolver;
+            TestRPackages.installedPackages = testPackages;
+            TestRPackages.resolver = resolver;
+            TestRPackages.needsInstall = true;
+        }
+    }
+
+    @Override
+    public void beforeEval() {
+        if (needsInstall) {
+            needsInstall = false;
+
             TestBase.deleteDir(installDir());
             installDir().toFile().mkdirs();
             System.out.printf(".begin install.");
-            for (String p : testPackages) {
+            for (String p : installedPackages) {
                 // Takes time, provide user feedback
                 System.out.printf(".pkg: %s.", p);
                 PackagePath packagePath = getPackagePaths(p, resolver.getPath(p));
@@ -181,13 +197,18 @@ public abstract class TestRPackages extends TestBase {
         }
     }
 
-    protected static void tearDownUninstallTestPackages(String[] testPackages) {
+    protected static void tearDownUninstallTestPackages() {
         if (!checkOnly()) {
-            for (String p : testPackages) {
-                if (!uninstallPackage(p)) {
-                    System.err.println("WARNING: error deleting package: " + p);
+            assert installedPackages != null && resolver != null : "inconsistent calls to setupInstallTestPackages / tearDownUninstallTestPackages";
+            if (!needsInstall) {
+                for (String p : installedPackages) {
+                    if (!uninstallPackage(p)) {
+                        System.err.println("WARNING: error deleting package: " + p);
+                    }
                 }
             }
+            installedPackages = null;
+            resolver = null;
         }
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java
index 53d8d460ccb9cb1fe5e8635d63be7cf4eb1f1ce2..04ab1ce911c96d09bfd1a741d56a6625b3bd295f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,7 +78,7 @@ public class TestRecommendedPackages extends TestRPackages {
 
     @AfterClass
     public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages(packages);
+        tearDownUninstallTestPackages();
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java
index ce2a48e598f43e587aa819f422e5eecaa44beb15..5843ad45da8f693c315df98ad880aaa92e348ad4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@ public class TestS4TestPackage extends TestRPackages {
 
     @AfterClass
     public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages(TEST_PACKAGES);
+        tearDownUninstallTestPackages();
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java
index 7bd9ce16caef3b0c1edee6585f1dbd04d4e6f303..637377fa32eb74183e6864bb203e9d52eb699206 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java
@@ -42,7 +42,7 @@ public class TestVanillaPackage extends TestRPackages {
 
     @AfterClass
     public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages(TEST_PACKAGES);
+        tearDownUninstallTestPackages();
     }
 
     @Test
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index fbba58aff015a9320c03f816472756010c44622c..0e4d84ad26a1d5e719b8dee1f5cb939e4b501786 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -405,8 +405,11 @@ def _test_package():
 def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
+def _simple_generated_unit_tests():
+    return ','.join(map(_test_subpackage, ['library.base', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data']))
+
 def _simple_unit_tests():
-    return ','.join(map(_test_subpackage, ['library.base', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'tck', 'parser', 'S4', 'rng', 'runtime.data']))
+    return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
 
 def _package_unit_tests():
     return ','.join(map(_test_subpackage, ['rffi', 'rpackages']))
@@ -426,10 +429,13 @@ def _gate_unit_tests():
 def _all_unit_tests():
     return _gate_unit_tests()
 
+def _all_generated_unit_tests():
+    return ','.join([_simple_generated_unit_tests(), _package_unit_tests()])
+
 def testgen(args):
     '''generate the expected output for unit tests, and All/Failing test classes'''
     parser = ArgumentParser(prog='r testgen')
-    parser.add_argument('--tests', action='store', default=_all_unit_tests(), help='pattern to match test classes')
+    parser.add_argument('--tests', action='store', default=_all_generated_unit_tests(), help='pattern to match test classes')
     args = parser.parse_args(args)
     # check we are in the home directory
     if os.getcwd() != _fastr_suite.dir: