diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a005ed5552eee6a8d07e2af9ac663575b495ec4..4e1c0222515ba52a6667437b1e1ecf499e9486dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added (for new features)
 
+* Tests for version history
 * Tests for inheritance bug (caosdb/caosdb-server!54)
 * Tests for versioning
 * Tests for deeply nested SELECT queries
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 1e107a6db48a8f5c82df613930871d0514b37852..1d0b6b9ded8854d500cb71481d309801f61c5c67 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -262,18 +262,6 @@ def test_annotation():
         rt = execute_query("FIND AnnotationTest*").delete()
 
 
-def test_history():
-    try:
-        rt = RecordType(name="SimpleTestProperty").insert()
-        rt.retrieve(flags={"H": None})
-        assert_equal(rt.messages["History"], ('Insert', None))
-    finally:
-        try:
-            rt.delete()
-        except BaseException:
-            pass
-
-
 def test_info():
     i = Info()
     assert_is_not_none(i.messages["Flags"])
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
index 11cd7986846bbccfb31be0f60e90dc0d7c276af8..b00a8e6026b26bf867584db01cbc4269550267ab 100644
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -937,25 +937,26 @@ def test_retrieve_acl():
         assert_equal(e.msg, "You are not allowed to do this.")
 
 
-@with_setup(setup, teardown)
 def test_retrieve_history():
     p = db.Property(name="TestProperty", datatype=db.TEXT).insert()
     assert_true(p.is_valid())
 
     grant_permission(p, "RETRIEVE:ENTITY")
+    p.retrieve()
+    assert p.version is not None
+    assert p.version.username is None, "username belongs to history"
 
     '''Failure'''
-    try:
+    with raises(db.TransactionError) as exc:
         p.retrieve(flags={"H": None})
-        assert_true(False)
-    except db.TransactionError as e:
-        assert_equal(e.msg, "You are not allowed to do this.")
+    assert "You are not allowed to do this." in str(exc.value)
 
     '''Success'''
     grant_permission(p, "RETRIEVE:HISTORY")
 
     p.retrieve(flags={"H": None})
-    assert_equal(p.messages["History"], ('Insert', None))
+    assert p.version is not None
+    assert p.version.username == db.get_config().get("Connection", "username")
 
 
 @with_setup(setup, teardown)
diff --git a/tests/test_version.py b/tests/test_version.py
index 4a02b7df4a70446b3956d9bc77c22cff01faac04..784c23b0754ad4f9710ced3930a776af7a2747ee 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -47,7 +47,7 @@ def insertion(name="TestRT", parents=[]):
     rt.insert()
     assert rt.version is not None
     assert rt.version.id is not None
-    assert rt.version.date is not None
+    assert rt.version.is_head is True
     assert len(rt.version.predecessors) == 0
     assert len(rt.version.successors) == 0
     return rt
@@ -58,7 +58,6 @@ def test_retrieve():
     version = rt.version
 
     rt2 = c.execute_query("FIND RecordType TestRT", unique=True)
-    assert parse(rt2.version.date) == parse(version.date)
     assert rt2.version == version
 
 
@@ -72,10 +71,8 @@ def test_update_description():
     assert rt.description == new_desc
     assert rt.version is not None
     assert rt.version.id is not None
-    assert rt.version.date is not None
     assert rt.version != old_version
-    assert rt.version.date != old_version.date
-    assert parse(rt.version.date) > parse(old_version.date)
+    assert rt.version.is_head is True
 
     rt2 = c.execute_query("FIND RecordType TestRT", unique=True)
     assert rt2.version.id == rt.version.id
@@ -92,6 +89,7 @@ def test_update_description():
                                     "@" + old_version.id, sync=False)[0]
     assert rt_old.version.id == old_version.id
     assert rt_old.description == old_desc
+    assert rt_old.version.is_head is False
 
 
 def test_update_parent():
@@ -740,10 +738,7 @@ def test_update_name():
     assert rt.name == new_name
     assert rt.version is not None
     assert rt.version.id is not None
-    assert rt.version.date is not None
     assert rt.version != old_version
-    assert rt.version.date != old_version.date
-    assert parse(rt.version.date) > parse(old_version.date)
 
     assert len(c.execute_query("FIND RecordType {}".format(old_name))) == 0
     rt2 = c.execute_query("FIND RecordType {}".format(new_name), unique=True)
@@ -819,3 +814,36 @@ def test_delete_referenced_entity():
     rec_v2 = c.Container().retrieve(query=str(rec.id) + "@HEAD",
                                     flags={"cache": "false"}, sync=False)[0]
     assert rec_v2.get_property(ref_rt) is None
+
+
+def test_retrieve_history():
+    rt = insertion()
+    versions = []
+    desc = dict()
+
+    versions.append(rt.version)
+    desc[rt.version.id] = rt.description
+    v5_version = None
+
+    for i in range(10):
+        rt.description = rt.description + str(i)
+        rt.update()
+        versions.append(rt.version)
+        desc[rt.version.id] = rt.description
+        if i == 5:
+            v5_version = rt.version
+
+    # retrieve history
+    rt_v5 = c.Container().retrieve(query=str(rt.id) + "@HEAD~4",
+                                   flags={"H": None},
+                                   sync=False)[0]
+    assert rt_v5.version.is_complete_history is True
+    assert rt_v5.version.id == v5_version.id
+    history = rt_v5.version.get_history()
+    assert len(history) == len(versions)
+    # Compare actual and expected version
+    for act, exp in zip(history, versions):
+        assert act.id == exp.id
+        tst = c.Container().retrieve(query=str(rt.id) + "@" + act.id,
+                                     sync=False)[0]
+        assert tst.description == desc[act.id]