diff --git a/SAS/ResourceAssignment/Common/lib/specification.py b/SAS/ResourceAssignment/Common/lib/specification.py
index 5f953232fe009402f5cf5405fa2647c66b8ca07a..b164ab72e6e8a5a90b5493548b6fd0bcdf674a9c 100644
--- a/SAS/ResourceAssignment/Common/lib/specification.py
+++ b/SAS/ResourceAssignment/Common/lib/specification.py
@@ -724,7 +724,7 @@ class Specification:
 
         :returns 2-tuple (start_time, end_time)
         """
-        # TODO: don't fix this crap here. Bad start/stop time has to go to error, like any other bad spec part.
+        # TODO? don't fix this crap here. Bad start/stop time has to go to error, like any other bad spec part.
         if not self.isUnmovable(): #maintenance and reservation
             shift = timedelta(seconds=0)
             starttime = self.starttime
@@ -746,7 +746,7 @@ class Specification:
                 self.min_starttime = self.starttime
             if self.max_endtime:
                 self.endtime = self.max_endtime
-            #TODO Not happy with this min/maxDuration
+            #TODO Not happy with this min/maxDuration, what to do if duration is not None but they are set?
             if self.duration is None:
                 if self.max_duration:
                     self.duration = self.max_duration
@@ -775,9 +775,9 @@ class Specification:
         self._store_changed_start_and_end_times_to_otdb(self.starttime, self.endtime, self.duration, self.otdb_id)
         #TODO self._store_changed_start_and_end_times_to_mom(self.starttime, self.endtime, self.duration, self.otdb_id)
 
+    #TODO maybe use min_duration, max_duration if specified? DwellScheduler can't use them right now?
     def calculate_dwell_values(self, start_time, end_time, min_starttime, max_endtime):
-        """
-        Use any specified min_starttime/max_endtime to calculate the min_starttime/max_starttime. All timestamps are in
+        """ Use any specified min_starttime/max_endtime to calculate the min_starttime/max_starttime. All timestamps are in
         datetime format
 
         :param start_time:      Task fixed start time
@@ -867,8 +867,8 @@ class Specification:
             self.logger.warn('Task otdb_id=%s with status \'%s\' is not assignable. Allowed statuses are %s' %
                         (self.otdb_id, self.status, assignable_task_states_str))
 
-            message = "doAssignment: Unsupported status '%s' of task with OTDB ID: %s" % (self.status, self.otdb_id)
-            raise Exception(message)
+            message = "Unsupported status '%s' of task with OTDB ID: %s" % (self.status, self.otdb_id)
+            raise Exception(message) #TODO more specific exception type?
 
     def set_status(self, new_status):
         """
diff --git a/SAS/ResourceAssignment/Common/test/test_specification.py b/SAS/ResourceAssignment/Common/test/test_specification.py
index 86c37c6364215448a63be9ffc9e3061ce9719bd6..474d8de471724947c24cdb903e7e73590da032f5 100755
--- a/SAS/ResourceAssignment/Common/test/test_specification.py
+++ b/SAS/ResourceAssignment/Common/test/test_specification.py
@@ -18,7 +18,7 @@
 # with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
 
 # $Id:  $
-import unittest, datetime, mock, os
+import unittest, mock, os
 from lofar.parameterset import parameterset
 from datetime import datetime, timedelta
 
@@ -49,8 +49,8 @@ class SpecificationTest(unittest.TestCase):
         #self.mom_id = 351557
         #self.otdb_id = 1290494
         #self.trigger_id = 2323
-        #future_start_time = (datetime.datetime.utcnow() + datetime.timedelta(hours=1)).strftime('%Y-%m-%d %H:%M:%S')
-        #future_stop_time = (datetime.datetime.utcnow() + datetime.timedelta(hours=2)).strftime('%Y-%m-%d %H:%M:%S')
+        #future_start_time = (datetime.utcnow() + datetime.timedelta(hours=1)).strftime('%Y-%m-%d %H:%M:%S')
+        #future_stop_time = (datetime.utcnow() + datetime.timedelta(hours=2)).strftime('%Y-%m-%d %H:%M:%S')
 
         otdbrpc_patcher = mock.patch('lofar.sas.otdb.otdbrpc')
         self.addCleanup(otdbrpc_patcher.stop)
@@ -84,8 +84,8 @@ class SpecificationTest(unittest.TestCase):
     def test_read_from_mom_misc(self):
         """ Verify that get_specification properly generates an RA parset subset for a preprocessing pipeline parset """
         # Arrange
-        min_start_time = datetime.datetime(2017, 10, 2, 22, 43, 12)
-        max_end_time = datetime.datetime(2017, 10, 3, 22, 43, 12)
+        min_start_time = datetime(2017, 10, 2, 22, 43, 12)
+        max_end_time = datetime(2017, 10, 3, 22, 43, 12)
         min_duration = timedelta(seconds=200)
         max_duration = timedelta(seconds=3600)
         self.momrpc_mock.get_trigger_time_restrictions.return_value = {"minStartTime": min_start_time,
@@ -379,8 +379,8 @@ class SpecificationTest(unittest.TestCase):
         start_time, end_time = Specification._get_start_and_end_times_from_parset(input_parset, INPUT_PREFIX)
 
         # Assert
-        self.assertEqual(start_time, datetime.datetime(2016, 12, 8, 23, 20, 25))
-        self.assertEqual(end_time, datetime.datetime(2016, 12, 9, 7, 20, 25))
+        self.assertEqual(start_time, datetime(2016, 12, 8, 23, 20, 25))
+        self.assertEqual(end_time, datetime(2016, 12, 9, 7, 20, 25))
 
     def test_get_no_start_and_end_times_from_parset(self):
         """ Verify that get_specification properly generates an RA parset subset for a reservation task """
@@ -432,9 +432,9 @@ class SpecificationTest(unittest.TestCase):
         input_parset = self.specification._get_parset_from_OTDB()
 
         # Assert
-        #TODO not sure what to assert here
+        #TODO not sure what to assert here, no easy comparison for parsets?
         #self.assertEqual(input_parset, None)
-        self.otdbrpc_mock.taskGetSpecification.assert()
+        self.otdbrpc_mock.taskGetSpecification.assert_any_call(otdb_id=562059)
 
     #TODO more tests for read_from_otdb?
     def test_read_from_otdb(self):
@@ -525,11 +525,280 @@ class SpecificationTest(unittest.TestCase):
     # ------------------------------------------------------------------------------------------------------------------
     # Tests of functions to change start/end times and durations
 
+    def test_update_start_end_times_value_error(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        self.specification.type = "maintenance"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertRaises(ValueError)
+        self.otdbrpc_mock.taskSetSpecification.assert_not_called()
+
+    def test_update_start_end_times_maintenance(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() - timedelta(minutes=1)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        self.specification.type = "maintenance"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertGreater(self.specification.starttime, start_time)
+        self.assertGreater(self.specification.endtime, end_time)
+        self.assertEqual(self.specification.endtime - self.specification.starttime, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_no_times(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertGreater(self.specification.starttime, datetime.utcnow())
+        self.assertGreater(self.specification.endtime, datetime.utcnow() + timedelta(hours=1))
+        self.assertEqual(self.specification.endtime - self.specification.starttime, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_past(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() - timedelta(minutes=1)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertGreater(self.specification.starttime, datetime.utcnow())
+        self.assertGreater(self.specification.endtime, datetime.utcnow() + timedelta(hours=1))
+        self.assertEqual(self.specification.endtime - self.specification.starttime, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_1min(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() + timedelta(minutes=1)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertEqual(self.specification.starttime, start_time)
+        self.assertEqual(self.specification.endtime, end_time)
+        self.assertEqual(self.specification.duration, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_min_start_time(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        min_start_time = datetime.utcnow() + timedelta(minutes=1)
+        start_time = datetime.utcnow() + timedelta(minutes=10)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.min_starttime = min_start_time
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
 
+        # Assert
+        self.assertEqual(self.specification.starttime, min_start_time)
+        self.assertEqual(self.specification.endtime, end_time)
+        self.assertGreater(self.specification.duration, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_max_end_time(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() + timedelta(minutes=1)
+        end_time = start_time + timedelta(hours=1)
+        max_end_time = datetime.utcnow() + timedelta(hours=2)
+        self.specification.max_endtime = max_end_time
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertEqual(self.specification.starttime, start_time)
+        self.assertEqual(self.specification.endtime, max_end_time)
+        self.assertGreater(self.specification.duration, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_duration(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() + timedelta(minutes=10)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.duration = end_time - start_time
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertEqual(self.specification.starttime, start_time)
+        self.assertEqual(self.specification.endtime, end_time)
+        self.assertEqual(self.specification.duration, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_min_duration(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() + timedelta(minutes=10)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.min_duration = end_time - start_time
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertEqual(self.specification.starttime, start_time)
+        self.assertEqual(self.specification.endtime, end_time)
+        self.assertEqual(self.specification.duration, timedelta(hours=1))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_predecessor_shift(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() + timedelta(minutes=10)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        spec = Specification(self.logger_mock, self.otdbrpc_mock, self.momrpc_mock, self.radbrpc_mock)
+        spec.starttime = start_time + timedelta(hours=2)
+        spec.endtime = end_time + timedelta(hours=2)
+        self.specification.predecessors.append(spec)
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertEqual(self.specification.starttime, spec.endtime + timedelta(minutes=3))
+        self.assertEqual(self.specification.endtime, spec.endtime + timedelta(hours=1) + timedelta(minutes=3))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_update_start_end_times_predecessor_no_shift(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime.utcnow() + timedelta(minutes=10)
+        end_time = start_time + timedelta(hours=1)
+        self.specification.starttime = start_time
+        self.specification.endtime = end_time
+        spec = Specification(self.logger_mock, self.otdbrpc_mock, self.momrpc_mock, self.radbrpc_mock)
+        spec.starttime = start_time - timedelta(hours=4)
+        spec.endtime = end_time - timedelta(hours=4)
+        self.specification.predecessors.append(spec)
+        self.specification.type = "observation"
+
+        # Act
+        self.specification.update_start_end_times()
+
+        # Assert
+        self.assertEqual(self.specification.starttime, spec.endtime + timedelta(minutes=3))
+        self.assertEqual(self.specification.endtime, spec.endtime + timedelta(hours=1) + timedelta(minutes=3))
+        self.otdbrpc_mock.taskSetSpecification.assert_called()
+
+    def test_calculate_dwell_values_with_misc(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        min_start_time = datetime(2017, 10, 2, 22, 43, 12)
+        max_end_time = datetime(2017, 10, 3, 22, 43, 12)
+        start_time = datetime(2017, 10, 2, 22, 00, 00)
+        end_time = datetime(2017, 10, 2, 23, 00, 00)
+        self.specification.type = "observation"
+
+        # Act
+        test_min_starttime, test_max_starttime, test_duration = \
+            self.specification.calculate_dwell_values(start_time, end_time, min_start_time, max_end_time)
+
+        # Assert
+        self.assertEqual(test_min_starttime, start_time)
+        self.assertEqual(test_max_starttime, max_end_time - timedelta(hours=1))
+        self.assertEqual(test_duration, timedelta(hours=1))
+
+    def test_calculate_dwell_values_without_misc(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        start_time = datetime(2017, 10, 3, 22, 00, 00)
+        end_time = datetime(2017, 10, 3, 23, 00, 00)
+        self.specification.type = "observation"
+
+        # Act
+        test_min_starttime, test_max_starttime, test_duration = \
+            self.specification.calculate_dwell_values(start_time, end_time, None, None)
+
+        # Assert
+        self.assertEqual(start_time, start_time)
+        self.assertEqual(test_max_starttime, start_time)
+        self.assertEqual(test_duration, timedelta(hours=1))
 
     # ------------------------------------------------------------------------------------------------------------------
     # Tests of functions to communicate with RADB
 
+    def test_read_from_radb(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        task = {"id": 1, "mom_id": 2, "otdb_id": 3, "status": "scheduled",
+                "type": "observation", "duration":100, "cluster": "CEP4"}
+        self.radbrpc_mock.getTask.return_value = task
+
+        # Act
+        self.specification.read_from_radb(1)
+
+        # Assert
+        self.assertEqual(self.specification.radb_id, task["id"])
+        self.assertEqual(self.specification.mom_id, task["mom_id"])
+        self.assertEqual(self.specification.otdb_id, task["otdb_id"])
+        self.assertEqual(self.specification.status, task["status"])
+        self.assertEqual(self.specification.type, task["type"])
+        self.assertEqual(self.specification.duration, timedelta(seconds=task["duration"]))
+        self.assertEqual(self.specification.cluster, task["cluster"])
+
+    def test_insert_into_radb(self):
+        """ Verify that get_specification properly generates an RA parset subset for a reservation task """
+        # Arrange
+        task = {"id": 1, "mom_id": 2, "otdb_id": 3, "status": "scheduled",
+                "type": "observation", "duration":100, "cluster": "CEP4"}
+        self.radbrpc_mock.getTask.return_value = task
+
+        # Act
+        self.specification.insert_into_radb()
+
+        # Assert
+        self.assertEqual(self.specification.radb_id, task["id"])
+        self.assertEqual(self.specification.mom_id, task["mom_id"])
+        self.assertEqual(self.specification.otdb_id, task["otdb_id"])
+        self.assertEqual(self.specification.status, task["status"])
+        self.assertEqual(self.specification.type, task["type"])
+        self.assertEqual(self.specification.duration, timedelta(seconds=task["duration"]))
+        self.assertEqual(self.specification.cluster, task["cluster"])
+
+
         # self.momrpc_mock.getPredecessorIds.return_value = {str(self.task_mom_id): self.predecessor_task_mom_ids}