diff --git a/slapos/recipe/erp5/__init__.py b/slapos/recipe/erp5/__init__.py
index 39e3f608702653e8c5548cbe2a22500c71c2d072..fa09ec6c011e8f4868bc5de59b4d23f66dc13a63 100644
--- a/slapos/recipe/erp5/__init__.py
+++ b/slapos/recipe/erp5/__init__.py
@@ -90,10 +90,10 @@ class Recipe(BaseSlapRecipe):
         certificate=frontend_certificate)
 
 
-    self.installTestRunner(ca_conf, mysql_conf, conversion_server_conf,
-                           memcached_conf, kumo_conf)
-    self.installTestSuiteRunner(ca_conf, mysql_conf, conversion_server_conf,
-                           memcached_conf, kumo_conf)
+#    self.installTestRunner(ca_conf, mysql_conf, conversion_server_conf,
+#                           memcached_conf, kumo_conf)
+#    self.installTestSuiteRunner(ca_conf, mysql_conf, conversion_server_conf,
+#                           memcached_conf, kumo_conf)
     self.linkBinary()
     connection_dict.update(**dict(
       site_user=user,
@@ -130,83 +130,6 @@ class Recipe(BaseSlapRecipe):
                 sphinx_searchd_port=port,
                 sphinx_searchd_sql_port=sql_port)
 
-  def installTestRunner(self, ca_conf, mysql_conf, conversion_server_conf,
-                        memcached_conf, kumo_conf):
-    """Installs bin/runUnitTest executable to run all tests using
-       bin/runUnitTest"""
-    testinstance = self.createDataDirectory('testinstance')
-    # workaround wrong assumptions of ERP5Type.tests.runUnitTest about
-    # directory existence
-    unit_test = os.path.join(testinstance, 'unit_test')
-    connection_string_list = []
-    for test_database, test_user, test_password in \
-          mysql_conf['mysql_parallel_test_dict'][-4:]:
-      connection_string_list.append(
-          '%s@%s:%s %s %s' % (test_database, mysql_conf['ip'],
-                            mysql_conf['tcp_port'], test_user, test_password))
-    if not os.path.isdir(unit_test):
-      os.mkdir(unit_test)
-    runUnitTest = zc.buildout.easy_install.scripts([
-      ('runUnitTest', __name__ + '.testrunner', 'runUnitTest')],
-      self.ws, sys.executable, self.bin_directory, arguments=[dict(
-        instance_home=testinstance,
-        prepend_path=self.bin_directory,
-        openssl_binary=self.options['openssl_binary'],
-        test_ca_path=ca_conf['certificate_authority_path'],
-        call_list=[self.options['runUnitTest_binary'],
-          '--erp5_sql_connection_string', '%(mysql_test_database)s@%'
-          '(ip)s:%(tcp_port)s %(mysql_test_user)s '
-          '%(mysql_test_password)s' % mysql_conf,
-          '--extra_sql_connection_string_list',','.join(connection_string_list),
-          '--conversion_server_hostname=%(conversion_server_ip)s' % \
-                                                         conversion_server_conf,
-          '--conversion_server_port=%(conversion_server_port)s' % \
-                                                         conversion_server_conf,
-          '--volatile_memcached_server_hostname=%(memcached_ip)s' % memcached_conf,
-          '--volatile_memcached_server_port=%(memcached_port)s' % memcached_conf,
-          '--persistent_memcached_server_hostname=%(kumo_gateway_ip)s' % kumo_conf,
-          '--persistent_memcached_server_port=%(kumo_gateway_port)s' % kumo_conf,
-      ]
-        )])[0]
-    self.path_list.append(runUnitTest)
-
-  def installTestSuiteRunner(self, ca_conf, mysql_conf, conversion_server_conf,
-                        memcached_conf, kumo_conf):
-    """Installs bin/runTestSuite executable to run all tests using
-       bin/runUnitTest"""
-    testinstance = self.createDataDirectory('test_suite_instance')
-    # workaround wrong assumptions of ERP5Type.tests.runUnitTest about
-    # directory existence
-    unit_test = os.path.join(testinstance, 'unit_test')
-    if not os.path.isdir(unit_test):
-      os.mkdir(unit_test)
-    connection_string_list = []
-    for test_database, test_user, test_password in \
-        mysql_conf['mysql_parallel_test_dict']:
-      connection_string_list.append(
-          '%s@%s:%s %s %s' % (test_database, mysql_conf['ip'],
-                              mysql_conf['tcp_port'], test_user, test_password))
-    command = zc.buildout.easy_install.scripts([
-      ('runTestSuite', __name__ + '.test_suite_runner', 'runTestSuite')],
-      self.ws, sys.executable, self.bin_directory, arguments=[dict(
-        instance_home=testinstance,
-        prepend_path=self.bin_directory,
-        openssl_binary=self.options['openssl_binary'],
-        test_ca_path=ca_conf['certificate_authority_path'],
-        call_list=[self.options['runTestSuite_binary'],
-          '--db_list', ','.join(connection_string_list),
-          '--conversion_server_hostname=%(conversion_server_ip)s' % \
-                                                         conversion_server_conf,
-          '--conversion_server_port=%(conversion_server_port)s' % \
-                                                         conversion_server_conf,
-          '--volatile_memcached_server_hostname=%(memcached_ip)s' % memcached_conf,
-          '--volatile_memcached_server_port=%(memcached_port)s' % memcached_conf,
-          '--persistent_memcached_server_hostname=%(kumo_gateway_ip)s' % kumo_conf,
-          '--persistent_memcached_server_port=%(kumo_gateway_port)s' % kumo_conf,
-      ]
-        )])[0]
-    self.path_list.append(command)
-
   def installFrontendZopeApache(self, ip, port, name, frontend_path, backend_url,
       backend_path, key, certificate, access_control_string=None):
     ident = 'frontend_' + name
diff --git a/slapos/recipe/erp5_test/__init__.py b/slapos/recipe/erp5_test/__init__.py
index 94db783585c0a75e73096d946e2778b20335e910..936c414b7e062fc3397c7f6b30649ae667a1d156 100644
--- a/slapos/recipe/erp5_test/__init__.py
+++ b/slapos/recipe/erp5_test/__init__.py
@@ -25,7 +25,80 @@
 #
 ##############################################################################
 from slapos.recipe.librecipe import GenericBaseRecipe
+import urlparse
 
 class Recipe(GenericBaseRecipe):
   def install(self):
-    pass
+    testinstance = self.options['test-instance-path']
+    mysql_connection_string_list = []
+    path_list = []
+    # XXX: assume existence of 100 test databases, because slaves are not
+    # functional yet in slapos: test_0...test_100, with same user name
+    mysql_template = "%s@%s:%s %s %s"
+    mysql_parsed = urlparse.urlparse(self.options['mysql-url'])
+    for i in range(0, 100):
+      mysql_connection_string_list.append(mysql_template % ('test_%s'% i,
+        mysql_parsed.hostname, mysql_parsed.port, 'test_%s'% i, mysql_parsed.password))
+    mysql_connection_string = mysql_template % ('erp5_test', mysql_parsed.hostname,
+      mysql_parsed.port, 'erp5_test', mysql_parsed.password)
+    cloudooo_parsed = urlparse.urlparse(self.options['cloudooo-url'])
+    memcached_parsed = urlparse.urlparse(self.options['memcached-url'])
+    kumofs_parsed = urlparse.urlparse(self.options['kumofs-url'])
+    path_list.append(self.createPythonScript(self.options['run-unit-test'],
+        __name__ + '.test.runUnitTest', [dict(
+        instance_home=testinstance,
+        prepend_path=self.options['prepend-path'],
+        openssl_binary=self.options['openssl-binary'],
+        test_ca_path=self.options['certificate-authority-path'],
+        call_list=[self.options['run-unit-test-binary'],
+          '--erp5_sql_connection_string', mysql_connection_string,
+          '--extra_sql_connection_string_list', ','.join(
+            mysql_connection_string_list),
+          '--conversion_server_hostname=%s' % cloudooo_parsed.hostname,
+          '--conversion_server_port=%s' % cloudooo_parsed.port,
+          '--volatile_memcached_server_hostname=%s' % memcached_parsed.hostname,
+          '--volatile_memcached_server_port=%s' % memcached_parsed.port,
+          '--persistent_memcached_server_hostname=%s' % kumofs_parsed.hostname,
+          '--persistent_memcached_server_port=%s' % kumofs_parsed.port,
+      ])]))
+
+    return path_list
+
+#  def installTestSuiteRunner(self, ca_conf, mysql_conf, conversion_server_conf,
+#                        memcached_conf, kumo_conf):
+#    """Installs bin/runTestSuite executable to run all tests using
+#       bin/runUnitTest"""
+#    testinstance = self.createDataDirectory('test_suite_instance')
+#    # workaround wrong assumptions of ERP5Type.tests.runUnitTest about
+#    # directory existence
+#    unit_test = os.path.join(testinstance, 'unit_test')
+#    if not os.path.isdir(unit_test):
+#      os.mkdir(unit_test)
+#    mysql_connection_string_list = []
+#    for test_database, test_user, test_password in \
+#        mysql_conf['mysql_parallel_test_dict']:
+#      mysql_connection_string_list.append(
+#          '%s@%s:%s %s %s' % (test_database, mysql_conf['ip'],
+#                              mysql_conf['tcp_port'], test_user, test_password))
+#    command = zc.buildout.easy_install.scripts([
+#      ('runTestSuite', __name__ + '.test_suite_runner', 'runTestSuite')],
+#      self.ws, sys.executable, self.bin_directory, arguments=[dict(
+#        instance_home=testinstance,
+#        prepend_path=self.bin_directory,
+#        openssl_binary=self.options['openssl_binary'],
+#        test_ca_path=ca_conf['certificate_authority_path'],
+#        call_list=[self.options['runTestSuite_binary'],
+#          '--db_list', ','.join(mysql_connection_string_list),
+#          '--conversion_server_hostname=%(conversion_server_ip)s' % \
+#                                                         conversion_server_conf,
+#          '--conversion_server_port=%(conversion_server_port)s' % \
+#                                                         conversion_server_conf,
+#          '--volatile_memcached_server_hostname=%(memcached_ip)s' % memcached_conf,
+#          '--volatile_memcached_server_port=%(memcached_port)s' % memcached_conf,
+#          '--persistent_memcached_server_hostname=%(kumo_gateway_ip)s' % kumo_conf,
+#          '--persistent_memcached_server_port=%(kumo_gateway_port)s' % kumo_conf,
+#      ]
+#        )])[0]
+#    self.path_list.append(command)
+
+
diff --git a/software/erp5/instance-erp5-development.cfg b/software/erp5/instance-erp5-development.cfg
index 63131521f84bec73acc28436d48d2448ff390039..949f60b29c4a7191f4f3a1810e5afaf7369f5a19 100644
--- a/software/erp5/instance-erp5-development.cfg
+++ b/software/erp5/instance-erp5-development.cfg
@@ -13,6 +13,7 @@ parts +=
   request-kumofs
   basedirectory
   erp5-update
+  test-runner
 
 eggs-directory = ${buildout:eggs-directory}
 develop-eggs-directory = ${buildout:develop-eggs-directory}
@@ -22,6 +23,42 @@ offline = true
 # default site id
 site-id = erp5
 
+[test-runner]
+recipe = slapos.cookbook:erp5.test
+certificate-authority-path = $${test-certificate-authority:ca-dir}
+mysql-url = $${request-mariadb:connection-url}
+kumofs-url = $${request-kumofs:connection-url}
+memcached-url = $${request-memcached:connection-url}
+cloudooo-url = $${request-cloudooo:connection-url}
+test-instance-path = $${directory:unit-test-path}
+
+prepend-path = $${buildout:bin-directory}
+run-unit-test = $${buildout:bin-directory}/runUnitTest
+run-test-suite = $${buildout:bin-directory}/runTestSuite
+
+openssl-binary = $${test-certificate-authority:openssl-binary}
+run-unit-test-binary = ${buildout:bin-directory}/runUnitTest
+run-test-suite-binary = ${buildout:bin-directory}/runTestSuite
+
+[test-certificate-authority]
+recipe = slapos.cookbook:certificate_authority
+openssl-binary = ${openssl:location}/bin/openssl
+ca-dir = $${directory:test-ca-dir}
+requests-directory = $${test-cadirectory:requests}
+wrapper = $${basedirectory:services}/test-ca
+ca-private = $${test-cadirectory:private}
+ca-certs = $${test-cadirectory:certs}
+ca-newcerts = $${test-cadirectory:newcerts}
+ca-crl = $${test-cadirectory:crl}
+
+[test-cadirectory]
+recipe = slapos.cookbook:mkdirectory
+requests = $${directory:test-ca-dir}/requests/
+private = $${directory:test-ca-dir}/private/
+certs = $${directory:test-ca-dir}/certs/
+newcerts = $${directory:test-ca-dir}/newcerts/
+crl = $${directory:test-ca-dir}/crl/
+
 [erp5-update]
 recipe = slapos.cookbook:erp5.update
 
@@ -83,3 +120,7 @@ services = $${rootdirectory:etc}/run/
 recipe = slapos.cookbook:mkdirectory
 etc = $${buildout:directory}/etc/
 
+[directory]
+test-ca-dir = $${rootdirectory:srv}/test-ca/
+test-instance-path = $${rootdirectory:srv}/test-instance/
+unit-test-path = $${:test-instance-path}/unit_test/
diff --git a/software/erp5/instance.cfg b/software/erp5/instance.cfg
index 3a9be87adb1b7bcc19d2838ecaa4e2122d88cc0f..052e05c817264b32c7d1c082cbd8c4572061032c 100644
--- a/software/erp5/instance.cfg
+++ b/software/erp5/instance.cfg
@@ -1,7 +1,5 @@
 [instance]
 rdiff_backup_binary = ${buildout:bin-directory}/rdiff-backup
-runTestSuite_binary = ${buildout:bin-directory}/runTestSuite
-runUnitTest_binary = ${buildout:bin-directory}/runUnitTest
 sphinx_searchd_binary = ${sphinx:location}/bin/searchd
 
 [buildout]
diff --git a/software/erp5/software.cfg b/software/erp5/software.cfg
index d95e3b4dcfe9d72720fdcf895cab83361bdd8313..b7dcf2e28ad7c75eaf6477e51fbbc5562cf430fa 100644
--- a/software/erp5/software.cfg
+++ b/software/erp5/software.cfg
@@ -46,7 +46,7 @@ mode = 0644
 [template]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance.cfg
-md5sum = 5a8d8751d715eee6f98102328948f44b
+md5sum = 23f40eb3a9a51c4fcd2acd4270cfe626
 output = ${buildout:directory}/template.cfg
 mode = 0644
 
@@ -60,7 +60,7 @@ mode = 0644
 [template-erp5-development]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance-erp5-development.cfg
-md5sum = 97670f46ef45f1314ed03a71df56de4d
+md5sum = 79216b0c413b373b0dbe00220a0fbaf9
 output = ${buildout:directory}/template-erp5-development.cfg
 mode = 0644