diff --git a/SAS/OTDB_Services/TreeStatusEvents.py b/SAS/OTDB_Services/TreeStatusEvents.py
index d6589a99126bc0d526d497a5d8b654e44f150a2f..064e42451644740f89153c9dfbe05fb87b36c654 100755
--- a/SAS/OTDB_Services/TreeStatusEvents.py
+++ b/SAS/OTDB_Services/TreeStatusEvents.py
@@ -98,7 +98,7 @@ def main():
 
     create_service(options.busname, dbcreds)
 
-def create_service(busname, dbcreds):
+def create_service(busname, dbcreds, state_file_path='~/.lofar/otdb_treestatusevent_state'):
     alive = True
     connected = False
     otdb_connection = None
@@ -124,7 +124,7 @@ def create_service(busname, dbcreds):
             if connected:
                 # Get start_time (= creation time of last retrieved record if any)
                 try:
-                    treestatuseventfilename = os.path.expanduser('~/.lofar/otdb_treestatusevent_state')
+                    treestatuseventfilename = os.path.expanduser(state_file_path)
                     with open(treestatuseventfilename, 'r') as f:
                         line = f.readline()
                         if line.rfind('.') > 0:
diff --git a/SAS/OTDB_Services/test/CMakeLists.txt b/SAS/OTDB_Services/test/CMakeLists.txt
index 279c28690e825ae4b41dca0b4a85b5c51636e2d1..638cc329d86cd972c6745f1bcf56f70c53a7c345 100644
--- a/SAS/OTDB_Services/test/CMakeLists.txt
+++ b/SAS/OTDB_Services/test/CMakeLists.txt
@@ -1,10 +1,19 @@
 # $Id: CMakeLists.txt 1576 2015-09-29 15:22:28Z loose $
 
-include(LofarCTest)
+if(BUILD_TESTING)
+    include(LofarCTest)
+
+    include(FindPythonModule)
+    find_python_module(dateutil)
+
+    include(PythonInstall)
+    python_install(otdb_common_testing.py DESTINATION lofar/sas/otdb/testing)
+
+
+    lofar_add_test(t_TreeService)
+    lofar_add_test(t_TreeStatusEvents)
+endif()
+
 
-lofar_find_package(Python 3.4 REQUIRED)
-find_python_module(testing.postgresql)
 
-lofar_add_test(t_TreeService)
-lofar_add_test(t_TreeStatusEvents)
 
diff --git a/SAS/OTDB_Services/test/otdb_common_testing.py b/SAS/OTDB_Services/test/otdb_common_testing.py
new file mode 100755
index 0000000000000000000000000000000000000000..bc2caa098ef871ba37a634f8b45dd1313c14e67c
--- /dev/null
+++ b/SAS/OTDB_Services/test/otdb_common_testing.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2012-2015    ASTRON (Netherlands Institute for Radio Astronomy)
+# P.O. Box 2, 7990 AA Dwingeloo, The Netherlands
+#
+# This file is part of the LOFAR software suite.
+# The LOFAR software suite is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# The LOFAR software suite is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
+
+# $Id$
+import subprocess
+import os
+import logging
+
+logger = logging.getLogger(__name__)
+
+from lofar.common.testing.postgres import PostgresTestMixin
+
+class OTDBCommonTestMixin(PostgresTestMixin):
+    '''
+    A common test mixin class from which you can derive to get a freshly setup postgres testing instance with the latest OTDB sql setup scripts applied.
+    '''
+    gzipped_schema_dump_filename = ''
+
+    @classmethod
+    def apply_database_schema(cls):
+        logger.info('applying OTDB sql schema to %s', cls.dbcreds)
+
+        cmd1 = ['gzip', '-dc', cls.gzipped_schema_dump_filename]
+
+        cmd2 = ['psql', '-U', cls.dbcreds.user, '-h', cls.dbcreds.host,
+                '-p', str(cls.dbcreds.port), cls.dbcreds.database]
+
+        logger.info('executing: %s', ' '.join(cmd1))
+        logger.info('executing: %s', ' '.join(cmd2))
+
+        proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE)
+        proc2 = subprocess.Popen(cmd2, stdin=proc1.stdout)
+        proc1.wait(timeout=60)
+        proc2.wait(timeout=60)
+
+        if proc1.returncode != 0:
+            raise RuntimeError("Could not execute cmd: '%s' error=%s" % (' '.join(cmd1), proc1.stderr))
+
+        if proc2.returncode != 0:
+            raise RuntimeError("Could not execute cmd: '%s' error=%s" % (' '.join(cmd2), proc2.stderr))
+
+
+class OTDBTestInstance():
+    '''Helper class which uses the OTDBCommonTestMixin without a unittest.TestCase to setup/teardown a test OTDB instance'''
+    def __init__(self, gzipped_schema_dump_filename):
+        OTDBCommonTestMixin.gzipped_schema_dump_filename = gzipped_schema_dump_filename
+        self._db_creator = OTDBCommonTestMixin()
+
+    @property
+    def db(self):
+        return self._db_creator.db
+
+    @property
+    def dbcreds(self):
+        return self._db_creator.dbcreds
+
+    def __enter__(self):
+        try:
+            self._db_creator.setUpClass()
+            return self
+        except Exception as e:
+            logger.error(e)
+            self._db_creator.tearDownClass()
+            raise
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self._db_creator.tearDownClass()
+
diff --git a/SAS/OTDB_Services/test/t_TreeService.py b/SAS/OTDB_Services/test/t_TreeService.py
index 598fa2c1c9dc0422099d004a6bf1dc52cd8a11a6..02070ccdb8f89b7ae88dfafbe103695d2924598d 100644
--- a/SAS/OTDB_Services/test/t_TreeService.py
+++ b/SAS/OTDB_Services/test/t_TreeService.py
@@ -28,49 +28,15 @@ KeyUpdateCommand        : function to update the value of multiple (existing) ke
 StatusUpdateCommand     : finction to update the status of a tree.
 """
 
-import logging
-import testing.postgresql
-import psycopg2
-import subprocess
 from lofar.sas.otdb.TreeService import create_service
-from lofar.common.dbcredentials import Credentials
-from lofar.messaging import TemporaryExchange, RPCClient
+from lofar.messaging import TemporaryExchange, RPCClient, BusListenerJanitor
+from lofar.sas.otdb.testing.otdb_common_testing import OTDBTestInstance
 
-logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
+import logging
 logger = logging.getLogger(__name__)
+logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
 
-try:
-    postgresql = testing.postgresql.PostgresqlFactory()()
-
-    database_credentials = Credentials()
-    database_credentials.host = postgresql.dsn()['host']
-    database_credentials.database = postgresql.dsn()['database']
-    database_credentials.port = postgresql.dsn()['port']
-
-    # connect to test-db as root
-    conn = psycopg2.connect(**postgresql.dsn())
-    cursor = conn.cursor()
-
-    # set credentials to be used during tests
-    database_credentials.user = 'otdb_test_user'
-    database_credentials.password = 'otdb_test_password'  # cannot be empty...
-
-    # create user role
-    query = "CREATE USER %s WITH SUPERUSER PASSWORD '%s'" % (database_credentials.user, database_credentials.password)
-    cursor.execute(query)
-    conn.commit()
-    conn.close()
-
-    cmd1 = ['gzip', '-dc', 't_TreeService.in.unittest_db.dump.gz']
-
-    cmd2 = ['psql', '-U', database_credentials.user, '-h', database_credentials.host,
-            '-p', str(database_credentials.port), database_credentials.database]
-
-    proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE)
-    proc2 = subprocess.Popen(cmd2, stdin=proc1.stdout)
-    proc1.wait(timeout=60)
-    proc2.wait(timeout=60)
-
+with OTDBTestInstance('t_TreeService.in.unittest_db.dump.gz') as test_db:
     def do_rpc_catch_exception(exc_text, rpc_instance, method_name, arg_dict):
         try:
             print("** Executing {0}({1})...".format(method_name, arg_dict))
@@ -90,7 +56,7 @@ try:
     with TemporaryExchange(__name__) as tmp_exchange:
         exchange = tmp_exchange.address
 
-        with create_service(exchange=exchange, dbcreds=database_credentials) as service:
+        with BusListenerJanitor(create_service(exchange=exchange, dbcreds=test_db.dbcreds)) as service:
 
             with RPCClient(service_name=service.service_name, exchange=exchange, timeout=10) as otdbRPC:    # Existing: otdb_id:1099268, mom_id:353713
                 do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 1099268, 'MomID': 353713 })
@@ -190,5 +156,3 @@ try:
                 do_rpc_catch_exception('on invalid key', otdbRPC, "TaskSetSpecification", {'OtdbID':1099266,
                        'Specification':{'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.NoSuchKey':'NameOfTestHost'}})
 
-finally:
-    postgresql.stop()
diff --git a/SAS/OTDB_Services/test/t_TreeStatusEvents.py b/SAS/OTDB_Services/test/t_TreeStatusEvents.py
index 0b070818a72eaa82b7a11afa068d022809d9d91c..884a29b3fbcd5c875f7b51dea0b69ff8708cc688 100644
--- a/SAS/OTDB_Services/test/t_TreeStatusEvents.py
+++ b/SAS/OTDB_Services/test/t_TreeStatusEvents.py
@@ -28,69 +28,33 @@ KeyUpdateCommand        : function to update the value of multiple (existing) ke
 StatusUpdateCommand     : finction to update the status of a tree.
 """
 
-import sys, pg
-import logging
-import testing.postgresql
-import psycopg2
-import subprocess
 from lofar.messaging.messagebus import *
 from lofar.sas.otdb.TreeStatusEvents import create_service
-from lofar.common.dbcredentials import Credentials
 import threading
+import sys
 
-logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
+import logging
 logger = logging.getLogger(__name__)
+logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
 
-try:
-    postgresql = testing.postgresql.PostgresqlFactory()()
-
-    database_credentials = Credentials()
-    database_credentials.host = postgresql.dsn()['host']
-    database_credentials.database = postgresql.dsn()['database']
-    database_credentials.port = postgresql.dsn()['port']
-
-    # connect to test-db as root
-    conn = psycopg2.connect(**postgresql.dsn())
-    cursor = conn.cursor()
-
-    # set credentials to be used during tests
-    database_credentials.user = 'otdb_test_user'
-    database_credentials.password = 'otdb_test_password'  # cannot be empty...
-
-    # create user role
-    query = "CREATE USER %s WITH SUPERUSER PASSWORD '%s'" % (database_credentials.user, database_credentials.password)
-    cursor.execute(query)
-    conn.commit()
-    conn.close()
-
-    cmd1 = ['gzip', '-dc', 't_TreeStatusEvents.in.unittest_db.dump.gz']
-
-    cmd2 = ['psql', '-U', database_credentials.user, '-h', database_credentials.host,
-            '-p', str(database_credentials.port), database_credentials.database]
-
-    proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE)
-    proc2 = subprocess.Popen(cmd2, stdin=proc1.stdout)
-    proc1.wait(timeout=60)
-    proc2.wait(timeout=60)
-
-    otdb_connection = pg.connect(**database_credentials.pg_connect_options())
+from lofar.sas.otdb.testing.otdb_common_testing import OTDBTestInstance
 
+with OTDBTestInstance('t_TreeStatusEvents.in.unittest_db.dump.gz') as test_db:
     with TemporaryExchange(__name__) as tmp_exchange:
-        with TemporaryQueue(__name__, exchange=tmp_exchange.address) as tmp_queue:
+        with tmp_exchange.create_temporary_queue() as tmp_queue:
             with tmp_queue.create_frombus() as frombus:
 
-                t = threading.Thread(target=create_service, args=(tmp_exchange.address, database_credentials))
+                t = threading.Thread(target=create_service, args=(tmp_exchange.address, test_db.dbcreds, '/dev/nullz'))
                 t.daemon = True
                 t.start()
 
-                otdb_connection.query("select setTreeState(1, %d, %d::INT2,'%s')" % (1099266, 500, False))
-                msg = frombus.receive(timeout=5, acknowledge=True)	  # TreeStateEVent are send every 2 seconds
+                test_db.db.executeQuery("select setTreeState(1, %d, %d::INT2,'%s'::boolean);" % (1099266, 500, False))
+                test_db.db.commit()
+
+                msg = frombus.receive(timeout=500, acknowledge=True)	  # TreeStateEvent are send every 2 seconds
                 logger.info(msg)
                 try:
                     ok = (msg.content['treeID'] == 1099266 and msg.content['state'] == 'queued')
                 except IndexError:
                     ok = False
     sys.exit(not ok)   # 0 = success
-
-finally:
-    postgresql.stop()