diff --git a/soitool/main_window.py b/soitool/main_window.py
index 323ae98c48055f4811de6a0d7e2fa0851e564bc7..42fca26c7b8a25174e57328030c2164fb3c9ee10 100644
--- a/soitool/main_window.py
+++ b/soitool/main_window.py
@@ -235,15 +235,15 @@ class MainWindow(QMainWindow):
         in a new tab, which is selected.
         """
         # Get file-name from dialog
-        file_name = QFileDialog().getOpenFileName(
+        file_path = QFileDialog().getOpenFileName(
             self,
             "Ã…pne SOI",
             os.getcwd(),
             "Text/JSON-filer (SOI_*.txt SOI_*.json)",
         )[0]
 
-        if len(file_name) > 0:
-            soi = import_soi(file_name)
+        if len(file_path) > 0:
+            soi = import_soi(file_path)
 
             # Create and select tab
             tab = SOIWorkspaceWidget(soi)
diff --git a/soitool/serialize_export_import_soi.py b/soitool/serialize_export_import_soi.py
index 50b980682037f4ac964a6b0fed3e29595104f1d6..b4d6c145e3ff906d0f2e338ec2efccd67298e8f1 100644
--- a/soitool/serialize_export_import_soi.py
+++ b/soitool/serialize_export_import_soi.py
@@ -22,13 +22,13 @@ def serialize_soi(soi):
 
     Raises
     ------
-    ValueError
+    TypeError
         Raises error if parameter 'soi' is not a SOI.
     """
     # If parameter 'soi' is not a SOI
     if not isinstance(soi, SOI):
-        raise ValueError(
-            "Invalid value for parameter 'soi': " + "'{}'.".format(soi)
+        raise TypeError(
+            "Invalid type for parameter 'soi': " + "'{}'.".format(soi)
         )
 
     # Create dict with relevant module-information
@@ -58,6 +58,7 @@ def serialize_soi(soi):
         "title": soi.title,
         "description": soi.description,
         "date": soi.date,
+        "version": soi.version,
         "valid": {"from": soi.valid_from, "to": soi.valid_to},
         "icon": soi.icon,
         "classification": soi.classification,
@@ -107,14 +108,29 @@ def export_soi(soi, compressed=True):
     file.close()
 
 
-def import_soi(file_name):
+def import_soi(file_path):
     """Import compressed or uncompressed serialized SOI.
 
     Reads content of file and decompresses it for .txt-files.
     Creates an SOI-object based on the file content.
+
+    Parameters
+    ----------
+    file_path : string
+        full path to file containing serialized SOI
+
+    Returns
+    -------
+    soitool.soi.SOI
+        SOI-object
+
+    Raises
+    ------
+    TypeError
+        If 'type' of module or attachment is not implemented.
     """
-    with open(file_name, "r") as file:
-        if file_name[-4::] == ".txt":
+    with open(file_path, "r") as file:
+        if file_path[-4::] == ".txt":
             serialized = literal_eval(decompress(file.read()))
         else:
             serialized = literal_eval(file.read())
@@ -131,7 +147,7 @@ def import_soi(file_name):
                 {"widget": TableModule(size, content), "meta": module["meta"]}
             )
         else:
-            raise ValueError(
+            raise TypeError(
                 "Module-type '{}' is not recognized.".format(module_type)
             )
 
@@ -150,15 +166,15 @@ def import_soi(file_name):
                 }
             )
         else:
-            raise ValueError(
+            raise TypeError(
                 "Module-type '{}' is not recognized.".format(module_type)
             )
     # Create SOI
     soi = SOI(
         serialized["title"],
         serialized["description"],
-        "1",  # version
-        None,  # date
+        serialized["version"],
+        serialized["date"],
         serialized["valid"]["from"],
         serialized["valid"]["to"],
         serialized["icon"],
diff --git a/soitool/soi.py b/soitool/soi.py
index 75c502f7e2f86d3d1baea1cddf9c2cb527a8b3c4..796d98e3d0e577bdfb9f26fadc191aca16ada291 100644
--- a/soitool/soi.py
+++ b/soitool/soi.py
@@ -378,6 +378,8 @@ class SOI:
         """
         if self.placement_strategy == "auto":
             self.reorganize_rectpack()
+        elif self.placement_strategy == "manual":
+            return
         else:
             raise Exception(
                 "Unknown placement strategy: {}".format(
diff --git a/test/test_codebook_to_pdf.py b/test/test_codebook_to_pdf.py
index 5aa94bee06349f604c97f6065d7c10d0dc8112ab..4d2b8c49ed27943ec4d994bca49e15c5aca3bb96 100644
--- a/test/test_codebook_to_pdf.py
+++ b/test/test_codebook_to_pdf.py
@@ -43,14 +43,6 @@ class ExportTest(unittest.TestCase):
         # Assert file exists
         self.assertTrue(os.path.exists(file_path_small))
 
-        self.addCleanup(
-            partial(delete_generated_files, file_path_full, file_path_small)
-        )
-
-
-def delete_generated_files(file_path1, file_path2):
-    """Delete generated PDF-files."""
-    if os.path.exists(file_path1):
-        os.remove(file_path1)
-    if os.path.exists(file_path2):
-        os.remove(file_path2)
+        # Delete files
+        os.remove(file_path_full)
+        os.remove(file_path_small)
diff --git a/test/test_serialize_export_import.py b/test/test_serialize_export_import.py
new file mode 100644
index 0000000000000000000000000000000000000000..563c70e36c0b8f2cdde62cb932f3e3c54c18a1c2
--- /dev/null
+++ b/test/test_serialize_export_import.py
@@ -0,0 +1,178 @@
+"""Test serializing, exporting and importing of SOI."""
+import os
+import unittest
+import json
+from pathlib import Path
+from datetime import datetime
+from schema import Schema, And, Or
+from PySide2.QtWidgets import QApplication
+from PySide2 import QtGui
+from soitool.soi import SOI
+from soitool.modules.module_table import TableModule
+from soitool.serialize_export_import_soi import (
+    serialize_soi,
+    export_soi,
+    import_soi,
+)
+
+if isinstance(QtGui.qApp, type(None)):
+    app = QApplication([])
+else:
+    app = QtGui.qApp
+
+SOITOOL_ROOT_PATH = Path(__file__).parent.parent
+
+# SOI content
+TITLE = "testSOI"
+DESCRIPTION = "This is a description"
+VERSION = "1"
+DATE = "01.01.2020"
+VALID_FROM = "01.01.2020"
+VALID_TO = "02.01.2020"
+ICON = "soitool/media/HVlogo.png"
+CLASSIFICATION = "Ugradert"
+ORIENTATION = "portrait"
+PLACEMENT_STRATEGY = "manual"
+ALGORITHM_BIN = "BFF"
+ALGORITHM_PACK = "MaxRectsBl"
+ALGORITHM_SORT = "area"
+MODULES = [
+    {
+        "widget": TableModule(
+            size={"width": 50, "height": 75},
+            content=[["H1"], ["Row1"], ["Row2"]],
+        ),
+        "meta": {"x": 0, "y": 0, "page": 1, "name": "Table1"},
+    },
+    {
+        "widget": TableModule(
+            size={"width": 100, "height": 75},
+            content=[["H1", "H2"], ["Row1Col1", "Row1Col2"]],
+        ),
+        "meta": {"x": 200, "y": 150, "page": 1, "name": "Table1"},
+    },
+]
+# Valid schema for serialized SOI
+SCHEMA = Schema(
+    {
+        "title": And(str, len),
+        "description": str,
+        "date": Or(str, None),
+        "version": And(str, len),
+        "valid": {"from": Or(str, None), "to": Or(str, None)},
+        "icon": Or(str, None),
+        "classification": And(str, len),
+        "orientation": And(str, len, Or("portrait", "landscape")),
+        "placement_strategy": And(str, len, Or("manual", "auto")),
+        "algorithm_bin": And(str, len, Or("BFF", "BBF")),
+        "algorithm_pack": And(
+            str, len, Or("MaxRectsBl", "SkylineBl", "GuillotineBssfSas")
+        ),
+        "algorithm_sort": And(str, len, Or("none", "area", "width", "height")),
+        "modules": [
+            {
+                "type": And(str, len),
+                "data": {
+                    "size": {
+                        "width": And(Or(int, float), lambda w: w > 0),
+                        "height": And(Or(int, float), lambda h: h > 0),
+                    },
+                    "content": object,
+                },
+                "meta": {
+                    "x": And(Or(int, float), lambda x: x >= 0),
+                    "y": And(Or(int, float), lambda y: y >= 0),
+                    "page": And(int, lambda page: page >= 0),
+                    "name": And(str, len),
+                },
+            }
+        ],
+        "attachments": [
+            {
+                "type": And(str, len),
+                "data": {
+                    "size": {
+                        "width": And(Or(int, float), lambda w: w > 0),
+                        "height": And(Or(int, float), lambda h: h > 0),
+                    },
+                    "content": object,
+                },
+                "meta": {
+                    "x": And(Or(int, float), lambda x: x >= 0),
+                    "y": And(Or(int, float), lambda y: y >= 0),
+                    "page": And(int, lambda page: page >= 0),
+                    "name": And(str, len),
+                },
+            }
+        ],
+    }
+)
+
+
+class SerializeTest(unittest.TestCase):
+    """Testcase for functions in module 'serialize_export_import.py'."""
+
+    def setUp(self):
+        """Create SOI-object and generate filepath for exported SOI."""
+        self.soi = SOI(
+            title=TITLE,
+            description=DESCRIPTION,
+            version=VERSION,
+            date=DATE,
+            valid_from=VALID_FROM,
+            valid_to=VALID_TO,
+            icon=ICON,
+            classification=CLASSIFICATION,
+            orientation=ORIENTATION,
+            placement_strategy=PLACEMENT_STRATEGY,
+            algorithm_bin=ALGORITHM_BIN,
+            algorithm_pack=ALGORITHM_PACK,
+            algorithm_sort=ALGORITHM_SORT,
+            modules=MODULES,
+            attachments=MODULES,
+        )
+        date = datetime.now().strftime("%Y_%m_%d")
+        file_name = f"SOI_{TITLE}_{date}.json"
+        self.file_path = os.path.join(SOITOOL_ROOT_PATH, file_name)
+
+    def test_export_soi(self):
+        """Export SOI and check if file was created."""
+        # Export SOI
+        export_soi(self.soi, compressed=False)
+        # Assert file exists
+        self.assertTrue(os.path.exists(self.file_path))
+
+    def test_serialize_soi(self):
+        """Serialize SOI and check its validity against schema."""
+        # Serialize SOI and load as dict
+        serialized = serialize_soi(self.soi)
+        json_data = json.loads(serialized)
+        # Assert serialized SOI format matches schema
+        self.assertTrue(SCHEMA.is_valid(json_data))
+
+    def test_import_soi(self):
+        """Import serialized SOI, check SOI content and delete SOI-file."""
+        # Import SOI
+        soi = import_soi(self.file_path)
+
+        # Assert SOI content is correct
+        self.assertEqual(TITLE, soi.title)
+        self.assertEqual(DESCRIPTION, soi.description)
+        self.assertEqual(VERSION, soi.version)
+        self.assertEqual(DATE, soi.date)
+        self.assertEqual(VALID_FROM, soi.valid_from)
+        self.assertEqual(VALID_TO, soi.valid_to)
+        self.assertEqual(ICON, soi.icon)
+        self.assertEqual(CLASSIFICATION, soi.classification)
+        self.assertEqual(ORIENTATION, soi.orientation)
+        self.assertEqual(PLACEMENT_STRATEGY, soi.placement_strategy)
+        self.assertEqual(ALGORITHM_BIN, soi.algorithm_bin)
+        self.assertEqual(ALGORITHM_PACK, soi.algorithm_pack)
+        self.assertEqual(ALGORITHM_SORT, soi.algorithm_sort)
+        self.assertEqual(type(MODULES[0]["widget"]), TableModule)
+        self.assertEqual(type(MODULES[1]["widget"]), TableModule)
+        self.assertEqual(MODULES[0]["meta"], soi.modules[0]["meta"])
+        self.assertEqual(MODULES[1]["meta"], soi.modules[1]["meta"])
+
+        # Delete exported SOI-file
+        os.remove(self.file_path)