new file mode 100644
@@ -0,0 +1,28 @@
+# Isar Unittests
+
+The unittest python module adds some simple infrastructure that allows to
+unittest python functions defined in bitbake files.
+
+## Running the tests
+
+You can run the tests using avocado with `avocado --show=app,test run testsuite/unittests/`
+or by using the buildin module with `python3 -m unittest discover testsuite/unittests/`
+
+## Creating new tests
+
+See the [unittest documentation](https://docs.python.org/3/library/unittest.html)
+on how to create a test module and name it test_*bitbake_module_name*.py
+
+Use the function `load_function(file_name: str, function_name: str) -> Callable`
+in the bitbake module to load the function.
+
+Example:
+```python
+from bitbake import load_function
+
+my_function = load_function("meta/classes/my_module.bbclass", "my_function")
+my_function(arg1, arg2)
+```
+
+Use the [unittest.mock](https://docs.python.org/3/library/unittest.mock.html)
+library to mock the bb modules as needed.
new file mode 100644
@@ -0,0 +1,37 @@
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2023
+#
+# SPDX-License-Identifier: MIT
+
+import sys
+import pathlib
+from typing import Callable
+
+location = pathlib.Path(__file__).parent.resolve()
+sys.path.insert(0, "{}/../../bitbake/lib".format(location))
+
+from bb.parse import handle
+from bb.data import init
+
+# Modules added for reimport from testfiles
+from bb.data_smart import DataSmart
+
+
+def load_function(file_name: str, function_name: str) -> Callable:
+ """Load a python function defined in a bitbake file.
+
+ Args:
+ file_name (str): The path to the file e.g. `meta/classes/my_special.bbclass`.
+ function_name (str): The name of the python function without braces e.g. `my_special_function`
+
+ Returns:
+ Callable: The loaded function.
+ """
+ d = init()
+ parse = handle("{}/../../{}".format(location, file_name), d)
+ if function_name not in parse:
+ raise KeyError("Function {} does not exist in {}".format(
+ function_name, file_name))
+ namespace = {}
+ exec(parse[function_name], namespace)
+ return namespace[function_name]
new file mode 100644
@@ -0,0 +1,45 @@
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2023
+#
+# SPDX-License-Identifier: MIT
+
+import tempfile
+import pathlib
+import shutil
+import atexit
+
+temp_dirs = []
+
+
+class TemporaryRootfs:
+ """ A temporary rootfs folder that will be removed after the testrun. """
+
+ def __init__(self):
+ self._rootfs_path = tempfile.mkdtemp()
+ temp_dirs.append(self._rootfs_path)
+
+ def path(self) -> str:
+ return self._rootfs_path
+
+ def create_file(self, path: str, content: str) -> None:
+ """ Create a file with the given content.
+
+ Args:
+ path (str): The path to the file e.g. `/etc/hostname`.
+ content (str): The content of the file e.g. `my_special_host`
+
+ Returns:
+ None
+ """
+ pathlib.Path(self._rootfs_path +
+ path).parent.mkdir(parents=True, exist_ok=True)
+ with open(self._rootfs_path + path, 'w') as file:
+ file.write(content)
+
+
+def cleanup():
+ for temp_dir in temp_dirs:
+ shutil.rmtree(temp_dir)
+
+
+atexit.register(cleanup)