diff --git a/LCS/PyCommon/test/t_cep4_utils.py b/LCS/PyCommon/test/t_cep4_utils.py
index 63a0744aa5f711c3f92f4d85fd78c6724d550c38..9de56861165f5b4bf8013282eaa2c38c5bb79b14 100755
--- a/LCS/PyCommon/test/t_cep4_utils.py
+++ b/LCS/PyCommon/test/t_cep4_utils.py
@@ -22,25 +22,34 @@ from subprocess import call
 
 import logging
 from lofar.common.cep4_utils import *
-from lofar.common.test_utils import unit_test
+from lofar.common.test_utils import integration_test
 
 logger = logging.getLogger(__name__)
 
+@integration_test
 class TestCep4Utils(unittest.TestCase):
 
-    @unit_test
+    def setUpClass(self):
+        try:
+            cep4_true_cmd = wrap_command_in_cep4_head_node_ssh_call(['true'])
+            if call(cep4_true_cmd) == 0:
+                logger.info('We can reach the CEP4 head node. Continuing with tests...')
+            else:
+                logger.warning('Cannot reach the CEP4 head node. skipping tests...')
+                raise unittest.SkipTest('Cannot reach the CEP4 head node. skipping tests...')
+        except:
+            raise unittest.SkipTest('Cannot reach the CEP4 head node. skipping tests...')
+
     def test_01_wrap_command_in_cep4_head_node_ssh_call(self):
         cmd = wrap_command_in_cep4_head_node_ssh_call(['true'])
         logger.info('executing command: %s', ' '.join(cmd))
         self.assertEqual(0, call(cmd))
 
-    @unit_test
     def test_02_get_cep4_available_cpu_nodes(self):
         node_nrs = get_cep4_available_cpu_nodes()
         self.assertTrue(isinstance(node_nrs, list))
         self.assertTrue(len(node_nrs) > 0)
 
-    @unit_test
     def test_03_wrap_command_in_cep4_random_cpu_node_ssh_call(self):
         '''
         this test calls and tests the functionality of the following methods via
@@ -50,7 +59,6 @@ class TestCep4Utils(unittest.TestCase):
         logger.info('executing command: %s', ' '.join(cmd))
         self.assertEqual(0, call(cmd))
 
-    @unit_test
     def test_04_wrap_command_in_cep4_available_cpu_node_with_lowest_load_ssh_call(self):
         '''
         this test calls and tests the functionality of the following methods via
@@ -62,7 +70,6 @@ class TestCep4Utils(unittest.TestCase):
         logger.info('executing command: %s', ' '.join(cmd))
         self.assertEqual(0, call(cmd))
 
-    @unit_test
     def test_05_wrap_command_for_docker_in_cep4_head_node_ssh_call(self):
         '''
         this test calls and tests the functionality of wrap_command_for_docker and
@@ -75,7 +82,6 @@ class TestCep4Utils(unittest.TestCase):
         logger.info('executing command: %s', ' '.join(cmd))
         self.assertEqual(0, call(cmd))
 
-    @unit_test
     def test_06_get_slurm_info_from_within_docker_via_cep4_head(self):
         '''
         test to see if we can execute a command via ssh on the head node,
@@ -98,18 +104,4 @@ class TestCep4Utils(unittest.TestCase):
 if __name__ == '__main__':
     logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.DEBUG)
 
-    # first try if we can reach cep4
-    # this assumes the code in wrap_command_in_cep4_head_node_ssh_call is correct and working
-    # (which is also being tested in the unittests)
-    # if and only if the command to the head node succeeds, then we can do the tests
-    # otherwise, for whatever reason the ssh call fails, we skip the tests because we cannot reach cep4 head node.
-    cep4_true_cmd = wrap_command_in_cep4_head_node_ssh_call(['true'])
-
-    if call(cep4_true_cmd) == 0:
-        logger.info('We can reach the CEP4 head node. Continuing with tests...')
-        unittest.main()
-    else:
-        logger.warning('Cannot reach the CEP4 head node. skipping tests...')
-        #exit with special 'skipped' exit-code
-        exit(3)
-
+    unittest.main()
diff --git a/SAS/DataManagement/Cleanup/CleanupService/test/test_cleanup_service_and_rpc.py b/SAS/DataManagement/Cleanup/CleanupService/test/test_cleanup_service_and_rpc.py
index 35b2ef8228f370bdbad63fe97b5b3fc1abf75f9a..5e28031cec8909f04098279fd098750f79c9a1c6 100755
--- a/SAS/DataManagement/Cleanup/CleanupService/test/test_cleanup_service_and_rpc.py
+++ b/SAS/DataManagement/Cleanup/CleanupService/test/test_cleanup_service_and_rpc.py
@@ -5,98 +5,108 @@ import uuid
 import datetime
 import logging
 from lofar.messaging.messagebus import TemporaryQueue
+from lofar.common.test_utils import integration_test
 
 logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
 logger = logging.getLogger(__name__)
 
-with TemporaryQueue(__name__) as tmp_queue:
-    busname = tmp_queue.address
-
-    logger.warning("Fix and re-enable test_cleanup_service_and_rpc!")
-    exit(3)
-
-    # TODO: the cleanup service does not use shutil.rmtree under the hood anymore,
-    # so we cannot mock that
-    # and we do not want to delete actual data
-    # so I disabled this test for now.
-
-    ## the cleanup service uses shutil.rmtree under the hood
-    ## so, mock/patch shutil.rmtree and fake the delete action
-    ## because we do not want to delete any real data in this test
-    #with patch('shutil.rmtree', autospec=True) as patch_rmtree:
-        #mock_rmtree = patch_rmtree.return_value
-        #mock_rmtree.return_value = True
-
-        #with patch('lofar.sas.resourceassignment.resourceassignmentservice.rpc.RARPC', autospec=True) as patch_rarpc:
-            #mock_rarpc = patch_rarpc.return_value
-            #mock_rarpc.getTask.side_effect = lambda otdb_id: {'id': 42, 'mom_id': 1000042} if otdb_id == 13 else {'id': 43, 'mom_id': 1000043} if otdb_id == 14 else None
-
-            #with patch('lofar.mom.momqueryservice.momqueryrpc.MoMQueryRPC', autospec=True) as patch_momrpc:
-                #mock_momrpc = patch_momrpc.return_value
-                #mock_momrpc.getObjectDetails.return_value = {'1000042': {'project_name': 'my_project'}}
-
-                ## now that we have a mocked the external dependencies, import cleanupservice
-                #from lofar.sas.datamanagement.cleanup.service import createService
-                #from lofar.sas.datamanagement.cleanup.rpc import CleanupRPC
-
-                #class TestCleanupServiceAndRPC(unittest.TestCase):
-                    #def testRemovePath(self):
-                        #with CleanupRPC(busname=busname) as rpc:
-                            ##try some invalid input
-                            #self.assertFalse(rpc.removePath(None)['deleted'])
-                            #self.assertFalse(rpc.removePath(True)['deleted'])
-                            #self.assertFalse(rpc.removePath({'foo':'bar'})['deleted'])
-                            #self.assertFalse(rpc.removePath(['foo', 'bar'])['deleted'])
-
-                            ##try some dangerous paths
-                            ##these should not be deleted
-                            #result = rpc.removePath('/')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Path does not start with' in result['message'])
-
-                            #result = rpc.removePath('/foo/*/bar')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('No wildcards allowed' in result['message'])
-
-                            #result = rpc.removePath('/foo/ba?r')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('No wildcards allowed' in result['message'])
-
-                            #result = rpc.removePath('/data')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Path does not start with' in result['message'])
-
-                            #result = rpc.removePath('/data/test-projects/')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Path should be a subdir of' in result['message'])
-
-                            #result = rpc.removePath('/data/test-projects/foo')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Path should be a subdir of' in result['message'])
-
-                            #result = rpc.removePath('/data/test-projects/foo/')
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Path should be a subdir of' in result['message'])
-
-                            ##try an actual delete, should work with mocked shutil.rmtree
-                            #self.assertTrue(rpc.removePath('/data/test-projects/foo/bar')['deleted'])
-
-                    #def testRemoveTaskData(self):
-                        #with CleanupRPC(busname=busname) as rpc:
-                            ##try existing otdb_id=13
-                            #self.assertTrue(rpc.removeTaskData(13)['deleted'])
-
-                            ##try non_existing mom_project for otdb_id=14
-                            #result = rpc.removeTaskData(14)
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Could not find mom project details' in result['message'])
-
-                            ##try non_existing otdb_id=15
-                            #result = rpc.removeTaskData(15)
-                            #self.assertFalse(result['deleted'])
-                            #self.assertTrue('Could not find task' in result['message'])
-
-                ## create and run the service
-                #with createService(busname=busname):
-                    ## and run all tests
-                    #unittest.main()
+
+@integration_test
+class CleanupServiceRpcTest(unittest.TestCase):
+    def integration_test(self):
+        with TemporaryQueue(__name__) as tmp_queue:
+            busname = tmp_queue.address
+
+            logger.warning("Fix and re-enable test_cleanup_service_and_rpc!")
+            exit(3)
+
+            # TODO: the cleanup service does not use shutil.rmtree under the hood anymore,
+            # so we cannot mock that
+            # and we do not want to delete actual data
+            # so I disabled this test for now.
+
+            ## the cleanup service uses shutil.rmtree under the hood
+            ## so, mock/patch shutil.rmtree and fake the delete action
+            ## because we do not want to delete any real data in this test
+            #with patch('shutil.rmtree', autospec=True) as patch_rmtree:
+                #mock_rmtree = patch_rmtree.return_value
+                #mock_rmtree.return_value = True
+
+                #with patch('lofar.sas.resourceassignment.resourceassignmentservice.rpc.RARPC', autospec=True) as patch_rarpc:
+                    #mock_rarpc = patch_rarpc.return_value
+                    #mock_rarpc.getTask.side_effect = lambda otdb_id: {'id': 42, 'mom_id': 1000042} if otdb_id == 13 else {'id': 43, 'mom_id': 1000043} if otdb_id == 14 else None
+
+                    #with patch('lofar.mom.momqueryservice.momqueryrpc.MoMQueryRPC', autospec=True) as patch_momrpc:
+                        #mock_momrpc = patch_momrpc.return_value
+                        #mock_momrpc.getObjectDetails.return_value = {'1000042': {'project_name': 'my_project'}}
+
+                        ## now that we have a mocked the external dependencies, import cleanupservice
+                        #from lofar.sas.datamanagement.cleanup.service import createService
+                        #from lofar.sas.datamanagement.cleanup.rpc import CleanupRPC
+
+                        #class TestCleanupServiceAndRPC(unittest.TestCase):
+                            #def testRemovePath(self):
+                                #with CleanupRPC(busname=busname) as rpc:
+                                    ##try some invalid input
+                                    #self.assertFalse(rpc.removePath(None)['deleted'])
+                                    #self.assertFalse(rpc.removePath(True)['deleted'])
+                                    #self.assertFalse(rpc.removePath({'foo':'bar'})['deleted'])
+                                    #self.assertFalse(rpc.removePath(['foo', 'bar'])['deleted'])
+
+                                    ##try some dangerous paths
+                                    ##these should not be deleted
+                                    #result = rpc.removePath('/')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Path does not start with' in result['message'])
+
+                                    #result = rpc.removePath('/foo/*/bar')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('No wildcards allowed' in result['message'])
+
+                                    #result = rpc.removePath('/foo/ba?r')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('No wildcards allowed' in result['message'])
+
+                                    #result = rpc.removePath('/data')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Path does not start with' in result['message'])
+
+                                    #result = rpc.removePath('/data/test-projects/')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Path should be a subdir of' in result['message'])
+
+                                    #result = rpc.removePath('/data/test-projects/foo')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Path should be a subdir of' in result['message'])
+
+                                    #result = rpc.removePath('/data/test-projects/foo/')
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Path should be a subdir of' in result['message'])
+
+                                    ##try an actual delete, should work with mocked shutil.rmtree
+                                    #self.assertTrue(rpc.removePath('/data/test-projects/foo/bar')['deleted'])
+
+                            #def testRemoveTaskData(self):
+                                #with CleanupRPC(busname=busname) as rpc:
+                                    ##try existing otdb_id=13
+                                    #self.assertTrue(rpc.removeTaskData(13)['deleted'])
+
+                                    ##try non_existing mom_project for otdb_id=14
+                                    #result = rpc.removeTaskData(14)
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Could not find mom project details' in result['message'])
+
+                                    ##try non_existing otdb_id=15
+                                    #result = rpc.removeTaskData(15)
+                                    #self.assertFalse(result['deleted'])
+                                    #self.assertTrue('Could not find task' in result['message'])
+
+                        ## create and run the service
+                        #with createService(busname=busname):
+                            ## and run all tests
+                            #unittest.main()
+
+if __name__ == "__main__":
+    logging.basicConfig(format = '%(asctime)s %(levelname)s %(message)s', level = logging.INFO)
+    unittest.main()
+
diff --git a/SAS/OTDB_Services/test/t_TreeService.py b/SAS/OTDB_Services/test/t_TreeService.py
index 8da76f304ead54eff9d5f0ca5a9e34e61efc606b..fed1ee1882495a06db23dd3cb44afcf620014d60 100644
--- a/SAS/OTDB_Services/test/t_TreeService.py
+++ b/SAS/OTDB_Services/test/t_TreeService.py
@@ -31,131 +31,139 @@ StatusUpdateCommand     : finction to update the status of a tree.
 from lofar.sas.otdb.TreeService import create_service
 from lofar.messaging import TemporaryExchange, RPCClient, BusListenerJanitor
 from lofar.sas.otdb.testing.otdb_common_testing import OTDBTestInstance
+import unittest
+from lofar.common.test_utils import integration_test
 
 import logging
 
 logger = logging.getLogger(__name__)
 logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
 
-# todo: use unittest package for this
-
-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))
-            rpc_instance.execute(method_name=method_name, **arg_dict)
-            raise Exception("Expected an exception {0}, didn't get any".format(exc_text))
-        except Exception:
-            print("Caught expected exception {0}".format(exc_text))
-        print("======")
-
-    def do_rpc(rpc_instance, method_name, arg_dict):
-        print("** Executing {0}({1})...".format(method_name, arg_dict))
-        answer = rpc_instance.execute(method_name=method_name, **arg_dict)
-        print("result =", answer)
-        print("======")
-        return answer
-
-    with TemporaryExchange(__name__) as tmp_exchange:
-        exchange = tmp_exchange.address
-
-        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 })
-                do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 1099268, 'MomID': 5 })
-                do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 1099268, 'MomID': None })
-                do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 5, 'MomID': 353713 })
-                do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': 5, 'MomID': 5 })
-                do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': 5, 'MomID': None })
-                do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': None, 'MomID': 353713 })
-                do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': None, 'MomID': 5 })
-                do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': None, 'MomID': None })
-
-                do_rpc(otdbRPC, "GetDefaultTemplates", {})
-
-                do_rpc(otdbRPC, "SetProject",
-                       {'name':"Taka Tuka Land", "title":"Adventure movie", "pi":"Pippi",
-                        "co_i":"Mr.Nelson", "contact":"Witje"})
-
-                do_rpc(otdbRPC, "TaskCreate", {'OtdbID':1099268, 'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
-                do_rpc(otdbRPC, "TaskCreate", {'MomID':353713,   'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
-                do_rpc_catch_exception('on non-exsisting campaign', otdbRPC, "TaskCreate",
-                                       {'MomID':998877,   'TemplateName':'BeamObservation',
-                                        'CampaignName':'No such campaign', 'Specification': {'state':'finished'}})
-                do_rpc(otdbRPC, "TaskCreate", {'MomID':998877,   'TemplateName':'BeamObservation',
-                                     'CampaignName':'Taka Tuka Land', 'Specification': {'state':'finished'}})
-                data = do_rpc(otdbRPC, "TaskCreate", {'MomID':12345, 'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
-                new_tree1 = data['MomID']
-                data = do_rpc(otdbRPC, "TaskCreate", {'MomID':54321, 'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
-                new_tree2= data['MomID']
-
-                do_rpc(otdbRPC, "TaskPrepareForScheduling", {'MomID':new_tree1})   # template
-                do_rpc(otdbRPC, "TaskPrepareForScheduling", {'MomID':new_tree1})   # now a VIC tree
-                do_rpc(otdbRPC, "TaskPrepareForScheduling",
-                       {'MomID':new_tree1, 'StartTime':'2016-03-01 12:00:00',
-                        'StopTime':'2016-03-01 12:34:56'})
-                do_rpc_catch_exception("on invalid stoptime", otdbRPC,
-                                       "TaskPrepareForScheduling",
-                                       {'MomID':new_tree1, 'StartTime':'2016-03-01 12:00:00',
-                                        'StopTime':'2016'})
-
-                do_rpc(otdbRPC, "TaskDelete", {'MomID':new_tree2})
-
-                do_rpc(otdbRPC, "TaskGetSpecification", {'OtdbID':1099269})  # PIC
-                do_rpc(otdbRPC, "TaskGetSpecification", {'OtdbID':1099238})	  # Template
-                do_rpc(otdbRPC, "TaskGetSpecification", {'OtdbID':1099266})	  # VIC
-                do_rpc_catch_exception('on non-existing treeID', otdbRPC,
-                                       "TaskGetSpecification", {'OtdbID':5}) # Non existing
-
-                # PIC
-                do_rpc(otdbRPC, "TaskSetStatus",
-                       {'OtdbID':1099269, 'NewStatus':'finished', 'UpdateTimestamps':True})
-                # Template
-                do_rpc(otdbRPC, "TaskSetStatus",
-                       {'OtdbID':1099238, 'NewStatus':'finished', 'UpdateTimestamps':True})
-                # VIC
-                do_rpc(otdbRPC, "TaskSetStatus",
-                       {'OtdbID':1099266, 'NewStatus':'finished', 'UpdateTimestamps':True})
-
-                # Nonexisting tree
-                do_rpc_catch_exception('on invalid treeID', otdbRPC,
-                                       "TaskSetStatus",
-                                       {'OtdbID':10, 'NewStatus':'finished',
-                                        'UpdateTimestamps':True})
-
-                # VIC tree: invalid status
-                do_rpc_catch_exception('on invalid status', otdbRPC, "TaskSetStatus",
-                                       {'OtdbID':1099266, 'NewStatus':'what_happend',
-                                        'UpdateTimestamps':True})
-                # Set PIC back to active...
-                do_rpc(otdbRPC, "TaskSetStatus",
-                       {'OtdbID':1099269, 'NewStatus':'active', 'UpdateTimestamps':True})
-
-
-                do_rpc(otdbRPC, "GetStations", {})
-
-                # VIC tree: valid
-                do_rpc(otdbRPC, "TaskSetSpecification",
-                       {'OtdbID':1099266,
-                       'Specification':
-                           {'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.pythonHost':
-                                'NameOfTestHost'}})
-                # Template tree: not supported yet
-                do_rpc(otdbRPC, "TaskSetSpecification", {'OtdbID':1099238,
-                       'Specification':{'LOFAR.ObsSW.Observation.Scheduler.priority':'0.1'}})
-                # PIC tree: not supported yet
-                do_rpc_catch_exception('on invalid treetype (PIC)', otdbRPC,
-                                       "TaskSetSpecification",
-                                       {'OtdbID':1099269,
-                                        'Specification':{'LOFAR.PIC.Core.CS001.status_state':'50'}})
-                # Non exsisting tree
-                do_rpc_catch_exception('on invalid treeID', otdbRPC,
-                                       "TaskSetSpecification",
-                                       {'OtdbID':10,
-                                        'Specification':
-                                            {'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.pythonHost':'NameOfTestHost'}})
-                # VIC tree: wrong key
-                do_rpc_catch_exception('on invalid key', otdbRPC, "TaskSetSpecification", {'OtdbID':1099266,
-                       'Specification':{'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.NoSuchKey':'NameOfTestHost'}})
 
+@integration_test
+class TreeServiceTest(unittest.TestCase):
+    def test(self):
+        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))
+                    rpc_instance.execute(method_name=method_name, **arg_dict)
+                    raise Exception("Expected an exception {0}, didn't get any".format(exc_text))
+                except Exception:
+                    print("Caught expected exception {0}".format(exc_text))
+                print("======")
+
+            def do_rpc(rpc_instance, method_name, arg_dict):
+                print("** Executing {0}({1})...".format(method_name, arg_dict))
+                answer = rpc_instance.execute(method_name=method_name, **arg_dict)
+                print("result =", answer)
+                print("======")
+                return answer
+
+            with TemporaryExchange(__name__) as tmp_exchange:
+                exchange = tmp_exchange.address
+
+                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 })
+                        do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 1099268, 'MomID': 5 })
+                        do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 1099268, 'MomID': None })
+                        do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': 5, 'MomID': 353713 })
+                        do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': 5, 'MomID': 5 })
+                        do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': 5, 'MomID': None })
+                        do_rpc(otdbRPC, "TaskGetIDs", {'OtdbID': None, 'MomID': 353713 })
+                        do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': None, 'MomID': 5 })
+                        do_rpc_catch_exception('', otdbRPC, "TaskGetIDs", {'OtdbID': None, 'MomID': None })
+
+                        do_rpc(otdbRPC, "GetDefaultTemplates", {})
+
+                        do_rpc(otdbRPC, "SetProject",
+                               {'name':"Taka Tuka Land", "title":"Adventure movie", "pi":"Pippi",
+                                "co_i":"Mr.Nelson", "contact":"Witje"})
+
+                        do_rpc(otdbRPC, "TaskCreate", {'OtdbID':1099268, 'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
+                        do_rpc(otdbRPC, "TaskCreate", {'MomID':353713,   'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
+                        do_rpc_catch_exception('on non-exsisting campaign', otdbRPC, "TaskCreate",
+                                               {'MomID':998877,   'TemplateName':'BeamObservation',
+                                                'CampaignName':'No such campaign', 'Specification': {'state':'finished'}})
+                        do_rpc(otdbRPC, "TaskCreate", {'MomID':998877,   'TemplateName':'BeamObservation',
+                                             'CampaignName':'Taka Tuka Land', 'Specification': {'state':'finished'}})
+                        data = do_rpc(otdbRPC, "TaskCreate", {'MomID':12345, 'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
+                        new_tree1 = data['MomID']
+                        data = do_rpc(otdbRPC, "TaskCreate", {'MomID':54321, 'TemplateName':'BeamObservation', 'Specification': {'state':'finished'}})
+                        new_tree2= data['MomID']
+
+                        do_rpc(otdbRPC, "TaskPrepareForScheduling", {'MomID':new_tree1})   # template
+                        do_rpc(otdbRPC, "TaskPrepareForScheduling", {'MomID':new_tree1})   # now a VIC tree
+                        do_rpc(otdbRPC, "TaskPrepareForScheduling",
+                               {'MomID':new_tree1, 'StartTime':'2016-03-01 12:00:00',
+                                'StopTime':'2016-03-01 12:34:56'})
+                        do_rpc_catch_exception("on invalid stoptime", otdbRPC,
+                                               "TaskPrepareForScheduling",
+                                               {'MomID':new_tree1, 'StartTime':'2016-03-01 12:00:00',
+                                                'StopTime':'2016'})
+
+                        do_rpc(otdbRPC, "TaskDelete", {'MomID':new_tree2})
+
+                        do_rpc(otdbRPC, "TaskGetSpecification", {'OtdbID':1099269})  # PIC
+                        do_rpc(otdbRPC, "TaskGetSpecification", {'OtdbID':1099238})	  # Template
+                        do_rpc(otdbRPC, "TaskGetSpecification", {'OtdbID':1099266})	  # VIC
+                        do_rpc_catch_exception('on non-existing treeID', otdbRPC,
+                                               "TaskGetSpecification", {'OtdbID':5}) # Non existing
+
+                        # PIC
+                        do_rpc(otdbRPC, "TaskSetStatus",
+                               {'OtdbID':1099269, 'NewStatus':'finished', 'UpdateTimestamps':True})
+                        # Template
+                        do_rpc(otdbRPC, "TaskSetStatus",
+                               {'OtdbID':1099238, 'NewStatus':'finished', 'UpdateTimestamps':True})
+                        # VIC
+                        do_rpc(otdbRPC, "TaskSetStatus",
+                               {'OtdbID':1099266, 'NewStatus':'finished', 'UpdateTimestamps':True})
+
+                        # Nonexisting tree
+                        do_rpc_catch_exception('on invalid treeID', otdbRPC,
+                                               "TaskSetStatus",
+                                               {'OtdbID':10, 'NewStatus':'finished',
+                                                'UpdateTimestamps':True})
+
+                        # VIC tree: invalid status
+                        do_rpc_catch_exception('on invalid status', otdbRPC, "TaskSetStatus",
+                                               {'OtdbID':1099266, 'NewStatus':'what_happend',
+                                                'UpdateTimestamps':True})
+                        # Set PIC back to active...
+                        do_rpc(otdbRPC, "TaskSetStatus",
+                               {'OtdbID':1099269, 'NewStatus':'active', 'UpdateTimestamps':True})
+
+
+                        do_rpc(otdbRPC, "GetStations", {})
+
+                        # VIC tree: valid
+                        do_rpc(otdbRPC, "TaskSetSpecification",
+                               {'OtdbID':1099266,
+                               'Specification':
+                                   {'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.pythonHost':
+                                        'NameOfTestHost'}})
+                        # Template tree: not supported yet
+                        do_rpc(otdbRPC, "TaskSetSpecification", {'OtdbID':1099238,
+                               'Specification':{'LOFAR.ObsSW.Observation.Scheduler.priority':'0.1'}})
+                        # PIC tree: not supported yet
+                        do_rpc_catch_exception('on invalid treetype (PIC)', otdbRPC,
+                                               "TaskSetSpecification",
+                                               {'OtdbID':1099269,
+                                                'Specification':{'LOFAR.PIC.Core.CS001.status_state':'50'}})
+                        # Non exsisting tree
+                        do_rpc_catch_exception('on invalid treeID', otdbRPC,
+                                               "TaskSetSpecification",
+                                               {'OtdbID':10,
+                                                'Specification':
+                                                    {'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.pythonHost':'NameOfTestHost'}})
+                        # VIC tree: wrong key
+                        do_rpc_catch_exception('on invalid key', otdbRPC, "TaskSetSpecification", {'OtdbID':1099266,
+                               'Specification':{'LOFAR.ObsSW.Observation.ObservationControl.PythonControl.NoSuchKey':'NameOfTestHost'}})
+
+
+if __name__ == "__main__":
+    logging.basicConfig(format = '%(asctime)s %(levelname)s %(message)s', level = logging.INFO)
+    unittest.main()
diff --git a/SAS/OTDB_Services/test/t_TreeStatusEvents.py b/SAS/OTDB_Services/test/t_TreeStatusEvents.py
index 5fe78d931e8f7fcd3f3c79e3dd68cee8cc0c088a..c7e7da352bb0c4207f8e45a30229610b2c1e7378 100644
--- a/SAS/OTDB_Services/test/t_TreeStatusEvents.py
+++ b/SAS/OTDB_Services/test/t_TreeStatusEvents.py
@@ -34,6 +34,8 @@ import threading
 import sys
 from datetime import datetime, timedelta
 from tempfile import NamedTemporaryFile
+import unittest
+from lofar.common.test_utils import integration_test
 
 import logging
 logger = logging.getLogger(__name__)
@@ -41,30 +43,36 @@ logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=loggin
 
 from lofar.sas.otdb.testing.otdb_common_testing import OTDBTestInstance
 
-# todo: use unittest package for this
 
-with OTDBTestInstance('t_TreeStatusEvents.in.unittest_db.dump.gz') as test_db:
-    with TemporaryExchange(__name__) as tmp_exchange:
-        with tmp_exchange.create_temporary_queue() as tmp_queue:
-            with tmp_queue.create_frombus() as frombus:
+@integration_test
+class TreeStatusEventsTest(unittest.TestCase):
+    def test(self):
+        with OTDBTestInstance('t_TreeStatusEvents.in.unittest_db.dump.gz') as test_db:
+            with TemporaryExchange(__name__) as tmp_exchange:
+                with tmp_exchange.create_temporary_queue() as tmp_queue:
+                    with tmp_queue.create_frombus() as frombus:
 
-                with NamedTemporaryFile(mode='w+') as state_file:
-                    state_file.file.write((datetime.utcnow()-timedelta(seconds=2)).strftime("%Y-%m-%d %H:%M:%S"))
-                    state_file.file.flush()
+                        with NamedTemporaryFile(mode='w+') as state_file:
+                            state_file.file.write((datetime.utcnow()-timedelta(seconds=2)).strftime("%Y-%m-%d %H:%M:%S"))
+                            state_file.file.flush()
 
-                    t = threading.Thread(target=create_service, args=(tmp_exchange.address, test_db.dbcreds, state_file.name))
-                    t.daemon = True
-                    t.start()
+                            t = threading.Thread(target=create_service, args=(tmp_exchange.address, test_db.dbcreds, state_file.name))
+                            t.daemon = True
+                            t.start()
 
-                    with test_db.create_database_connection() as db:
-                        db.executeQuery("select setTreeState(1, %d, %d::INT2,'%s'::boolean);" % (1099266, 500, False))
-                        db.commit()
+                            with test_db.create_database_connection() as db:
+                                db.executeQuery("select setTreeState(1, %d, %d::INT2,'%s'::boolean);" % (1099266, 500, False))
+                                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
+                            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
+                            self.assertTrue(ok)
+
+if __name__ == "__main__":
+    logging.basicConfig(format = '%(asctime)s %(levelname)s %(message)s', level = logging.INFO)
+    unittest.main()