diff --git a/odml/property.py b/odml/property.py
index 74e31f7..894296d 100644
--- a/odml/property.py
+++ b/odml/property.py
@@ -22,9 +22,9 @@ class BaseProperty(base.baseobject, Property):
                  dependency=None, dependency_value=None, dtype=None,
                  value_origin=None, id=None):
         """
-        Create a new Property with a single value. The method will try to infer
-        the value's dtype from the type of the value if not explicitly stated.
-        Example for a property with
+        Create a new Property. If a value without an explicitly stated dtype
+        has been provided, the method will try to infer the value's dtype.
+        Example:
         >>> p = Property("property1", "a string")
         >>> p.dtype
         >>> str
@@ -34,21 +34,25 @@ class BaseProperty(base.baseobject, Property):
         >>> p = Property("prop", [2, 3, 4])
         >>> p.dtype
         >>> int
-        :param name: The name of the property
-        :param value: Some data value, this may be a list of homogeneous values
+        :param name: The name of the property.
+        :param value: Some data value, it can be a single value or
+                      a list of homogeneous values.
         :param unit: The unit of the stored data.
-        :param uncertainty: the uncertainty (e.g. the standard deviation)
+        :param uncertainty: The uncertainty (e.g. the standard deviation)
                             associated with a measure value.
         :param reference: A reference (e.g. an URL) to an external definition
                           of the value.
         :param definition: The definition of the property.
         :param dependency: Another property this property depends on.
         :param dependency_value: Dependency on a certain value.
-        :param dtype: the data type of the values stored in the property,
-                     if dtype is not given, the type is deduced from the values
+        :param dtype: The data type of the values stored in the property,
+                      if dtype is not given, the type is deduced from the values.
+                      Check odml.DType for supported data types.
         :param value_origin: Reference where the value originated from e.g. a file name.
+        :param id: UUID string as specified in RFC 4122. If no id is provided,
+                   an id will be generated and assigned. An id has to be unique
+                   within an odML Document.
         """
-        # TODO validate arguments
         try:
             if id is not None:
                 self._id = str(uuid.UUID(id))
@@ -84,7 +88,7 @@ class BaseProperty(base.baseobject, Property):
 
     def new_id(self, id=None):
         """
-        new_id sets the id of the current object to a RFC 4122 compliant UUID.
+        new_id sets the id of the current object to an RFC 4122 compliant UUID.
         If an id was provided, it is assigned if it is RFC 4122 UUID format compliant.
         If no id was provided, a new UUID is generated and assigned.
         :param id: UUID string as specified in RFC 4122.
@@ -108,7 +112,7 @@ class BaseProperty(base.baseobject, Property):
     @property
     def dtype(self):
         """
-        The data type of the value
+        The data type of the value. Check odml.DType for supported data types.
         """
         return self._dtype
 
@@ -116,11 +120,9 @@ class BaseProperty(base.baseobject, Property):
     def dtype(self, new_type):
         """
         If the data type of a property value is changed, it is tried
-        to convert the value to the new type.
-        If this doesn't work, the change is refused.
-
-        This behaviour can be overridden by directly accessing the *_dtype*
-        attribute and adjusting the *data* attribute manually.
+        to convert existing values to the new type. If this doesn't work,
+        the change is refused. The dtype can always be changed, if
+        a Property does not contain values.
         """
         # check if this is a valid type
         if not dtypes.valid_type(new_type):
@@ -139,7 +141,7 @@ class BaseProperty(base.baseobject, Property):
     @property
     def parent(self):
         """
-        The section containing this property
+        The section containing this property.
         """
         return self._parent
 
@@ -170,29 +172,30 @@ class BaseProperty(base.baseobject, Property):
     @property
     def value(self):
         """
-        Returns the value(s) stored in this property. Method always returns a list that
-        is a copy (!) of the stored value. Changing this list will NOT change the property.
-        For manipulation of the stored values use the append, extend, and direct access methods
-        (using brackets).
+        Returns the value(s) stored in this property. Method always returns a list
+        that is a copy (!) of the stored value. Changing this list will NOT change
+        the property.
+        For manipulation of the stored values use the append, extend, and direct
+        access methods (using brackets).
 
         For example:
-        >> p = odml.Property("prop", value=[1, 2, 3])
-        >> print(p.value)
+        >>> p = odml.Property("prop", value=[1, 2, 3])
+        >>> print(p.value)
         [1, 2, 3]
-        >> p.value.append(4)
-        >> print(p.value)
+        >>> p.value.append(4)
+        >>> print(p.value)
         [1, 2, 3]
 
         Individual values can be accessed and manipulated like this:
         >>> print(p[0])
         [1]
-        >> p[0] = 4
-        >> print(p[0])
+        >>> p[0] = 4
+        >>> print(p[0])
         [4]
 
         The values can be iterated e.g. with a loop:
-        >> for v in p.value:
-              print(v)
+        >>> for v in p.value:
+        >>>   print(v)
         4
         2
         3
@@ -201,18 +204,18 @@ class BaseProperty(base.baseobject, Property):
 
     def value_str(self, index=0):
         """
-        Used to access typed data of the value as a string.
-        Use data to access the raw type, i.e.:
+        Used to access typed data of the value at a specific
+        index position as a string.
         """
         return dtypes.set(self._value[index], self._dtype)
 
     def _validate_values(self, values):
         """
-            Method ensures that the passed value(s) can be cast to the
-            same dtype, i.e. that associated with this property or the
-            inferred dtype of the first entry of the values list.
+        Method ensures that the passed value(s) can be cast to the
+        same dtype, i.e. that are associated with this property or the
+        inferred dtype of the first entry of the values list.
 
-        :param values an iterable that contains the values
+        :param values: an iterable that contains the values.
         """
         for v in values:
             try:
@@ -227,7 +230,7 @@ class BaseProperty(base.baseobject, Property):
         If new_value is a string, it will convert it to a list of
         strings if the new_value contains embracing brackets.
 
-        returns list of new_value
+        :return: list of new_value
         """
         if isinstance(new_value, str):
             if new_value[0] == "[" and new_value[-1] == "]":
@@ -241,21 +244,22 @@ class BaseProperty(base.baseobject, Property):
         elif not isinstance(new_value, list):
             new_value = [new_value]
         else:
-            raise ValueError("odml.Property._convert_value_input: unsupported data type for values: %s" % type(new_value))
+            raise ValueError("odml.Property._convert_value_input: "
+                             "unsupported data type for values: %s" % type(new_value))
         return new_value
 
     @value.setter
     def value(self, new_value):
         """
-
         Set the value of the property discarding any previous information.
         Method will try to convert the passed value to the dtype of
-        the property and raise an ValueError, if not possible
+        the property and raise an ValueError if not possible.
 
-        :param new_value a single value or list of values.
+        :param new_value: a single value or list of values.
         """
         # Make sure boolean value 'False' gets through as well...
-        if new_value is None or (isinstance(new_value, (list, tuple, str)) and len(new_value) == 0):
+        if new_value is None or \
+                (isinstance(new_value, (list, tuple, str)) and len(new_value) == 0):
             self._value = []
             return
 
@@ -285,6 +289,8 @@ class BaseProperty(base.baseobject, Property):
 
     @uncertainty.setter
     def uncertainty(self, new_value):
+        if new_value == "":
+            new_value = None
         self._uncertainty = new_value
 
     @property
@@ -339,9 +345,9 @@ class BaseProperty(base.baseobject, Property):
 
     def remove(self, value):
         """
-        Remove a value from this property and unset its parent.
-        Raises a TypeError if this would cause the property not to hold any
-        value at all. This can be circumvented by using the *_values* property.
+        Remove a value from this property. Only the first encountered
+        occurrence of the passed in value is removed from the properties
+        list of values.
         """
         if value in self._value:
             self._value.remove(value)
@@ -358,6 +364,7 @@ class BaseProperty(base.baseobject, Property):
     def clone(self):
         """
         Clone this object to copy it independently to another document.
+        The id of the cloned object will be set to a different uuid.
         """
         obj = super(BaseProperty, self).clone()
         obj._parent = None
@@ -367,23 +374,23 @@ class BaseProperty(base.baseobject, Property):
         return obj
 
     def merge(self, other, strict=True):
-        """Merges the property 'other' into self, if possible. Information
-        will be synchronized. Method will raise an ValueError when the
+        """
+        Merges the property 'other' into self, if possible. Information
+        will be synchronized. Method will raise a ValueError when the
         information in this property and the passed property are in
         conflict.
 
-        :param other a Property
-        :param strict Bool value to indicate whether types should be
-        implicitly converted even when information may be lost. Default is True, i.e. no conversion, and error will be raised if types do not match.
-
+        :param other: an odML Property.
+        :param strict: Bool value to indicate whether types should be implicitly converted
+               even when information may be lost. Default is True, i.e. no conversion,
+               and a ValueError will be raised if types do not match.
         """
-        assert(isinstance(other, (BaseProperty)))
+        assert(isinstance(other, BaseProperty))
         if strict and self.dtype != other.dtype:
             raise ValueError("odml.Property.merge: src and dest dtypes do not match!")
 
         if self.unit is not None and other.unit is not None and self.unit != other.unit:
-            raise ValueError("odml.Property.merge: src and dest units (%s, %s) do not match!"
-                             % (other.unit, self.unit))
+            raise ValueError("odml.Property.merge: src and dest units (%s, %s) do not match!" % (other.unit, self.unit))
 
         if self.definition is not None and other.definition is not None:
             self_def = ''.join(map(str.strip, self.definition.split())).lower()
@@ -422,14 +429,14 @@ class BaseProperty(base.baseobject, Property):
 
     def unmerge(self, other):
         """
-        Stub that doesn't do anything for this class
+        Stub that doesn't do anything for this class.
         """
         pass
 
     def get_merged_equivalent(self):
         """
-        Return the merged object (i.e. if the section is linked to another one,
-        return the corresponding property of the linked section) or None
+        Return the merged object (i.e. if the parent section is linked to another one,
+        return the corresponding property of the linked section) or None.
         """
         if self.parent is None or self.parent._merged is None:
             return None
@@ -466,17 +473,18 @@ class BaseProperty(base.baseobject, Property):
 
     def extend(self, obj, strict=True):
         """
-        Extend the list of values stored in this property by the passed values. Method will 
-        raise an ValueError, if values cannot be converted to the current dtype. One can also pass
-        another Property to append all values stored in that one. In this case units must match!
+        Extend the list of values stored in this property by the passed values. Method
+        will raise a ValueError, if values cannot be converted to the current dtype.
+        One can also pass another Property to append all values stored in that one.
+        In this case units must match!
 
-        :param obj single value, list of values or Property
-        :param strict a Bool that controls whether dtypes must match. Default is True.
+        :param obj: single value, list of values or a Property.
+        :param strict: a Bool that controls whether dtypes must match. Default is True.
         """
         if isinstance(obj, BaseProperty):
-            if (obj.unit != self.unit):
-                raise ValueError("odml.Property.append: src and dest units (%s, %s) do not match!"
-                                 % (obj.unit, self.unit))
+            if obj.unit != self.unit:
+                raise ValueError("odml.Property.extend: src and dest units (%s, %s) "
+                                 "do not match!" % (obj.unit, self.unit))
             self.extend(obj.value)
             return
 
@@ -486,29 +494,41 @@ class BaseProperty(base.baseobject, Property):
 
         new_value = self._convert_value_input(obj)
         if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype:
-            raise ValueError("odml.Property.extend: passed value data type does not match dtype!");
+            raise ValueError("odml.Property.extend: "
+                             "passed value data type does not match dtype!")
 
         if not self._validate_values(new_value):
-            raise ValueError("odml.Property.append: passed value(s) cannot be converted to "
-                             "data type \'%s\'!" % self._dtype)
+            raise ValueError("odml.Property.extend: passed value(s) cannot be converted "
+                             "to data type \'%s\'!" % self._dtype)
         self._value.extend([dtypes.get(v, self.dtype) for v in new_value])
 
     def append(self, obj, strict=True):
         """
-        Append a single value to the list of stored values. Method will raise an ValueError if 
-        the passed value cannot be converted to the current dtype.
+        Append a single value to the list of stored values. Method will raise
+        a ValueError if the passed value cannot be converted to the current dtype.
 
-        :param obj the additional value.
-        :param strict a Bool that controls whether dtypes must match. Default is True.
+        :param obj: the additional value.
+        :param strict: a Bool that controls whether dtypes must match. Default is True.
         """
+        # Ignore empty values before nasty stuff happens, but make sure
+        # 0 and False get through.
+        if obj in [None, "", [], {}]:
+            return
+
+        if not self.value:
+            self.value = obj
+            return
+
         new_value = self._convert_value_input(obj)
         if len(new_value) > 1:
             raise ValueError("odml.property.append: Use extend to add a list of values!")
+
         if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype:
-            raise ValueError("odml.Property.extend: passed value data type does not match dtype!");
+            raise ValueError("odml.Property.append: "
+                             "passed value data type does not match dtype!")
 
         if not self._validate_values(new_value):
-            raise ValueError("odml.Property.append: passed value(s) cannot be converted to "
-                             "data type \'%s\'!" % self._dtype)
-        self._value.append(dtypes.get(new_value[0], self.dtype))
+            raise ValueError("odml.Property.append: passed value(s) cannot be converted "
+                             "to data type \'%s\'!" % self._dtype)
 
+        self._value.append(dtypes.get(new_value[0], self.dtype))

Property.append returns dtype error on unset dtype
When using `Property.append` of a Property where neither value nor dtype are set, a dtype mismatch related ValueError is raised.
diff --git a/test/test_property.py b/test/test_property.py
index d0dc673..f0aa976 100644
--- a/test/test_property.py
+++ b/test/test_property.py
@@ -10,26 +10,67 @@ class TestProperty(unittest.TestCase):
     def setUp(self):
         pass
 
+    def test_simple_attributes(self):
+        p_name = "propertyName"
+        p_origin = "from over there"
+        p_unit = "pears"
+        p_uncertainty = "+-12"
+        p_ref = "4 8 15 16 23"
+        p_def = "an odml test property"
+        p_dep = "yes"
+        p_dep_val = "42"
+
+        prop = Property(name=p_name, value_origin=p_origin, unit=p_unit,
+                        uncertainty=p_uncertainty, reference=p_ref, definition=p_def,
+                        dependency=p_dep, dependency_value=p_dep_val)
+
+        self.assertEqual(prop.name, p_name)
+        self.assertEqual(prop.value_origin, p_origin)
+        self.assertEqual(prop.unit, p_unit)
+        self.assertEqual(prop.uncertainty, p_uncertainty)
+        self.assertEqual(prop.reference, p_ref)
+        self.assertEqual(prop.definition, p_def)
+        self.assertEqual(prop.dependency, p_dep)
+        self.assertEqual(prop.dependency_value, p_dep_val)
+
+        # Test setting attributes
+        prop.name = "%s_edit" % p_name
+        self.assertEqual(prop.name, "%s_edit" % p_name)
+        prop.value_origin = "%s_edit" % p_origin
+        self.assertEqual(prop.value_origin, "%s_edit" % p_origin)
+        prop.unit = "%s_edit" % p_unit
+        self.assertEqual(prop.unit, "%s_edit" % p_unit)
+        prop.uncertainty = "%s_edit" % p_uncertainty
+        self.assertEqual(prop.uncertainty, "%s_edit" % p_uncertainty)
+        prop.reference = "%s_edit" % p_ref
+        self.assertEqual(prop.reference, "%s_edit" % p_ref)
+        prop.definition = "%s_edit" % p_def
+        self.assertEqual(prop.definition, "%s_edit" % p_def)
+        prop.dependency = "%s_edit" % p_dep
+        self.assertEqual(prop.dependency, "%s_edit" % p_dep)
+        prop.dependency_value = "%s_edit" % p_dep_val
+        self.assertEqual(prop.dependency_value, "%s_edit" % p_dep_val)
+
+        # Test setting attributes to None when '' is passed.
+        prop.value_origin = ""
+        self.assertIsNone(prop.value_origin)
+        prop.unit = ""
+        self.assertIsNone(prop.unit)
+        prop.uncertainty = ""
+        self.assertIsNone(prop.uncertainty)
+        prop.reference = ""
+        self.assertIsNone(prop.reference)
+        prop.definition = ""
+        self.assertIsNone(prop.definition)
+        prop.dependency = ""
+        self.assertIsNone(prop.dependency)
+        prop.dependency_value = ""
+        self.assertIsNone(prop.dependency_value)
+
     def test_value(self):
         p = Property("property", 100)
         self.assertEqual(p.value[0], 100)
-        self.assertEqual(type(p.value), list)
-
-        p.append(10)
-        self.assertEqual(len(p), 2)
-        self.assertRaises(ValueError, p.append, [1, 2, 3])
-
-        p.extend([20, 30, '40'])
-        self.assertEqual(len(p), 5)
-        with self.assertRaises(ValueError):
-            p.append('invalid')
-        with self.assertRaises(ValueError):
-            p.extend(('5', 6, 7))
-
-        p2 = Property("property 2", 3)
-        self.assertRaises(ValueError, p.append, p2)
-        p.extend(p2)
-        self.assertEqual(len(p), 6)
+        self.assertIsInstance(p.value, list)
 
         p.value = None
         self.assertEqual(len(p), 0)
@@ -46,42 +87,178 @@ class TestProperty(unittest.TestCase):
         p.value = ()
         self.assertEqual(len(p), 0)
 
-        p3 = Property("test", value=2, unit="Hz")
-        p4 = Property("test", value=5.5, unit="s")
+        p.value.append(5)
+        self.assertEqual(len(p.value), 0)
+
+        p2 = Property("test", {"name": "Marie", "name": "Johanna"})
+        self.assertEqual(len(p2), 1)
+
+        # Test tuple dtype value.
+        t = Property(name="Location", value='(39.12; 67.19)', dtype='2-tuple')
+        tuple_value = t.value[0]  # As the formed tuple is a list of list
+        self.assertEqual(tuple_value[0], '39.12')
+        self.assertEqual(tuple_value[1], '67.19')
 
+        # Test invalid tuple length
         with self.assertRaises(ValueError):
-            p3.append(p4)
+            _ = Property(name="Public-Key", value='(5689; 1254; 687)', dtype='2-tuple')
 
-        p.value.append(5)
-        self.assertEqual(len(p.value), 0)
-        self.assertRaises(ValueError, p.append, 5.5)
+    def test_value_append(self):
+        # Test append w/o Property value or dtype
+        prop = Property(name="append")
+        prop.append(1)
+        self.assertEqual(prop.dtype, DType.int)
+        self.assertEqual(prop.value, [1])
+
+        # Test append with Property dtype.
+        prop = Property(name="append", dtype="int")
+        prop.append(3)
+        self.assertEqual(prop.value, [3])
+
+        # Test append with Property value
+        prop = Property(name="append", value=[1, 2])
+        prop.append(3)
+        self.assertEqual(prop.value, [1, 2, 3])
+
+        # Test append with Property list value
+        prop = Property(name="append", value=[1, 2])
+        prop.append([3])
+        self.assertEqual(prop.value, [1, 2, 3])
+
+        # Test append of empty values, make sure 0 and False are properly handled
+        prop = Property(name="append")
+        prop.append(None)
+        prop.append("")
+        prop.append([])
+        prop.append({})
+        self.assertEqual(prop.value, [])
+
+        prop.append(0)
+        self.assertEqual(prop.value, [0])
+
+        prop.value = None
+        prop.dtype = None
+        prop.append(False)
+        self.assertEqual(prop.value, [False])
+
+        prop = Property(name="append", value=[1, 2])
+        prop.append(None)
+        prop.append("")
+        prop.append([])
+        prop.append({})
+        self.assertEqual(prop.value, [1, 2])
 
-        p.append(5.5, strict=False)
-        self.assertEqual(len(p), 1)
+        prop.append(0)
+        self.assertEqual(prop.value, [1, 2, 0])
 
-        self.assertRaises(ValueError, p.extend, [3.14, 6.28])
-        p.extend([3.14, 6.28], strict=False)
-        self.assertEqual(len(p), 3)
+        # Test fail append with multiple values
+        prop = Property(name="append", value=[1, 2, 3])
+        with self.assertRaises(ValueError):
+            prop.append([4, 5])
+        self.assertEqual(prop.value, [1, 2, 3])
+
+        # Test fail append with mismatching dtype
+        prop = Property(name="append", value=[1, 2], dtype="int")
+        with self.assertRaises(ValueError):
+            prop.append([3.14])
+        with self.assertRaises(ValueError):
+            prop.append([True])
+        with self.assertRaises(ValueError):
+            prop.append(["5.927"])
+        self.assertEqual(prop.value, [1, 2])
+
+        # Test strict flag
+        prop.append(3.14, strict=False)
+        prop.append(True, strict=False)
+        prop.append("5.927", strict=False)
+        self.assertEqual(prop.value, [1, 2, 3, 1, 5])
+
+        # Make sure non-convertible values still raise an error
+        with self.assertRaises(ValueError):
+            prop.append("invalid")
+        self.assertEqual(prop.value, [1, 2, 3, 1, 5])
 
         p5 = Property("test", value="a string")
         p5.append("Freude")
         self.assertEqual(len(p5), 2)
         self.assertRaises(ValueError, p5.append, "[a, b, c]")
-        p5.extend("[a, b, c]")
-        self.assertEqual(len(p5), 5)
 
-        p6 = Property("test", {"name": "Marie", "name": "Johanna"})
-        self.assertEqual(len(p6), 1)
+    def test_value_extend(self):
+        prop = Property(name="extend")
 
-        # Test tuple dtype value.
-        t = Property(name="Location", value='(39.12; 67.19)', dtype='2-tuple')
-        tuple_value = t.value[0]  # As the formed tuple is a list of list
-        self.assertEqual(tuple_value[0], '39.12')
-        self.assertEqual(tuple_value[1], '67.19')
+        # Test extend w/o Property value or dtype.
+        val = [1, 2, 3]
+        prop.extend(val)
+        self.assertEqual(prop.dtype, DType.int)
+        self.assertEqual(prop.value, val)
 
-        # Test invalid tuple length
+        # Extend with single value.
+        prop.extend(4)
+        self.assertEqual(prop.value, [1, 2, 3, 4])
+
+        # Extend with list value.
+        prop.extend([5, 6])
+        self.assertEqual(prop.value, [1, 2, 3, 4, 5, 6])
+
+        # Test extend w/o Property value
+        prop = Property(name="extend", dtype="float")
+        prop.extend([1.0, 2.0, 3.0])
+        self.assertEqual(prop.value, [1.0, 2.0, 3.0])
+
+        # Test extend with Property value
+        prop = Property(name="extend", value=10)
+        prop.extend([20, 30, '40'])
+        self.assertEqual(prop.value, [10, 20, 30, 40])
+
+        # Test extend fail with mismatching dtype
         with self.assertRaises(ValueError):
-            _ = Property(name="Public-Key", value='(5689; 1254; 687)', dtype='2-tuple')
+            prop.extend(['5', 6, 7])
+        with self.assertRaises(ValueError):
+            prop.extend([5, 6, 'a'])
+
+        # Test extend via Property
+        prop = Property(name="extend", value=["a", "b"])
+        ext_prop = Property(name="value extend", value="c")
+        prop.extend(ext_prop)
+        self.assertEqual(prop.value, ["a", "b", "c"])
+
+        ext_prop.value = ["d", "e"]
+        prop.extend(ext_prop)
+        self.assertEqual(prop.value, ["a", "b", "c", "d", "e"])
+
+        ext_prop = Property(name="value extend", value=[1, 2 ,3])
+        with self.assertRaises(ValueError):
+            prop.extend(ext_prop)
+        self.assertEqual(prop.value, ["a", "b", "c", "d", "e"])
+
+        # Test extend via Property unit check
+        prop = Property(name="extend", value=[1, 2], unit="mV")
+        ext_prop = Property(name="extend", value=[3, 4], unit="mV")
+        prop.extend(ext_prop)
+        self.assertEqual(prop.value, [1, 2, 3, 4])
+
+        ext_prop.unit = "kV"
+        with self.assertRaises(ValueError):
+            prop.extend(ext_prop)
+        self.assertEqual(prop.value, [1, 2, 3, 4])
+
+        ext_prop.unit = ""
+        with self.assertRaises(ValueError):
+            prop.extend(ext_prop)
+        self.assertEqual(prop.value, [1, 2, 3, 4])
+
+        # Test strict flag
+        prop = Property(name="extend", value=[1, 2], dtype="int")
+        with self.assertRaises(ValueError):
+            prop.extend([3.14, True, "5.927"])
+        self.assertEqual(prop.value, [1, 2])
+
+        prop.extend([3.14, True, "5.927"], strict=False)
+        self.assertEqual(prop.value, [1, 2, 3, 1, 5])
+
+        # Make sure non-convertible values still raise an error
+        with self.assertRaises(ValueError):
+            prop.extend([6, "some text"])
 
     def test_get_set_value(self):
         values = [1, 2, 3, 4, 5]
@@ -150,9 +327,6 @@ class TestProperty(unittest.TestCase):
         assert(p.dtype == 'string')
         assert(p.value == ['7', '20', '1 Dog', 'Seven'])
 
-    def test_name(self):
-        pass
-
     def test_parent(self):
         p = Property("property_section", parent=Section("S"))
         self.assertIsInstance(p.parent, BaseSection)
@@ -206,6 +380,12 @@ class TestProperty(unittest.TestCase):
         with self.assertRaises(AttributeError):
             prop.dtype = "x-tuple"
 
+        # Test not setting None when a property contains values.
+        prop.value = [1, 2, 3]
+        self.assertIsNotNone(prop.dtype)
+        prop.dtype = None
+        self.assertIsNotNone(prop.dtype)
+
     def test_get_path(self):
         doc = Document()
         sec = Section(name="parent", parent=doc)
@@ -218,14 +398,6 @@ class TestProperty(unittest.TestCase):
         prop.parent = sec
         self.assertEqual("/%s:%s" % (sec.name, prop.name), prop.get_path())
 
-    def test_value_origin(self):
-        p = Property("P")
-        self.assertEqual(p.value_origin, None)
-        p = Property("P", value_origin="V")
-        self.assertEqual(p.value_origin, "V")
-        p.value_origin = ""
-        self.assertEqual(p.value_origin, None)
-
     def test_id(self):
         p = Property(name="P")
         self.assertIsNotNone(p.id)
diff --git a/test/test_property_integration.py b/test/test_property_integration.py
index 479883f..cf30d59 100644
--- a/test/test_property_integration.py
+++ b/test/test_property_integration.py
@@ -106,6 +106,7 @@ class TestPropertyIntegration(unittest.TestCase):
         self.assertEqual(jprop.unit, p_unit)
         self.assertEqual(jprop.uncertainty, p_uncertainty)
         self.assertEqual(jprop.reference, p_ref)
+        self.assertEqual(jprop.definition, p_def)
         self.assertEqual(jprop.dependency, p_dep)
         self.assertEqual(jprop.dependency_value, p_dep_val)
 
@@ -116,6 +117,7 @@ class TestPropertyIntegration(unittest.TestCase):
         self.assertEqual(xprop.unit, p_unit)
         self.assertEqual(xprop.uncertainty, p_uncertainty)
         self.assertEqual(xprop.reference, p_ref)
+        self.assertEqual(xprop.definition, p_def)
         self.assertEqual(xprop.dependency, p_dep)
         self.assertEqual(xprop.dependency_value, p_dep_val)
 
@@ -126,5 +128,6 @@ class TestPropertyIntegration(unittest.TestCase):
         self.assertEqual(yprop.unit, p_unit)
         self.assertEqual(yprop.uncertainty, p_uncertainty)
         self.assertEqual(yprop.reference, p_ref)
+        self.assertEqual(yprop.definition, p_def)
         self.assertEqual(yprop.dependency, p_dep)
         self.assertEqual(yprop.dependency_value, p_dep_val)

pip install -e .
parse_log_pytest
lxml enum34 pyyaml rdflib
pytest
apt-get update apt-get install -y libxml2-dev libxslt1-dev lib32z1-dev
3.5
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
brotlipy==0.7.0
certifi==2021.5.30
cffi @ file:///tmp/build/80754af9/cffi_1625814693874/work
charset-normalizer @ file:///tmp/build/80754af9/charset-normalizer_1630003229654/work
cryptography @ file:///tmp/build/80754af9/cryptography_1635366128178/work
html5lib @ file:///Users/ktietz/demo/mc3/conda-bld/html5lib_1629144453894/work
idna @ file:///tmp/build/80754af9/idna_1637925883363/work
importlib-metadata==4.8.3
iniconfig==1.1.1
isodate @ file:///Users/ktietz/demo/mc3/conda-bld/isodate_1630584690429/work
keepalive @ file:///home/conda/feedstock_root/build_artifacts/keepalive_1635948558527/work
lxml @ file:///tmp/build/80754af9/lxml_1616442911898/work
-e git+https://github.com/G-Node/python-odml.git@c16f9891c4363dfcf907fd7daa076acba4cbe5eb#egg=odML
packaging==21.3
pluggy==1.0.0
py==1.11.0
pycparser @ file:///tmp/build/80754af9/pycparser_1636541352034/work
pyOpenSSL @ file:///opt/conda/conda-bld/pyopenssl_1643788558760/work
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
PySocks @ file:///tmp/build/80754af9/pysocks_1605305763431/work
pytest==7.0.1
PyYAML==5.4.1
rdflib @ file:///home/conda/feedstock_root/build_artifacts/rdflib_1610581402529/work
requests @ file:///opt/conda/conda-bld/requests_1641824580448/work
six @ file:///tmp/build/80754af9/six_1644875935023/work
SPARQLWrapper @ file:///home/conda/feedstock_root/build_artifacts/sparqlwrapper_1629916978493/work
tomli==1.2.3
typing_extensions==4.1.1
urllib3 @ file:///opt/conda/conda-bld/urllib3_1643638302206/work
webencodings==0.5.1
zipp==3.6.0

name: python-odml
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - brotlipy=0.7.0=py36h27cfd23_1003
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - cffi=1.14.6=py36h400218f_0
  - charset-normalizer=2.0.4=pyhd3eb1b0_0
  - cryptography=35.0.0=py36hd23ed53_0
  - enum34=1.1.10=py36h06a4308_0
  - html5lib=1.1=pyhd3eb1b0_0
  - icu=58.2=he6710b0_3
  - idna=3.3=pyhd3eb1b0_0
  - isodate=0.6.0=pyhd3eb1b0_1
  - keepalive=0.5=pyhd8ed1ab_6
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - libxml2=2.9.14=h74e7548_0
  - libxslt=1.1.35=h4e12654_0
  - lxml=4.6.3=py36h9120a33_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - pycparser=2.21=pyhd3eb1b0_0
  - pyopenssl=22.0.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pysocks=1.7.1=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - python_abi=3.6=2_cp36m
  - pyyaml=5.4.1=py36h27cfd23_1
  - rdflib=5.0.0=py36h5fab9bb_3
  - readline=8.2=h5eee18b_0
  - requests=2.27.1=pyhd3eb1b0_0
  - setuptools=58.0.4=py36h06a4308_0
  - six=1.16.0=pyhd3eb1b0_1
  - sparqlwrapper=1.8.5=py36h5fab9bb_1006
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - urllib3=1.26.8=pyhd3eb1b0_0
  - webencodings=0.5.1=py36_1
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - yaml=0.2.5=h7b6447c_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pytest==7.0.1
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/python-odml

test/test_property.py::TestProperty::test_simple_attributes test/test_property.py::TestProperty::test_value_append
test/test_property.py::TestProperty::test_bool_conversion test/test_property.py::TestProperty::test_clone test/test_property.py::TestProperty::test_dtype test/test_property.py::TestProperty::test_get_merged_equivalent test/test_property.py::TestProperty::test_get_path test/test_property.py::TestProperty::test_get_set_value test/test_property.py::TestProperty::test_id test/test_property.py::TestProperty::test_merge test/test_property.py::TestProperty::test_new_id test/test_property.py::TestProperty::test_parent test/test_property.py::TestProperty::test_str_to_int_convert test/test_property.py::TestProperty::test_value test/test_property.py::TestProperty::test_value_extend test/test_property_integration.py::TestPropertyIntegration::test_id test/test_property_integration.py::TestPropertyIntegration::test_simple_attributes
odml/property.py
odml/property.py