diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7e92345efdf7e3c3c94928324c8e31bbee6797a..73403111ac141553237a3f1691adc22ad2183a16 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,38 +1,96 @@
-# Changelog
+# Changelog #
+
 All notable changes to this project will be documented in this file.
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [Unreleased] ##
+
+### Added ###
+
+* Empty string support (See caosdb-server#33)
+
+### Changed ###
+
+* `get_property` method also accepts instances of properties now, e.g.
+  `record.get_property(Property(name="length"))`
+* the value of properties is parsed to python types (int, float, boolean) when
+  setting the value with the setter and when the datatype changes. Before this
+  change, the value was parsed to python types only when parsing an xml and
+  only for int and float.
+
+### Deprecated ###
+
+### Removed ###
+
+### Fixed ###
+
+- Replaced deprecated Logger.warn() method.
 
+### Security ###
 
+## [0.3.0] - 2020-04-24##
 
-## [Unreleased]
+### Added ###
+
+* `apiutils.apply_to_ids` -- a helper which applies a function to all ids which
+  are used by an entity (own entity, parents, properties, references etc.).
+
+### Changed ###
+
+### Deprecated ###
+
+### Fixed ###
+
+* import bugs in apiutils
+
+## [0.2.4] -- 2020-04-23
 
 ### Added
-- An `auth_token` parameter for `caosdb.configure_connection(...)`. This parameter accepts a plain text auth token (which can only be issued by the CaosDB Server). Under the hood, auth tokens are stored plain, instead of urlencoded now.
+
+- An `auth_token` parameter for `caosdb.configure_connection(...)`. This
+  parameter accepts a plain text auth token (which can only be issued by the
+  CaosDB Server). Under the hood, auth tokens are stored plain, instead of
+  urlencoded now.
 - New type of exception: `ConfigurationException` for misconfigurations.
 - Some unit tests, mainly for the `caosdb.connection.authentication` module
-* Advanced setup.py for easy versioning and publication as pypi repository.
+- Advanced setup.py for easy versioning and publication as pypi repository.
+- `caosdb.apiutils` has new functions `id_query` and
+  `retrieve_entities_with_ids`
+- New exception: `EntityDoesNotExistError`
+- `RELEASE_GUIDELINES.md` with release instructions.
+- More documentation and tests.
 
 ### Changed
-- [pytest](https://docs.pytest.org/en/latest/) is the new preferred unit test frame work.
-- If a password is specified in the configuration even though the password_method is not set to `plain`, a warning is logged.
-- Under the hood, the password of from a `pass` or `keyring` call is not stored anymore. Instead the password is requested each time a login is necessary.
-- Always load system default CA repository into the ssl context
 
+- [pytest](https://docs.pytest.org/en/latest/) is the new preferred unit test
+  frame work.
+- If a password is specified in the configuration even though the
+  password_method is not set to `plain`, a warning is logged.
+- Under the hood, the password of from a `pass` or `keyring` call is not stored
+  anymore. Instead the password is requested each time a login is necessary.
+- Always load system default CA repository into the ssl context.
+- Datatypes are now in `caosdb.common.datatype` (though still available in the
+  main `caosdb` namespace).
+- Logging to stdout is now more configurable.
 
 ### Deprecated
-- Unit test frame work: [Nose](https://nose.readthedocs.io/en/latest/) should not be used anymore. Please use [pytest](https://docs.pytest.org/en/latest/) instead.
+
+- Unit test frame work: [Nose](https://nose.readthedocs.io/en/latest/) should
+  not be used anymore. Please use [pytest](https://docs.pytest.org/en/latest/)
+  instead.
 
 ### Fixed
+
 - #1 - Problems with pass as a credentials provider
 - #3 - Python client does login before the first request to circumvent problems
   with anonymous role.
+- Many other fixes
 
 
+## [0.1.0] - 2018-10-09 ##
 
-## [0.1.0] - 2018-10-09
 Tag `v0.1` - Commit 6fc0dcaa
 
 
diff --git a/README.md b/README.md
index 242081ba042969b4728ec330ac8d2f4d93626bc9..ef26a604905d5140ae9a775065002af35ffe2121 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ project](https://gitlab.com/caosdb/caosdb) for more information.
 
 Copyright (C) 2018 Research Group Biomedical Physics, Max Planck Institute for
 Dynamics and Self-Organization Göttingen.
+Copyright (C) 2020 Indiscale GmbH <info@indiscale.com>
 
 All files in this repository are licensed under a [GNU Affero General Public
 License](LICENCE.md) (version 3 or later).
diff --git a/RELEASE_GUIDELINES.md b/RELEASE_GUIDELINES.md
index 2f53e48f0541a30c6812a96cfe7613267ada5065..02be5c1ad19f6a3a405fb08d62e23dab350ad445 100644
--- a/RELEASE_GUIDELINES.md
+++ b/RELEASE_GUIDELINES.md
@@ -1,4 +1,4 @@
-# Release Guidelines for the CaosDB MySQL Backend
+# Release Guidelines for the CaosDB Python Client Library
 
 This document specifies release guidelines in addition to the generel release
 guidelines of the CaosDB Project
@@ -18,7 +18,9 @@ guidelines of the CaosDB Project
 
 2. Check all general prerequisites.
 
-3. Prepare the [setup.py](./setup.py): Update the `MAJOR`, `MINOR`, `MICRO`, `PRE` variables and set `ISRELEASED` to `True`. Use the possibility to issue pre-release versions for testing.
+3. Prepare [setup.py](./setup.py): Update the `MAJOR`, `MINOR`, `MICRO`, `PRE`
+   variables and set `ISRELEASED` to `True`. Use the possibility to issue
+   pre-release versions for testing.
 
 4. Merge the release branch into the master branch.
 
@@ -26,7 +28,9 @@ guidelines of the CaosDB Project
 
 6. Delete the release branch.
 
-7. Publish the release by executing `./release.sh` with uploads the caosdb
+7. Remove possibly existing `./dist` directory with old release.
+
+8. Publish the release by executing `./release.sh` with uploads the caosdb
    module to the Python Package Index [pypi.org](https://pypi.org).
 
-8. Merge the master branch back into the dev branch.
+9. Merge the master branch back into the dev branch.
diff --git a/release.sh b/release.sh
old mode 100644
new mode 100755
index dd469f3a44633113154419b15da1cfb97f30a38a..a5f3654291743e5ac22fd3b938719e294b3a1e90
--- a/release.sh
+++ b/release.sh
@@ -1,3 +1,4 @@
 #!/bin/bash
+rm -r dist/ build/ .eggs/
 python setup.py sdist bdist_wheel
 python -m twine upload -s dist/*
diff --git a/setup.py b/setup.py
index 7ab1f2c62de98ad2a62572bffe96ac73913ebf88..8893a126a7a02d7646625af7fc82787238344173 100755
--- a/setup.py
+++ b/setup.py
@@ -46,11 +46,15 @@ from setuptools import find_packages, setup
 ########################################################################
 
 MAJOR = 0
-MINOR = 2
-MICRO = 4
-PRE = "rc0"
-ISRELEASED = True
-VERSION = "{}.{}.{}{}".format(MAJOR, MINOR, MICRO, PRE)
+MINOR = 3
+MICRO = 2
+PRE = ""  # e.g. rc0, alpha.1, 0.beta-23
+ISRELEASED = False
+
+if PRE:
+    VERSION = "{}.{}.{}-{}".format(MAJOR, MINOR, MICRO, PRE)
+else:
+    VERSION = "{}.{}.{}".format(MAJOR, MINOR, MICRO)
 
 
 # Return the git revision as a string
diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py
index f3887099a93d50740a3b2825bc6e8a9677509079..bd279fcfe5c394b9b5cff787169cff5b9f2d3031 100644
--- a/src/caosdb/apiutils.py
+++ b/src/caosdb/apiutils.py
@@ -5,6 +5,8 @@
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -34,7 +36,8 @@ from subprocess import call
 from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
                                     REFERENCE, TEXT)
 from caosdb.common.models import (Container, Entity, File, Property, Query,
-                                  Record, RecordType, get_config)
+                                  Record, RecordType, get_config,
+                                  execute_query, is_reference)
 
 
 def new_record(record_type, name=None, description=None,
@@ -85,11 +88,11 @@ def new_record(record_type, name=None, description=None,
 def id_query(ids):
     q = "FIND Entity with " + " OR ".join(["id={}".format(id) for id in ids])
 
-    return db.execute_query(q)
+    return execute_query(q)
 
 
 def retrieve_entities_with_ids(entities):
-    collection = db.Container()
+    collection = Container()
     step = 20
 
     for i in range(len(entities)//step+1):
@@ -669,3 +672,36 @@ def describe_diff(olddiff, newdiff, name=None, as_update=True):
                        "version of {}\n\n".format(name))+description
 
     return description
+
+
+def apply_to_ids(entities, func):
+    """ Apply a function to all ids.
+
+    All ids means the ids of the entities themselves but also to all parents,
+    properties and referenced entities.
+
+    Parameters
+    ----------
+    entities : list of Entity
+    func : function with one parameter.
+    """
+    for entity in entities:
+        _apply_to_ids_of_entity(entity, func)
+
+
+def _apply_to_ids_of_entity(entity, func):
+    entity.id = func(entity.id)
+
+    for par in entity.parents:
+        par.id = func(par.id)
+
+    for prop in entity.properties:
+        prop.id = func(prop.id)
+        isref = is_reference(prop.datatype)
+
+        if isref:
+            if isinstance(prop.value, list):
+                prop.value = [func(el) for el in prop.value]
+            else:
+                if prop.value is not None:
+                    prop.value = func(prop.value)
diff --git a/src/caosdb/common/datatype.py b/src/caosdb/common/datatype.py
index f40b79f9819ea74461f8fcf7135f9baff69ac526..246485c3957462fc98ac83f9d904413ad7518302 100644
--- a/src/caosdb/common/datatype.py
+++ b/src/caosdb/common/datatype.py
@@ -3,7 +3,9 @@
 # ** header v3.0
 # This file is a part of the CaosDB Project.
 #
+# Copyright (C) 2020 IndiScale GmbH
 # Copyright (C) 2020 Henrik tom Wörden, IndiScale GmbH
+# Copyright (C) 2020 Daniel Hornung (d.hornung@indiscale.com)
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -43,7 +45,7 @@ def LIST(datatype):
 
 def get_list_datatype(datatype):
     """ returns the datatype of the elements in the list """
-    match = re.match("LIST(<|&lt;)(?P<datatype>.*)(>|&gt;)", "LISTING")
+    match = re.match("LIST(<|&lt;)(?P<datatype>.*)(>|&gt;)", datatype)
 
     if match is not None:
         return match.group("datatype")
@@ -65,7 +67,6 @@ def is_reference(datatype):
     """
 
     if datatype in [DOUBLE, BOOLEAN, INTEGER, TEXT, DATETIME]:
-
         return False
     elif is_list_datatype(datatype):
         return is_reference(get_list_datatype(datatype))
@@ -109,7 +110,7 @@ def get_id_of_datatype(datatype):
         raise AmbiguityException(
             "Name {} did not lead to unique result; Missing "
             "implementation".format(datatype))
-    elif len(res) == 1:
+    elif len(res) != 1:
         raise EntityDoesNotExistError(
             "No RecordType named {}".format(datatype))
 
diff --git a/src/caosdb/common/models.py b/src/caosdb/common/models.py
index 508a2c53a14bfe0816269bf1dd64b3f99554fec8..5ab31f482454a408c8b692e24adea4099a28f6cc 100644
--- a/src/caosdb/common/models.py
+++ b/src/caosdb/common/models.py
@@ -38,8 +38,8 @@ from sys import hexversion
 from tempfile import NamedTemporaryFile
 from warnings import warn
 
-from lxml import etree
-
+from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
+                                    LIST, REFERENCE, TEXT, is_reference)
 from caosdb.common.utils import uuid, xml2str
 from caosdb.configuration import get_config
 from caosdb.connection.connection import get_connection
@@ -51,8 +51,9 @@ from caosdb.exceptions import (AmbiguityException, AuthorizationException,
                                EntityHasNoDatatypeError, TransactionError,
                                UniqueNamesError, UnqualifiedParentsError,
                                UnqualifiedPropertiesError, URITooLongException)
-from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
-                                    LIST, REFERENCE, TEXT, is_reference)
+from lxml import etree
+
+from .datatype import is_reference
 
 _ENTITY_URI_SEGMENT = "Entity"
 
@@ -81,27 +82,29 @@ class Entity(object):
     def __init__(self, name=None, id=None, description=None,  # @ReservedAssignment
                  datatype=None, value=None, **kwargs):
         self.__role = kwargs["role"] if "role" in kwargs else None
-        self.name = name
-        self.description = description
-        self.id = id
-        self.value = value
+        self._checksum = None
+        self._size = None
+        self._upload = None
+        self._wrapped_entity = None
+        self._cuid = None
+        self._flags = dict()
+        self.__value = None
+        self.__datatype = None
         self.datatype = datatype
+        self.value = value
         self.messages = _Messages()
         self.properties = _Properties()
         self.parents = _Parents()
         self.path = None
         self.file = None
-        self._checksum = None
-        self._size = None
-        self._upload = None
         self.unit = None
-        self._cuid = None
         self.acl = None
         self.permissions = None
-        self._wrapped_entity = None
-        self._flags = dict()
         self.is_valid = lambda: False
         self.is_deleted = lambda: False
+        self.name = name
+        self.description = description
+        self.id = id
 
     @property
     def role(self):
@@ -158,6 +161,8 @@ class Entity(object):
 
     @datatype.setter
     def datatype(self, new_type):
+        # re-parse value
+        self.__value = _parse_value(new_type, self.__value)
         self.__datatype = new_type
 
     @property
@@ -195,7 +200,7 @@ class Entity(object):
 
     @value.setter
     def value(self, new_value):
-        self.__value = new_value
+        self.__value = _parse_value(self.datatype, new_value)
 
     @property
     def path(self):
@@ -536,17 +541,48 @@ class Entity(object):
 
         return self.properties
 
-    def get_property(self, key):
-        if isinstance(key, int):
+    def get_property(self, pattern):
+        """ Return the first matching property or None.
+
+        Parameters
+        ----------
+        pattern : str or int or Entity
+            The name or id to look for (case-insensitive) or an Entity where
+            the name or id is used to match the properites of this instance.
+
+        Returns
+        -------
+        property : Property
+            The first Property of this Entity with a matching name or id.
+
+        """
+        # entity given
+
+        if (hasattr(pattern, "name") or hasattr(pattern, "id")):
+            # only return if a result was found, otherwise use id
+
+            if (hasattr(pattern, "name") and pattern.name is not None
+                    and self.get_property(pattern.name) is not None):
+
+                return self.get_property(pattern.name)
+
+            if hasattr(pattern, "id") and pattern.id is not None:
+                return self.get_property(pattern.id)
+
+        # int given
+        elif isinstance(pattern, int):
             for p in self.properties:
-                if p.id is not None and int(p.id) == int(key):
+                if p.id is not None and int(p.id) == int(pattern):
                     return p
-        else:
+        # str given
+        elif isinstance(pattern, str):
             for p in self.properties:
                 if (p.name is not None
-                        and str(p.name).lower() == str(key).lower()):
+                        and str(p.name).lower() == str(pattern).lower()):
 
                     return p
+        else:
+            raise ValueError("argument should be entity, int , string")
 
         return None
 
@@ -784,22 +820,11 @@ class Entity(object):
                     Was ' + str(type(child)))
 
         # parse VALUE
-
         if len(vals):
-            entity.value = _parse_col_values(entity.datatype, vals)
-        elif elem.text is not None:
-            if elem.text.strip() != "":
-                text_val = elem.text.strip()
-
-                if entity.datatype == DOUBLE:
-                    entity.value = float(text_val)
-                elif entity.datatype == DATETIME or entity.datatype == TEXT:
-                    entity.value = text_val
-                else:
-                    try:  # for references  and integer
-                        entity.value = int(text_val)
-                    except BaseException:
-                        entity.value = text_val
+            # The value[s] have been inside a <Value> tag.
+            entity.value = vals
+        elif elem.text is not None and elem.text.strip() != "":
+            entity.value = elem.text.strip()
 
         return entity
 
@@ -945,35 +970,66 @@ class Entity(object):
         return self
 
 
-def _parse_col_values(cdt, vals):
-    matcher = re.compile(r"^(?P<col>[^<]+)<(?P<dt>[^>]+)>$")
-    m = matcher.match(cdt)
-    if m:
-        col = m.group("col")
-        dt = m.group("dt")
-
-        if col == "LIST":
-            ret = list()
-            add = ret.append
+def _parse_value(datatype, value):
+    if value is None:
+        return value
+    if datatype is None:
+        return value
+    if datatype == DOUBLE:
+        return float(value)
+    if datatype == INTEGER:
+        return int(str(value))
+    if datatype == BOOLEAN:
+        if str(value).lower() == "true":
+            return True
+        elif str(value).lower() == "false":
+            return False
         else:
-            return vals
+            raise ValueError("Boolean value was {}.".format(value))
+    if datatype in [DATETIME, TEXT]:
+        if isinstance(value, str):
+            return value
+
+    # deal with collections
+    if isinstance(datatype, str):
+        matcher = re.compile(r"^(?P<col>[^<]+)<(?P<dt>[^>]+)>$")
+        m = matcher.match(datatype)
+        if m:
+            col = m.group("col")
+            dt = m.group("dt")
+
+            if col == "LIST":
+                ret = list()
+            else:
+                return value
 
-        for v in vals:
-            if dt == DOUBLE:
-                add(float(v))
-            elif dt == TEXT or dt == DATETIME:
-                add(v)
+            if hasattr(value, "__iter__") and not isinstance(value, str):
+                for v in value:
+                    ret.append(_parse_value(dt, v))
             else:
-                try:
-                    add(int(v))
-                except BaseException:
-                    add(v)
+                # put a single value into a list since the datatype says so.
+                ret.append(_parse_value(dt, value))
 
-        return ret
+            return ret
 
-    if len(vals) == 1:
-        return vals[0]
-    return vals
+    # This is for a special case, where the xml parser could not differentiate
+    # between single values and lists with one element. As
+    if hasattr(value, "__len__") and len(value) == 1:
+        return _parse_value(datatype, value[0])
+
+    # deal with references
+    if isinstance(value, Entity):
+        return value
+    if isinstance(value, str) and "@" in value:
+        # probably this is a versioned reference
+        return str(value)
+    else:
+        # for unversioned references
+        try:
+            return int(value)
+        except ValueError:
+            # reference via name
+            return str(value)
 
 
 def _log_request(request, xml_body=None):
diff --git a/src/caosdb/connection/connection.py b/src/caosdb/connection/connection.py
index 3553c86ca844ca0d83852985caa67158fdbda36b..5fbca32ed9a8d8f5028b340821c84a2b65ef03a4 100644
--- a/src/caosdb/connection/connection.py
+++ b/src/caosdb/connection/connection.py
@@ -178,10 +178,10 @@ class _DefaultCaosDBServerConnection(CaosDBServerConnection):
         context.verify_mode = ssl.CERT_REQUIRED
 
         if config.get("ssl_insecure"):
-            _LOGGER.warn("*** Warning! ***\n"
-                         "Insecure SSL mode, certificate will not be checked! "
-                         "Please consider removing the `ssl_insecure` configuration option.\n"
-                         "****************")
+            _LOGGER.warning("*** Warning! ***\n"
+                            "Insecure SSL mode, certificate will not be checked! "
+                            "Please consider removing the `ssl_insecure` configuration option.\n"
+                            "****************")
             context.verify_mode = ssl.CERT_NONE
 
         if (not context.verify_mode == ssl.CERT_NONE and
diff --git a/unittests/record.py b/unittests/record.py
deleted file mode 100644
index 22e7676bbd50cf060f534e655bc29dd2b512a0bc..0000000000000000000000000000000000000000
--- a/unittests/record.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# -*- encoding: utf-8 -*-
-#
-# ** header v3.0
-# This file is a part of the CaosDB Project.
-#
-# Copyright (C) 2018 Research Group Biomedical Physics,
-# Max-Planck-Institute for Dynamics and Self-Organization Göttingen
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# ** end header
-#
-# Test record for test_apiutils
-# A. Schlemmer, 02/2018
-
-import caosdb as db
-from lxml import etree
-
-# This is Record ID 171179 from the current CaosDB
-testrecord1 = db.Record._from_xml(db.Record(), etree.fromstring("""<Record id="171179"><TransactionBenchmark></TransactionBenchmark><Parent id="163454" name="LeapExperiment" description="Experiment for the LEAP project."/><Property id="163414" name="experimentId" description="A unique identifier for experiments" datatype="TEXT" importance="FIX" flag="inheritance:FIX">KCdSYWJiaXQnLCAnZXhfdml2bycsICdzeW5jaHJvbml6YXRpb25fbWFwJywgTm9uZSwgJzIwMTctMDgtMTEnLCBOb25lLCBOb25lKQ==</Property><Property id="568765" name="LISTofTEXT" datatype="LIST&lt;TEXT&gt;" importance="FIX"><Value>One</Value><Value>Two</Value><Value>Three</Value><Value></Value><Value><EmptyString/></Value></Property><Property id="568765" name="EMPTYTEXT1" datatype="TEXT" importance="FIX"><Value><EmptyString/></Value></Property><Property id="568765" name="EMPTYTEXT2" datatype="TEXT" importance="FIX"><EmptyString/></Property><Property id="568765" name="NULLTEXT1" datatype="TEXT" importance="FIX"></Property><Property id="568765" name="NULLTEXT2" datatype="TEXT" importance="FIX"><Value></Value></Property><Property id="163442" name="date" description="A calendar date. When something took place." datatype="DATETIME" importance="FIX" flag="inheritance:FIX">2017-08-11</Property><Property id="163399" name="vivoness" description="How the experiment was done: IN_VIVO or EX_VIVO." datatype="TEXT" importance="FIX" flag="inheritance:FIX">ex_vivo</Property><Property id="163418" name="species" description="The species of the experimental animal." datatype="TEXT" importance="FIX" flag="inheritance:FIX">Rabbit</Property><Property id="163449" name="ExperimentSeries" description="A collection of [Experiment] records which have the same [aim]." datatype="ExperimentSeries" importance="FIX" flag="inheritance:FIX">163386</Property><Property id="163397" name="MultiRecRecording" datatype="LIST&lt;MultiRecRecording&gt;" importance="FIX" flag="inheritance:FIX"><Value>171242</Value><Value>170651</Value><Value>171701</Value><Value>172074</Value><Value>171408</Value><Value>171687</Value><Value>170791</Value><Value>171115</Value><Value>171893</Value><Value>171237</Value><Value>171309</Value><Value>170899</Value><Value>171048</Value><Value>171077</Value><Value>171723</Value><Value>171085</Value><Value>171812</Value><Value>171829</Value><Value>171669</Value><Value>170695</Value><Value>170875</Value><Value>171751</Value><Value>171412</Value><Value>172204</Value><Value>170997</Value><Value>171490</Value><Value>171504</Value><Value>170977</Value><Value>171895</Value><Value>172233</Value><Value>171261</Value><Value>171318</Value><Value>171014</Value><Value>171132</Value><Value>171575</Value><Value>172217</Value><Value>171638</Value><Value>170656</Value><Value>171927</Value><Value>172232</Value><Value>171864</Value><Value>171564</Value><Value>171090</Value><Value>171633</Value><Value>171456</Value><Value>171755</Value><Value>170641</Value><Value>172144</Value><Value>171872</Value><Value>171619</Value><Value>171180</Value><Value>172019</Value><Value>171193</Value><Value>171069</Value><Value>171643</Value><Value>171789</Value><Value>170785</Value><Value>170904</Value><Value>171130</Value><Value>171098</Value><Value>171241</Value><Value>171796</Value><Value>171776</Value><Value>171175</Value><Value>171112</Value><Value>171514</Value><Value>171854</Value><Value>170962</Value><Value>171818</Value><Value>170745</Value><Value>171149</Value><Value>170639</Value><Value>171508</Value><Value>170800</Value><Value>171141</Value><Value>171414</Value><Value>171325</Value><Value>172168</Value><Value>171184</Value><Value>172083</Value><Value>172029</Value><Value>171556</Value><Value>172195</Value><Value>170789</Value><Value>171300</Value><Value>172230</Value><Value>171720</Value><Value>171341</Value><Value>171937</Value><Value>171673</Value><Value>172106</Value><Value>171281</Value><Value>171897</Value><Value>171108</Value><Value>172014</Value><Value>170867</Value><Value>171531</Value><Value>171674</Value><Value>172077</Value><Value>170944</Value><Value>171228</Value><Value>172207</Value><Value>171039</Value><Value>171778</Value><Value>170794</Value><Value>171646</Value><Value>172027</Value><Value>171279</Value><Value>171618</Value><Value>171233</Value><Value>170811</Value><Value>171357</Value><Value>172180</Value><Value>171585</Value><Value>170774</Value><Value>171625</Value><Value>171310</Value><Value>171855</Value><Value>172084</Value><Value>171395</Value><Value>171955</Value><Value>172216</Value><Value>171705</Value><Value>171312</Value><Value>171659</Value><Value>172192</Value><Value>171157</Value><Value>171978</Value><Value>170707</Value><Value>171250</Value><Value>171929</Value><Value>171709</Value><Value>170898</Value><Value>170723</Value><Value>172060</Value><Value>171693</Value><Value>172036</Value><Value>172162</Value><Value>171460</Value><Value>172065</Value><Value>171174</Value><Value>171461</Value><Value>172093</Value><Value>171200</Value><Value>172007</Value><Value>172102</Value><Value>171368</Value><Value>171761</Value><Value>172157</Value><Value>171354</Value><Value>170698</Value><Value>171254</Value><Value>171740</Value><Value>171303</Value><Value>170874</Value><Value>171248</Value><Value>171698</Value><Value>171191</Value><Value>171948</Value><Value>171920</Value><Value>171319</Value><Value>170649</Value><Value>171731</Value><Value>170643</Value><Value>171007</Value><Value>172186</Value><Value>171831</Value><Value>172128</Value><Value>172154</Value><Value>170841</Value><Value>171530</Value><Value>171142</Value><Value>171857</Value><Value>170982</Value><Value>171852</Value><Value>171574</Value><Value>171136</Value><Value>172107</Value><Value>171819</Value><Value>171746</Value><Value>171036</Value><Value>171331</Value><Value>170682</Value><Value>171779</Value><Value>171747</Value><Value>171383</Value><Value>170748</Value><Value>170691</Value><Value>170820</Value><Value>170829</Value><Value>171888</Value><Value>172098</Value><Value>172199</Value><Value>171290</Value><Value>170935</Value><Value>171056</Value><Value>171131</Value><Value>171415</Value><Value>171105</Value><Value>171135</Value><Value>171371</Value><Value>171640</Value><Value>171534</Value><Value>171012</Value><Value>172047</Value><Value>172081</Value><Value>171666</Value><Value>172089</Value><Value>172063</Value><Value>171449</Value><Value>171159</Value><Value>171808</Value><Value>171932</Value><Value>170664</Value><Value>172000</Value><Value>171220</Value><Value>170955</Value><Value>170740</Value><Value>171350</Value><Value>171528</Value><Value>171081</Value><Value>171199</Value><Value>171711</Value><Value>171446</Value><Value>171607</Value><Value>171292</Value><Value>170762</Value><Value>171896</Value><Value>170810</Value><Value>170990</Value><Value>171332</Value><Value>171080</Value><Value>171075</Value><Value>172130</Value><Value>171525</Value><Value>171993</Value><Value>172091</Value><Value>171924</Value><Value>172153</Value><Value>170661</Value><Value>171190</Value><Value>171021</Value><Value>172158</Value><Value>171980</Value><Value>171480</Value><Value>171598</Value><Value>171827</Value><Value>172166</Value><Value>171392</Value><Value>171512</Value><Value>171008</Value><Value>171610</Value><Value>171692</Value><Value>171908</Value><Value>171733</Value><Value>170866</Value><Value>171100</Value></Property><Property id="163401" name="PulsarProtocolLog" description="A log from Pulsar. This is the generic super type. Sub types will represent the log of a particular protocol." datatype="LIST&lt;PulsarProtocolLog&gt;" importance="FIX" flag="inheritance:FIX"><Value>171750</Value><Value>171019</Value><Value>171765</Value><Value>171269</Value><Value>170700</Value><Value>171665</Value><Value>171496</Value><Value>170954</Value><Value>170780</Value><Value>171313</Value><Value>171202</Value></Property><Property id="163429" name="ACQRawData" description="A file which is the direct/raw output of Acqknowledge." datatype="ACQRawData" importance="FIX" flag="inheritance:FIX">45506</Property><Property id="163456" name="syncMapValuesFiles" description="DESCRIBE ME!" datatype="LIST&lt;FILE&gt;" importance="FIX" flag="inheritance:FIX"><Value>45508</Value><Value>45509</Value><Value>45510</Value><Value>45511</Value><Value>45512</Value><Value>45513</Value><Value>45514</Value><Value>45515</Value><Value>45516</Value><Value>45517</Value><Value>45518</Value><Value>45519</Value><Value>45520</Value><Value>45521</Value><Value>45522</Value><Value>45523</Value><Value>45524</Value><Value>45525</Value><Value>45526</Value><Value>45527</Value><Value>45528</Value><Value>45529</Value><Value>45530</Value><Value>45531</Value><Value>45532</Value></Property></Record>
-"""))
-
-testrecord2 = db.Record._from_xml(db.Record(), etree.fromstring(
-"""<Record id="43742">
-    <Permissions>
-      <Permission name="USE:AS_REFERENCE" />
-      <Permission name="USE:AS_DATA_TYPE" />
-      <Permission name="RETRIEVE:ENTITY" />
-      <Permission name="UPDATE:DESCRIPTION" />
-      <Permission name="UPDATE:FILE:ADD" />
-      <Permission name="UPDATE:FILE:MOVE" />
-      <Permission name="RETRIEVE:ACL" />
-      <Permission name="DELETE" />
-      <Permission name="RETRIEVE:OWNER" />
-      <Permission name="UPDATE:PROPERTY:ADD" />
-      <Permission name="UPDATE:ROLE" />
-      <Permission name="UPDATE:PARENT:ADD" />
-      <Permission name="RETRIEVE:FILE" />
-      <Permission name="USE:AS_PROPERTY" />
-      <Permission name="UPDATE:PARENT:REMOVE" />
-      <Permission name="USE:AS_PARENT" />
-      <Permission name="UPDATE:PROPERTY:REMOVE" />
-      <Permission name="UPDATE:NAME" />
-      <Permission name="UPDATE:DATA_TYPE" />
-      <Permission name="UPDATE:VALUE" />
-      <Permission name="RETRIEVE:HISTORY" />
-      <Permission name="EDIT:ACL" />
-      <Permission name="UPDATE:FILE:REMOVE" />
-      <Permission name="UPDATE:QUERY_TEMPLATE_DEFINITION" />
-    </Permissions>
-    <Parent id="43740" name="TestRT" />
-    <Property id="43741" name="TestProp" datatype="TEXT" importance="FIX">
-      a string
-      <Permissions>
-        <Permission name="USE:AS_REFERENCE" />
-        <Permission name="USE:AS_DATA_TYPE" />
-        <Permission name="RETRIEVE:ENTITY" />
-        <Permission name="UPDATE:DESCRIPTION" />
-        <Permission name="UPDATE:FILE:ADD" />
-        <Permission name="UPDATE:FILE:MOVE" />
-        <Permission name="RETRIEVE:ACL" />
-        <Permission name="DELETE" />
-        <Permission name="RETRIEVE:OWNER" />
-        <Permission name="UPDATE:PROPERTY:ADD" />
-        <Permission name="UPDATE:ROLE" />
-        <Permission name="UPDATE:PARENT:ADD" />
-        <Permission name="RETRIEVE:FILE" />
-        <Permission name="USE:AS_PROPERTY" />
-        <Permission name="UPDATE:PARENT:REMOVE" />
-        <Permission name="USE:AS_PARENT" />
-        <Permission name="UPDATE:PROPERTY:REMOVE" />
-        <Permission name="UPDATE:NAME" />
-        <Permission name="UPDATE:DATA_TYPE" />
-        <Permission name="UPDATE:VALUE" />
-        <Permission name="RETRIEVE:HISTORY" />
-        <Permission name="EDIT:ACL" />
-        <Permission name="UPDATE:FILE:REMOVE" />
-        <Permission name="UPDATE:QUERY_TEMPLATE_DEFINITION" />
-      </Permissions>
-    </Property>
-  </Record>"""))
-
-
-def test_null_empty_text_value_1():
-    assert testrecord1.get_property("LISTofTEXT").value == ["One", "Two", "Three", None, ""]
-
-def test_null_empty_text_value_2():
-    assert testrecord1.get_property("NULLTEXT1").value == None
-
-def test_null_empty_text_value_3():
-    assert testrecord1.get_property("NULLTEXT2").value == None
-
-def test_null_empty_text_value_4():
-    assert testrecord1.get_property("EMPTYTEXT1").value == ""
-
-def test_null_empty_text_value_5():
-    assert testrecord1.get_property("EMPTYTEXT2").value == ""
-
-def test_string_value():
-    testrecord2.get_property("TestProp").value == "a string"
diff --git a/unittests/test_add_property.py b/unittests/test_add_property.py
index bd68f31b89c439c2bd333586b65d9f012b09d7e3..874314ee62d5471a9e859d8c4dc44c4e4a6532c7 100644
--- a/unittests/test_add_property.py
+++ b/unittests/test_add_property.py
@@ -22,6 +22,7 @@
 # ** end header
 #
 import caosdb as db
+from pytest import raises
 from nose.tools import assert_is, assert_is_none, assert_equals, assert_is_not_none, assert_raises
 
 
@@ -176,19 +177,38 @@ def test_property_parameter_with_entity_and_datatype():
         unit="m",
         description="This is the length of something.")
 
-    assert_equals(0, len(rec.get_properties()))
-    rec.add_property(abstract_property, 3.14, datatype=db.INTEGER)
-    assert_equals(1, len(rec.get_properties()))
+    assert 0 == len(rec.get_properties())
+    rec.add_property(abstract_property, 300, datatype=db.INTEGER)
+    assert 1 == len(rec.get_properties())
     concrete_property = rec.get_property("length")
-    assert_is_not_none(concrete_property)
-    assert_equals(concrete_property.name, "length")
-    assert_equals(concrete_property.id, 512)
-    assert_equals(concrete_property.description,
-                  "This is the length of something.")
-    assert_equals(concrete_property.unit, "m")
-    assert_equals(concrete_property.value, 3.14)
-    assert_equals(concrete_property.datatype, db.INTEGER)
-    assert_is(concrete_property._wrapped_entity, abstract_property)
+    assert concrete_property is not None
+    assert concrete_property.name == "length"
+    assert concrete_property.id == 512
+    assert concrete_property.description == "This is the length of something."
+    assert concrete_property.unit == "m"
+    assert concrete_property.value == 300
+    assert concrete_property.datatype == db.INTEGER
+    assert id(concrete_property._wrapped_entity) == id(abstract_property)
+
+    concrete_property.value = None
+
+    with raises(ValueError):
+        # cannot parse 3.14 to integer
+        concrete_property.value = 3.14
+
+    assert concrete_property.value is None
+    assert concrete_property.datatype == db.INTEGER
+
+    concrete_property.datatype = db.DOUBLE
+    concrete_property.value = 3.14
+
+    with raises(ValueError):
+        # cannot parse 3.14 to integer
+        concrete_property.datatype = db.INTEGER
+
+    # nothing should've changed after the ValueError
+    assert concrete_property.datatype == db.DOUBLE
+    assert concrete_property.value == 3.14
 
 
 def test_kw_name_and_value():
diff --git a/unittests/test_apiutils.py b/unittests/test_apiutils.py
index 5476059344407c0c08e86dc8c15fae73b12a23c6..df6fe52d5b6f7ceddea791167a2355d7b3bf2fc8 100644
--- a/unittests/test_apiutils.py
+++ b/unittests/test_apiutils.py
@@ -5,6 +5,8 @@
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -25,9 +27,10 @@
 # A. Schlemmer, 02/2018
 
 import caosdb as db
-from .record import testrecord
+from caosdb.apiutils import apply_to_ids
 import pickle
 import tempfile
+from .test_property import testrecord
 
 
 def test_convert_object():
@@ -42,3 +45,20 @@ def test_pickle_object():
         f.seek(0)
         rn2 = pickle.load(f)
     assert r2.date == rn2.date
+
+
+def test_apply_to_ids():
+    parent = db.RecordType(id=3456)
+    rec = db.Record(id=23)
+    p = db.Property(id=23345, datatype=db.INTEGER)
+    rec.add_parent(parent)
+    rec.add_property(p)
+
+    def invert(id_):
+        return id_ * -1
+    apply_to_ids([rec], invert)
+
+    assert invert(3456) == -3456
+    assert rec.parents[0].id == -3456
+    assert rec.properties[0].id == -23345
+    assert rec.id == -23
diff --git a/unittests/test_datatype.py b/unittests/test_datatype.py
index 09b9557285f1243b00b97d600cc11ccdfa685ade..9b3c6267fb018e2cd3085dea568d7396c4549ac8 100644
--- a/unittests/test_datatype.py
+++ b/unittests/test_datatype.py
@@ -1,8 +1,89 @@
-from caosdb import LIST
-from caosdb import RecordType
+# ** header v3.0
+# This file is a part of the CaosDB Project.
+#
+# Copyright (c) 2020 IndiScale GmbH
+# Copyright (c) 2020 Daniel Hornung (d.hornung@indiscale.com)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+# ** end header
+from pytest import raises
+import caosdb as db
+from caosdb.common import datatype
+from caosdb.common.models import _parse_value
 
 
 def test_list():
-    assert LIST("RT") == "LIST<RT>"
-    assert LIST(RecordType("bla")) == "LIST<bla>"
+    assert db.LIST("RT") == "LIST<RT>"
+    assert db.LIST(db.RecordType("bla")) == "LIST<bla>"
 
+
+def test_list_utilites():
+    """Test for example if get_list_datatype works."""
+    dtype = db.LIST(db.INTEGER)
+    assert datatype.get_list_datatype(dtype) == db.INTEGER
+
+
+def test_parsing_of_intger_list_values():
+    dtype = db.LIST(db.INTEGER)
+    assert _parse_value(dtype, [1, 2, 3]) == [1, 2, 3]
+    assert _parse_value(dtype, [1]) == [1]
+    assert _parse_value(dtype, [None, 1, 2, 3]) == [None, 1, 2, 3]
+    assert _parse_value(dtype, [1, None, 1, 2, 3]) == [1, None, 1, 2, 3]
+    assert _parse_value(dtype, ["4", 4]) == [4, 4]
+    assert _parse_value(dtype, []) == []
+    assert _parse_value(dtype, None) is None
+    assert _parse_value(None, [1, 2, 3.14, "asdf"]) == [1, 2, 3.14, "asdf"]
+    assert _parse_value(dtype, 1) == [1]
+
+    with raises(ValueError):
+        # float value in list
+        _parse_value(dtype, ["4.3", 4])
+
+
+def test_parsing_of_boolean_list_values():
+    dtype = db.LIST(db.BOOLEAN)
+    assert _parse_value(dtype, [True, False, True]) == [True, False, True]
+    assert _parse_value(dtype, ["true", False, None]) == [True, False, None]
+
+    with raises(ValueError):
+        _parse_value(dtype, ["not a boolean"])
+
+
+def test_parsing_of_unknown_col_datatype():
+    dtype = "Arraay<TEXT>"
+    obj = {"a": "b"}
+    assert id(_parse_value(dtype, obj)) == id(obj)
+
+
+def test_parsing_of_references():
+    dtype = "Person"
+    assert _parse_value(dtype, "Anna Lytik") == "Anna Lytik"
+    assert _parse_value(None, "Anna Lytik") == "Anna Lytik"
+    assert _parse_value(dtype, "2345@sdfg") == "2345@sdfg"
+    assert _parse_value(dtype, "2345") == 2345
+    assert _parse_value(dtype, 2345) == 2345
+
+    entity = db.Record(name="bla")
+    assert id(_parse_value(dtype, entity)) == id(entity)
+
+    dtype = db.RecordType(name="Person")
+    assert _parse_value(dtype, "Anna Lytik") == "Anna Lytik"
+    assert _parse_value(None, "Anna Lytik") == "Anna Lytik"
+    assert _parse_value(dtype, "2345@sdfg") == "2345@sdfg"
+    assert _parse_value(dtype, "2345") == 2345
+    assert _parse_value(dtype, 2345) == 2345
+
+    entity = db.Record(name="bla")
+    assert id(_parse_value(dtype, entity)) == id(entity)
diff --git a/unittests/test_entity.py b/unittests/test_entity.py
index c3862ae253b8fa8ad5640ae79c1088a385fb752b..d877e1ab7267977a7e73d65033d6f02c16ea5521 100644
--- a/unittests/test_entity.py
+++ b/unittests/test_entity.py
@@ -22,42 +22,36 @@
 # ** end header
 #
 """Tests for the Entity class."""
+# pylint: disable=missing-docstring
 import unittest
 
-from caosdb import Entity, configure_connection
+from caosdb import (INTEGER, Entity, Property, Record, RecordType,
+                    configure_connection)
 from caosdb.connection.mockup import MockUpServerConnection
-# pylint: disable=missing-docstring
-from nose.tools import assert_equal as eq
-from nose.tools import assert_is_not_none as there
-from nose.tools import assert_true as tru
-
 
-def setup_module():
-    there(Entity)
-    configure_connection(url="unittests", username="testuser",
-                         password="testpassword", timeout=200,
-                         implementation=MockUpServerConnection)
 
+class TestEntity(unittest.TestCase):
 
-def hat(obj, attr):
-    tru(hasattr(obj, attr))
-
+    def setUp(self):
+        self.assertIsNotNone(Entity)
+        configure_connection(url="unittests", username="testuser",
+                             password="testpassword", timeout=200,
+                             implementation=MockUpServerConnection)
 
-class TestEntity(unittest.TestCase):
     def test_instance_variables(self):
         entity = Entity()
-        hat(entity, "role")
-        hat(entity, "id")
-        hat(entity, "name")
-        hat(entity, "description")
-        hat(entity, "parents")
-        hat(entity, "properties")
+        self.assertTrue(hasattr(entity, "role"))
+        self.assertTrue(hasattr(entity, "id"))
+        self.assertTrue(hasattr(entity, "name"))
+        self.assertTrue(hasattr(entity, "description"))
+        self.assertTrue(hasattr(entity, "parents"))
+        self.assertTrue(hasattr(entity, "properties"))
 
     def test_role(self):
         entity = Entity(role="TestRole")
-        eq(entity.role, "TestRole")
+        self.assertEqual(entity.role, "TestRole")
         entity.role = "TestRole2"
-        eq(entity.role, "TestRole2")
+        self.assertEqual(entity.role, "TestRole2")
 
     def test_instanciation(self):
         self.assertRaises(Exception, Entity())
diff --git a/unittests/test_property.py b/unittests/test_property.py
index 1d41a200fecb5c9b8e314fecc81ef75b45a6ec79..8b2deeb4b06cfbf3d42881201307a1e2122124e3 100644
--- a/unittests/test_property.py
+++ b/unittests/test_property.py
@@ -5,6 +5,8 @@
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -23,35 +25,62 @@
 #
 """Tests for the Property class."""
 # pylint: disable=missing-docstring
-from nose.tools import (assert_is_not_none as there, assert_true as tru,
-                        assert_equal as eq)
-from caosdb import Entity, Property, configure_connection
-from caosdb.connection.mockup import MockUpServerConnection
+from lxml import etree
+from caosdb import Entity, Property, Record
 
-
-def setup_module():
-    there(Property)
-    configure_connection(url="unittests", username="testuser",
-                         password="testpassword", timeout=200,
-                         implementation=MockUpServerConnection)
-
-
-def hat(obj, attr):
-    tru(hasattr(obj, attr))
+parser = etree.XMLParser(remove_comments=True)
+testrecord = Record._from_xml(Record(),
+                              etree.parse("unittests/test_record.xml",
+                                          parser).getroot())
 
 
 def test_is_entity():
     prop = Property()
-    tru(isinstance(prop, Entity))
+    assert isinstance(prop, Entity)
 
 
 def test_instance_variables():
     prop = Property()
-    hat(prop, "datatype")
-    hat(prop, "unit")
-    hat(prop, "value")
+    assert hasattr(prop, "datatype")
+    assert hasattr(prop, "unit")
+    assert hasattr(prop, "value")
+
+
+def test_null_empty_text_value_1():
+    assert testrecord.get_property("LISTofTEXT").value == ["One", "Two", "Three", None, ""]
+
+
+def test_null_empty_text_value_2():
+    assert testrecord.get_property("NULLTEXT1").value is None
+
+
+def test_null_empty_text_value_3():
+    assert testrecord.get_property("NULLTEXT2").value is None
+
+
+def test_null_empty_text_value_4():
+    assert testrecord.get_property("EMPTYTEXT1").value == ""
+
+
+def test_null_empty_text_value_5():
+    assert testrecord.get_property("EMPTYTEXT2").value == ""
+
+
+def test_list_of_references_with_null():
+    assert testrecord.get_property("MultiRecRecording").value[0] is None
+    assert testrecord.get_property("MultiRecRecording").value[1] == 170651
 
 
 def test_role():
     prop = Property()
-    eq(prop.role, "Property")
+    assert prop.role == "Property"
+
+
+def test_get_property_with_entity():
+    p = Property(name="Prop")
+    r = Record().add_property("Prop", "blub")
+    assert r.get_property(p).value == "blub"
+
+    p = Property(id=1234)
+    r.add_property(id=1234, value="bla")
+    assert r.get_property(p).value == "bla"
diff --git a/unittests/test_record.py b/unittests/test_record.py
index 001f91a726ae8c532a35a6d4875f434bedd3bbce..3b4eb4bbd34110706f7b0b1e88daac6c070dc1c6 100644
--- a/unittests/test_record.py
+++ b/unittests/test_record.py
@@ -26,40 +26,24 @@
 # pylint: disable=missing-docstring
 import unittest
 
-from nose.tools import assert_equal as eq
-from nose.tools import assert_is_not_none as there
-from nose.tools import assert_true as tru
-
-from caosdb import Entity, Record, configure_connection
-from caosdb.connection.mockup import MockUpServerConnection
-
-
-def setup_module():
-    there(Record)
-    configure_connection(url="unittests", username="testuser",
-                         password="testpassword", timeout=200,
-                         implementation=MockUpServerConnection)
-
-
-def hat(obj, attr):
-    tru(hasattr(obj, attr))
+from caosdb import Entity, Record
 
 
 def test_is_entity():
     record = Record()
-    tru(isinstance(record, Entity))
+    assert isinstance(record, Entity)
 
 
 def test_role():
     record = Record()
-    eq(record.role, "Record")
+    assert record.role == "Record"
 
 
 class TestRecord(unittest.TestCase):
     def test_property_access(self):
         rec = Record()
         rec.add_property("Prop")
-        self.assertIsNone(rec.get_property("Pop"))
-        self.assertIsNotNone(rec.get_property("Prop"))
-        self.assertIsNotNone(rec.get_property("prop"))
-        self.assertIsNotNone(rec.get_property("prOp"))
+        assert rec.get_property("Pop") is None
+        assert rec.get_property("Prop") is not None
+        assert rec.get_property("prop") is not None
+        assert rec.get_property("prOp") is not None
diff --git a/unittests/test_record.xml b/unittests/test_record.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5567e59050fdbcd07ce9b13cdc640c7bccf6c165
--- /dev/null
+++ b/unittests/test_record.xml
@@ -0,0 +1,330 @@
+<Record id="171179">
+  <TransactionBenchmark></TransactionBenchmark>
+  <Parent description="Experiment for the LEAP project." id="163454" name="LeapExperiment"/>
+  <Property datatype="TEXT" description="A unique identifier for experiments" flag="inheritance:FIX" id="163414" importance="FIX" name="experimentId">KCdSYWJiaXQnLCAnZXhfdml2bycsICdzeW5jaHJvbml6YXRpb25fbWFwJywgTm9uZSwgJzIwMTctMDgtMTEnLCBOb25lLCBOb25lKQ==</Property>
+  <Property datatype="LIST&lt;TEXT&gt;" id="568765" importance="FIX" name="LISTofTEXT">
+    <Value>One</Value>
+    <Value>Two</Value>
+    <Value>Three</Value>
+    <Value></Value><!-- NULL Value-->
+    <Value>
+      <EmptyString/>
+    </Value>
+  </Property>
+  <Property datatype="TEXT" id="568765" importance="FIX" name="EMPTYTEXT1">
+    <Value>
+      <EmptyString/>
+    </Value>
+  </Property>
+  <Property datatype="TEXT" id="568765" importance="FIX" name="EMPTYTEXT2">
+    <EmptyString/>
+  </Property>
+  <Property datatype="TEXT" id="568765" importance="FIX" name="NULLTEXT1"></Property>
+  <Property datatype="TEXT" id="568765" importance="FIX" name="NULLTEXT2">
+  <Value></Value><!-- NULL Value -->
+  </Property>
+  <Property datatype="DATETIME" description="A calendar date. When something took place." flag="inheritance:FIX" id="163442" importance="FIX" name="date">2017-08-11</Property>
+  <Property datatype="TEXT" description="How the experiment was done: IN_VIVO or EX_VIVO." flag="inheritance:FIX" id="163399" importance="FIX" name="vivoness">ex_vivo</Property>
+  <Property datatype="TEXT" description="The species of the experimental animal." flag="inheritance:FIX" id="163418" importance="FIX" name="species">Rabbit</Property>
+  <Property datatype="ExperimentSeries" description="A collection of [Experiment] records which have the same [aim]." flag="inheritance:FIX" id="163449" importance="FIX" name="ExperimentSeries">163386</Property>
+  <Property datatype="LIST&lt;MultiRecRecording&gt;" flag="inheritance:FIX" id="163397" importance="FIX" name="MultiRecRecording">
+    <Value></Value>
+    <Value>170651</Value>
+    <Value>171701</Value>
+    <Value>172074</Value>
+    <Value>171408</Value>
+    <Value>171687</Value>
+    <Value>170791</Value>
+    <Value>171115</Value>
+    <Value>171893</Value>
+    <Value>171237</Value>
+    <Value>171309</Value>
+    <Value>170899</Value>
+    <Value>171048</Value>
+    <Value>171077</Value>
+    <Value>171723</Value>
+    <Value>171085</Value>
+    <Value>171812</Value>
+    <Value>171829</Value>
+    <Value>171669</Value>
+    <Value>170695</Value>
+    <Value>170875</Value>
+    <Value>171751</Value>
+    <Value>171412</Value>
+    <Value>172204</Value>
+    <Value>170997</Value>
+    <Value>171490</Value>
+    <Value>171504</Value>
+    <Value>170977</Value>
+    <Value>171895</Value>
+    <Value>172233</Value>
+    <Value>171261</Value>
+    <Value>171318</Value>
+    <Value>171014</Value>
+    <Value>171132</Value>
+    <Value>171575</Value>
+    <Value>172217</Value>
+    <Value>171638</Value>
+    <Value>170656</Value>
+    <Value>171927</Value>
+    <Value>172232</Value>
+    <Value>171864</Value>
+    <Value>171564</Value>
+    <Value>171090</Value>
+    <Value>171633</Value>
+    <Value>171456</Value>
+    <Value>171755</Value>
+    <Value>170641</Value>
+    <Value>172144</Value>
+    <Value>171872</Value>
+    <Value>171619</Value>
+    <Value>171180</Value>
+    <Value>172019</Value>
+    <Value>171193</Value>
+    <Value>171069</Value>
+    <Value>171643</Value>
+    <Value>171789</Value>
+    <Value>170785</Value>
+    <Value>170904</Value>
+    <Value>171130</Value>
+    <Value>171098</Value>
+    <Value>171241</Value>
+    <Value>171796</Value>
+    <Value>171776</Value>
+    <Value>171175</Value>
+    <Value>171112</Value>
+    <Value>171514</Value>
+    <Value>171854</Value>
+    <Value>170962</Value>
+    <Value>171818</Value>
+    <Value>170745</Value>
+    <Value>171149</Value>
+    <Value>170639</Value>
+    <Value>171508</Value>
+    <Value>170800</Value>
+    <Value>171141</Value>
+    <Value>171414</Value>
+    <Value>171325</Value>
+    <Value>172168</Value>
+    <Value>171184</Value>
+    <Value>172083</Value>
+    <Value>172029</Value>
+    <Value>171556</Value>
+    <Value>172195</Value>
+    <Value>170789</Value>
+    <Value>171300</Value>
+    <Value>172230</Value>
+    <Value>171720</Value>
+    <Value>171341</Value>
+    <Value>171937</Value>
+    <Value>171673</Value>
+    <Value>172106</Value>
+    <Value>171281</Value>
+    <Value>171897</Value>
+    <Value>171108</Value>
+    <Value>172014</Value>
+    <Value>170867</Value>
+    <Value>171531</Value>
+    <Value>171674</Value>
+    <Value>172077</Value>
+    <Value>170944</Value>
+    <Value>171228</Value>
+    <Value>172207</Value>
+    <Value>171039</Value>
+    <Value>171778</Value>
+    <Value>170794</Value>
+    <Value>171646</Value>
+    <Value>172027</Value>
+    <Value>171279</Value>
+    <Value>171618</Value>
+    <Value>171233</Value>
+    <Value>170811</Value>
+    <Value>171357</Value>
+    <Value>172180</Value>
+    <Value>171585</Value>
+    <Value>170774</Value>
+    <Value>171625</Value>
+    <Value>171310</Value>
+    <Value>171855</Value>
+    <Value>172084</Value>
+    <Value>171395</Value>
+    <Value>171955</Value>
+    <Value>172216</Value>
+    <Value>171705</Value>
+    <Value>171312</Value>
+    <Value>171659</Value>
+    <Value>172192</Value>
+    <Value>171157</Value>
+    <Value>171978</Value>
+    <Value>170707</Value>
+    <Value>171250</Value>
+    <Value>171929</Value>
+    <Value>171709</Value>
+    <Value>170898</Value>
+    <Value>170723</Value>
+    <Value>172060</Value>
+    <Value>171693</Value>
+    <Value>172036</Value>
+    <Value>172162</Value>
+    <Value>171460</Value>
+    <Value>172065</Value>
+    <Value>171174</Value>
+    <Value>171461</Value>
+    <Value>172093</Value>
+    <Value>171200</Value>
+    <Value>172007</Value>
+    <Value>172102</Value>
+    <Value>171368</Value>
+    <Value>171761</Value>
+    <Value>172157</Value>
+    <Value>171354</Value>
+    <Value>170698</Value>
+    <Value>171254</Value>
+    <Value>171740</Value>
+    <Value>171303</Value>
+    <Value>170874</Value>
+    <Value>171248</Value>
+    <Value>171698</Value>
+    <Value>171191</Value>
+    <Value>171948</Value>
+    <Value>171920</Value>
+    <Value>171319</Value>
+    <Value>170649</Value>
+    <Value>171731</Value>
+    <Value>170643</Value>
+    <Value>171007</Value>
+    <Value>172186</Value>
+    <Value>171831</Value>
+    <Value>172128</Value>
+    <Value>172154</Value>
+    <Value>170841</Value>
+    <Value>171530</Value>
+    <Value>171142</Value>
+    <Value>171857</Value>
+    <Value>170982</Value>
+    <Value>171852</Value>
+    <Value>171574</Value>
+    <Value>171136</Value>
+    <Value>172107</Value>
+    <Value>171819</Value>
+    <Value>171746</Value>
+    <Value>171036</Value>
+    <Value>171331</Value>
+    <Value>170682</Value>
+    <Value>171779</Value>
+    <Value>171747</Value>
+    <Value>171383</Value>
+    <Value>170748</Value>
+    <Value>170691</Value>
+    <Value>170820</Value>
+    <Value>170829</Value>
+    <Value>171888</Value>
+    <Value>172098</Value>
+    <Value>172199</Value>
+    <Value>171290</Value>
+    <Value>170935</Value>
+    <Value>171056</Value>
+    <Value>171131</Value>
+    <Value>171415</Value>
+    <Value>171105</Value>
+    <Value>171135</Value>
+    <Value>171371</Value>
+    <Value>171640</Value>
+    <Value>171534</Value>
+    <Value>171012</Value>
+    <Value>172047</Value>
+    <Value>172081</Value>
+    <Value>171666</Value>
+    <Value>172089</Value>
+    <Value>172063</Value>
+    <Value>171449</Value>
+    <Value>171159</Value>
+    <Value>171808</Value>
+    <Value>171932</Value>
+    <Value>170664</Value>
+    <Value>172000</Value>
+    <Value>171220</Value>
+    <Value>170955</Value>
+    <Value>170740</Value>
+    <Value>171350</Value>
+    <Value>171528</Value>
+    <Value>171081</Value>
+    <Value>171199</Value>
+    <Value>171711</Value>
+    <Value>171446</Value>
+    <Value>171607</Value>
+    <Value>171292</Value>
+    <Value>170762</Value>
+    <Value>171896</Value>
+    <Value>170810</Value>
+    <Value>170990</Value>
+    <Value>171332</Value>
+    <Value>171080</Value>
+    <Value>171075</Value>
+    <Value>172130</Value>
+    <Value>171525</Value>
+    <Value>171993</Value>
+    <Value>172091</Value>
+    <Value>171924</Value>
+    <Value>172153</Value>
+    <Value>170661</Value>
+    <Value>171190</Value>
+    <Value>171021</Value>
+    <Value>172158</Value>
+    <Value>171980</Value>
+    <Value>171480</Value>
+    <Value>171598</Value>
+    <Value>171827</Value>
+    <Value>172166</Value>
+    <Value>171392</Value>
+    <Value>171512</Value>
+    <Value>171008</Value>
+    <Value>171610</Value>
+    <Value>171692</Value>
+    <Value>171908</Value>
+    <Value>171733</Value>
+    <Value>170866</Value>
+    <Value>171100</Value>
+  </Property>
+  <Property datatype="LIST&lt;PulsarProtocolLog&gt;" description="A log from Pulsar. This is the generic super type. Sub types will represent the log of a particular protocol." flag="inheritance:FIX" id="163401" importance="FIX" name="PulsarProtocolLog">
+    <Value>171750</Value>
+    <Value>171019</Value>
+    <Value>171765</Value>
+    <Value>171269</Value>
+    <Value>170700</Value>
+    <Value>171665</Value>
+    <Value>171496</Value>
+    <Value>170954</Value>
+    <Value>170780</Value>
+    <Value>171313</Value>
+    <Value>171202</Value>
+  </Property>
+  <Property datatype="ACQRawData" description="A file which is the direct/raw output of Acqknowledge." flag="inheritance:FIX" id="163429" importance="FIX" name="ACQRawData">45506</Property>
+  <Property datatype="LIST&lt;FILE&gt;" description="DESCRIBE ME!" flag="inheritance:FIX" id="163456" importance="FIX" name="syncMapValuesFiles">
+    <Value>45508</Value>
+    <Value>45509</Value>
+    <Value>45510</Value>
+    <Value>45511</Value>
+    <Value>45512</Value>
+    <Value>45513</Value>
+    <Value>45514</Value>
+    <Value>45515</Value>
+    <Value>45516</Value>
+    <Value>45517</Value>
+    <Value>45518</Value>
+    <Value>45519</Value>
+    <Value>45520</Value>
+    <Value>45521</Value>
+    <Value>45522</Value>
+    <Value>45523</Value>
+    <Value>45524</Value>
+    <Value>45525</Value>
+    <Value>45526</Value>
+    <Value>45527</Value>
+    <Value>45528</Value>
+    <Value>45529</Value>
+    <Value>45530</Value>
+    <Value>45531</Value>
+    <Value>45532</Value>
+  </Property>
+</Record>