diff --git a/product/ERP5Type/Tool/ClassTool.py b/product/ERP5Type/Tool/ClassTool.py
index 79a4ceb000d2d5a35430a29a6fe964a34ecd93e3..cc09103d0959b7d6c030bad4f4a07a4aa658a50d 100644
--- a/product/ERP5Type/Tool/ClassTool.py
+++ b/product/ERP5Type/Tool/ClassTool.py
@@ -37,6 +37,7 @@ from Products.CMFCore.utils import UniqueObject
 
 import OFS
 import transaction
+from cStringIO import StringIO
 from zExceptions import BadRequest
 from zExceptions import Unauthorized
 from Acquisition import Implicit
@@ -72,6 +73,8 @@ import Products
 
 from zLOG import LOG, WARNING
 
+global_stream = None
+
 """
   ClassTool allows to create classes from the ZMI using code templates.
   ZMI-created classes can then be edited again.
@@ -1186,6 +1189,19 @@ def initialize( context ):
         writeLocalConstraint(class_id, text, create=create,
                              instance_home=self._v_instance_home.getPath())
 
+      security.declareProtected(Permissions.ManagePortal, 'runLiveTest')
+      def readTestOutput(self, position=0):
+        """
+        Return unread part of the test result
+        """
+        result = ''
+        position = int(position)
+        global global_stream
+        if global_stream is not None:
+          global_stream.seek(position)
+          result = global_stream.read()
+        return result
+
       security.declareProtected(Permissions.ManagePortal, 'runLiveTest')
       def runLiveTest(self, test_list=[], run_only=None, debug=None,
                       verbose=False):
@@ -1200,8 +1216,13 @@ def initialize( context ):
         """
         path = os.path.join(getConfiguration().instancehome, 'tests')
         verbosity = verbose and 2 or 1
-        return runLiveTest(test_list, run_only=run_only, debug=debug, path=path,
-                           verbosity=verbosity)
+        instance_home = getConfiguration().instancehome
+        global global_stream
+        global_stream = StringIO()
+        result = runLiveTest(test_list, run_only=run_only, debug=debug, path=path,
+                           stream=global_stream, verbosity=verbosity)
+        global_stream.seek(0)
+        return global_stream.read()
 
       def getProductList(self):
         """ List all products """
diff --git a/product/ERP5Type/tests/ERP5TypeLiveTestCase.py b/product/ERP5Type/tests/ERP5TypeLiveTestCase.py
index 169b7353dd52eb293b5348ed3711febec8503921..edc5b52a6203a9d51934d3340648c481e31e855b 100644
--- a/product/ERP5Type/tests/ERP5TypeLiveTestCase.py
+++ b/product/ERP5Type/tests/ERP5TypeLiveTestCase.py
@@ -444,7 +444,7 @@ class ERP5TypeLiveTestCase(ProcessingNodeTestCase, PortalTestCase):
 
         return ResponseWrapper(response, outstream, path)
 
-def runLiveTest(test_list, verbosity=1, **kw):
+def runLiveTest(test_list, verbosity=1, stream=None, **kw):
   from Products.ERP5Type.tests.runUnitTest import DebugTestResult
   from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
   from Products.ERP5Type.tests import backportUnittest
@@ -472,9 +472,8 @@ def runLiveTest(test_list, verbosity=1, **kw):
     ERP5TypeTestLoader.filter_test_list = [re.compile(x).search
                                             for x in run_only.split(',')]
   suite = ERP5TypeTestLoader().loadTestsFromNames(test_list)
-  stream = StringIO()
-  output = StringIO()
+  output = stream
+  if stream is None:
+    output = StringIO()
   output.write("**Running Live Test:\n")
   result = TestRunner(stream=output, verbosity=verbosity).run(suite)
-  output.write(stream.getvalue())
-  return output.getvalue()