diff --git a/theodolite-quarkus/build.gradle b/theodolite-quarkus/build.gradle
index 8b61bf506dd241c5b0d4e75b1357ef3fd5966135..8c0a13d1f24cfde01c8604285c49d3f48fe6a3b7 100644
--- a/theodolite-quarkus/build.gradle
+++ b/theodolite-quarkus/build.gradle
@@ -25,9 +25,12 @@ dependencies {
     implementation 'io.quarkus:quarkus-kubernetes-client'
     implementation 'org.apache.kafka:kafka-clients:2.7.0'
     implementation 'khttp:khttp:1.0.0'
+    compile 'junit:junit:4.12'
+
 
     testImplementation 'io.quarkus:quarkus-junit5'
     testImplementation 'io.rest-assured:rest-assured'
+    testImplementation 'org.junit-pioneer:junit-pioneer:1.4.0'
 }
 
 group 'theodolite'
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
index 59a793bd7c6d2897fc715c58deda54c178d160f4..ef4d371173c7099eb091f90cddbe26d31e6522be 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
@@ -2,6 +2,7 @@ package theodolite.evaluation
 
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
+import theodolite.util.IOHandler
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
 import java.text.Normalizer
@@ -36,24 +37,25 @@ class AnalysisExecutor(
      */
     fun analyze(load: LoadDimension, res: Resource, executionIntervals: List<Pair<Instant, Instant>>): Boolean {
         var result = false
-        val exporter = CsvExporter()
         var repetitionCounter = 1
 
         try {
-            var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
-            if (resultsFolder.isNotEmpty()){
-                resultsFolder += "/"
-            }
+            val ioHandler = IOHandler()
+            val resultsFolder: String = ioHandler.getResultFolderURL()
+            val fileURL = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}"
+
             val prometheusData = executionIntervals
                 .map { interval -> fetcher.fetchMetric(
                         start = interval.first,
                         end = interval.second,
                         query = "sum by(group)(kafka_consumergroup_group_lag >= 0)") }
 
-            val fileName= "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}"
             prometheusData.forEach{ data ->
-                exporter.toCsv(name = "${fileName}_${repetitionCounter++}", prom = data) }
-
+                ioHandler.writeToCSVFile(
+                    fileURL = "${fileURL}_${repetitionCounter++}",
+                    data = data.getResultAsList(),
+                    columns = listOf("group", "timestamp", "value"))
+            }
 
             val sloChecker = SloCheckerFactory().create(
                 sloType = slo.sloType,
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/CsvExporter.kt b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/CsvExporter.kt
deleted file mode 100644
index 970d1487014bfbddf7391e381d27ad5dbb246a7d..0000000000000000000000000000000000000000
--- a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/CsvExporter.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package theodolite.evaluation
-
-import mu.KotlinLogging
-import theodolite.util.PrometheusResponse
-import java.io.File
-import java.io.PrintWriter
-import java.util.*
-
-private val logger = KotlinLogging.logger {}
-
-/**
- *  Used to document the data received from prometheus for additional offline analysis.
- */
-class CsvExporter {
-
-    /**
-     * Uses the [PrintWriter] to transform a [PrometheusResponse] to a CSV file.
-     * @param name of the file.
-     * @param prom Response that is documented.
-     *
-     */
-    fun toCsv(name: String, prom: PrometheusResponse) {
-        val responseArray = promResponseToList(prom)
-        val csvOutputFile = File("$name.csv")
-
-        PrintWriter(csvOutputFile).use { pw ->
-            pw.println(listOf("group", "timestamp", "value").joinToString(separator=","))
-            responseArray.forEach {
-                pw.println(it.joinToString(separator=","))
-            }
-        }
-        logger.info { "Wrote CSV file: $name to ${csvOutputFile.absolutePath}." }
-    }
-
-    /**
-     * Converts a [PrometheusResponse] into a [List] of [List]s of [String]s
-     */
-    private fun promResponseToList(prom: PrometheusResponse): List<List<String>> {
-        val name = prom.data?.result?.get(0)?.metric?.group.toString()
-        val values = prom.data?.result?.get(0)?.values
-        val dataList = mutableListOf<List<String>>()
-
-        if (values != null) {
-            for (maybeValuePair in values) {
-                val valuePair = maybeValuePair as List<*>
-                val timestamp = (valuePair[0] as Double).toLong().toString()
-                val value = valuePair[1].toString()
-                dataList.add(listOf(name, timestamp, value))
-            }
-        }
-        return Collections.unmodifiableList(dataList)
-    }
-}
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
index 1fecc4664b02e51b581d84d6cbc19c9ddda82c9a..d38b50b70c63c90e6bbb618386e0ed897087e6f1 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
@@ -1,18 +1,13 @@
 package theodolite.execution
 
-import com.google.gson.GsonBuilder
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 import theodolite.patcher.PatcherDefinitionFactory
 import theodolite.strategies.StrategyFactory
 import theodolite.strategies.searchstrategy.CompositeStrategy
-import theodolite.util.Config
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
+import theodolite.util.*
 import java.io.File
-import java.io.PrintWriter
 import java.time.Duration
 
 
@@ -100,34 +95,16 @@ class TheodoliteExecutor(
         return this.kubernetesBenchmark
     }
 
-    private fun getResultFolderString(): String {
-        var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
-        val createResultsFolder = System.getenv("CREATE_RESULTS_FOLDER") ?: "false"
-
-        if (resultsFolder != ""){
-            logger.info { "RESULT_FOLDER: $resultsFolder" }
-            val directory = File(resultsFolder)
-            if (!directory.exists()) {
-                logger.error { "Folder $resultsFolder does not exist" }
-                if (createResultsFolder.toBoolean()) {
-                    directory.mkdirs()
-                } else {
-                    throw IllegalArgumentException("Result folder not found")
-                }
-            }
-            resultsFolder += "/"
-        }
-        return  resultsFolder
-    }
-
     /**
      * Run all experiments which are specified in the corresponding
      * execution and benchmark objects.
      */
     fun run() {
-        val resultsFolder = getResultFolderString()
-        storeAsFile(this.config, "$resultsFolder${this.config.executionId}-execution-configuration")
-        storeAsFile(kubernetesBenchmark, "$resultsFolder${this.config.executionId}-benchmark-configuration")
+        val ioHandler = IOHandler()
+        val resultsFolder = ioHandler.getResultFolderURL()
+        this.config.executionId = getAndIncrementExecutionID(resultsFolder+"expID.txt")
+        ioHandler.writeToJSONFile(this.config, "$resultsFolder${this.config.executionId}-execution-configuration")
+        ioHandler.writeToJSONFile(kubernetesBenchmark, "$resultsFolder${this.config.executionId}-benchmark-configuration")
 
         val config = buildConfig()
         // execute benchmarks for each load
@@ -136,14 +113,17 @@ class TheodoliteExecutor(
                 config.compositeStrategy.findSuitableResource(load, config.resources)
             }
         }
-        storeAsFile(config.compositeStrategy.benchmarkExecutor.results, "$resultsFolder${this.config.executionId}-result")
+        ioHandler.writeToJSONFile(config.compositeStrategy.benchmarkExecutor.results, "$resultsFolder${this.config.executionId}-result")
     }
 
-    private fun <T> storeAsFile(saveObject: T, filename: String) {
-        val gson = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create()
-
-        PrintWriter(filename).use { pw ->
-            pw.println(gson.toJson(saveObject))
-        }
+   private fun getAndIncrementExecutionID(fileURL: String): Int {
+       val ioHandler = IOHandler()
+       var executionID = 0
+       if (File(fileURL).exists()) {
+           executionID = ioHandler.readFileAsString(fileURL).toInt() + 1
+       }
+       ioHandler.writeStringToTextFile(fileURL, (executionID).toString())
+       return executionID
     }
+
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/IOHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/IOHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8d379fcf0543257edafd2e45383a02ba0254563d
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/IOHandler.kt
@@ -0,0 +1,94 @@
+package theodolite.util
+
+import com.google.gson.GsonBuilder
+import mu.KotlinLogging
+import java.io.File
+import java.io.PrintWriter
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ * The IOHandler handles most common I/O operations within the Theodolite framework
+ */
+class IOHandler {
+
+    /**
+     * The location in which Theodolite store result and configuration file are depends on
+     * the values of the environment variables `RESULT_FOLDER` and `CREATE_RESULTS_FOLDER`
+     *
+     * @return the URL of the result folder
+     */
+    fun getResultFolderURL(): String {
+        var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
+        val createResultsFolder = System.getenv("CREATE_RESULTS_FOLDER") ?: "false"
+
+        if (resultsFolder != ""){
+            logger.info { "RESULT_FOLDER: $resultsFolder" }
+            val directory = File(resultsFolder)
+            if (!directory.exists()) {
+                logger.error { "Folder $resultsFolder does not exist" }
+                if (createResultsFolder.toBoolean()) {
+                    directory.mkdirs()
+                } else {
+                    throw IllegalArgumentException("Result folder not found")
+                }
+            }
+            resultsFolder += "/"
+        }
+        return  resultsFolder
+    }
+
+    /**
+     * Read a file as String
+     *
+     * @param fileURL the URL of the file
+     * @return The content of the file as String
+     */
+    fun readFileAsString(fileURL: String): String {
+        return File(fileURL).inputStream().readBytes().toString(Charsets.UTF_8).trim()
+    }
+
+    /**
+     * Creates a JSON string of the given object and store them to file
+     *
+     * @param T class of the object to save
+     * @param objectToSave object which should be saved as file
+     * @param fileURL the URL of the file
+     */
+    fun <T> writeToJSONFile(objectToSave: T, fileURL: String) {
+        val gson = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create()
+        writeStringToTextFile(fileURL, gson.toJson(objectToSave))
+    }
+
+    /**
+     * Write to CSV file
+     *
+     * @param fileURL the URL of the file
+     * @param data  the data to write in the file, as list of list, each subList corresponds to a row in the CSV file
+     * @param columns columns of the CSV file
+     */
+    fun writeToCSVFile(fileURL: String, data: List<List<String>>, columns: List<String>) {
+        val outputFile = File("$fileURL.csv")
+        PrintWriter(outputFile).use { pw ->
+            pw.println(columns.joinToString(separator=","))
+            data.forEach {
+                pw.println(it.joinToString(separator=","))
+            }
+        }
+        logger.info { "Wrote CSV file: $fileURL to ${outputFile.absolutePath}." }
+    }
+
+    /**
+     * Write to text file
+     *
+     * @param fileURL the URL of the file
+     * @param data the data to write in the file as String
+     */
+    fun writeStringToTextFile(fileURL: String, data: String) {
+        val outputFile = File("$fileURL")
+        outputFile.printWriter().use {
+                it.println(data)
+        }
+        logger.info { "Wrote txt file: $fileURL to ${outputFile.absolutePath}." }
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt
index d1d59c482e64fd14c4744d8fcd606f286da24fb4..846577387c425e920da1c2fca1f972c880e1540a 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/PrometheusResponse.kt
@@ -1,6 +1,7 @@
 package theodolite.util
 
 import io.quarkus.runtime.annotations.RegisterForReflection
+import java.util.*
 
 /**
  * This class corresponds to the JSON response format of a Prometheus
@@ -17,6 +18,27 @@ data class PrometheusResponse(
      */
     var data: PromData? = null
 )
+{
+    /**
+     * Return the data of the PrometheusResponse as [List] of [List]s of [String]s
+     * The format of the returned list is: `[[ group, timestamp, value ], [ group, timestamp, value ], ... ]`
+     */
+    fun getResultAsList(): List<List<String>> {
+        val group = data?.result?.get(0)?.metric?.group.toString()
+        val values = data?.result?.get(0)?.values
+        val result = mutableListOf<List<String>>()
+
+        if (values != null) {
+            for (value in values) {
+                val valueList = value as List<*>
+                val timestamp = (valueList[0] as Double).toLong().toString()
+                val value = valueList[1].toString()
+                result.add(listOf(group, timestamp, value))
+            }
+        }
+        return Collections.unmodifiableList(result)
+    }
+}
 
 /**
  * Description of Prometheus data.
@@ -56,4 +78,5 @@ data class PromResult(
 @RegisterForReflection
 data class PromMetric(
     var group: String? = null
-)
\ No newline at end of file
+)
+
diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
index 82e4bc5d77f3f35d217c56a377513c0e7d329170..4f4308a35df598dc4932a8ac89a6c07fb967e416 100644
--- a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
@@ -21,7 +21,7 @@ import theodolite.util.PatcherDefinition
  */
 @QuarkusTest
 class ResourceLimitPatcherTest {
-    val testPath = "./src/main/resources/testYaml/"
+    val testPath = "./src/test/resources/"
     val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace(""))
     val patcherFactory = PatcherFactory()
 
diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
index 3cd6b012f09c5471b1b011b5cd03e61a0fab1c4e..7214422705a64f507a196a4b5f9b334665407422 100644
--- a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
@@ -21,7 +21,7 @@ import theodolite.util.PatcherDefinition
  */
 @QuarkusTest
 class ResourceRequestPatcherTest {
-    val testPath = "./src/main/resources/testYaml/"
+    val testPath = "./src/test/resources/"
     val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace(""))
     val patcherFactory = PatcherFactory()
 
diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/util/IOHandlerTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/util/IOHandlerTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6984c3935da3d26f95565b758547a98e0eeb155f
--- /dev/null
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/util/IOHandlerTest.kt
@@ -0,0 +1,134 @@
+package theodolite.util
+
+import com.google.gson.GsonBuilder
+import io.quarkus.test.junit.QuarkusTest
+import org.hamcrest.CoreMatchers.containsString
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.Rule
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+import org.junit.rules.TemporaryFolder
+import org.junitpioneer.jupiter.ClearEnvironmentVariable
+import org.junitpioneer.jupiter.SetEnvironmentVariable
+
+
+const val FOLDER_URL = "Test-Folder"
+@QuarkusTest
+internal class IOHandlerTest {
+
+    @Rule
+    private var temporaryFolder = TemporaryFolder()
+
+    @Test
+    fun testWriteStringToText() {
+        temporaryFolder.create()
+        val testContent = "Test-File-Content"
+        val folder = temporaryFolder.newFolder(FOLDER_URL)
+
+        IOHandler().writeStringToTextFile(
+            fileURL = "${folder.absolutePath}/test-file.txt",
+            data = testContent)
+
+        assertEquals(
+           testContent,
+            IOHandler().readFileAsString("${folder.absolutePath}/test-file.txt")
+        )
+    }
+
+    @Test
+    fun testWriteToCSVFile() {
+        temporaryFolder.create()
+        val folder = temporaryFolder.newFolder(FOLDER_URL)
+
+        val testContent = listOf(
+            listOf("apples","red"),
+            listOf("bananas","yellow"),
+            listOf("avocado","brown"))
+        val columns = listOf("Fruit", "Color")
+
+        IOHandler().writeToCSVFile(
+            fileURL = "${folder.absolutePath}/test-file",
+            data = testContent,
+            columns = columns)
+
+        var expected = "Fruit,Color\n"
+        testContent.forEach { expected += it[0] + "," +  it[1] + "\n" }
+
+        assertEquals(
+            expected.trim(),
+            IOHandler().readFileAsString("${folder.absolutePath}/test-file.csv")
+        )
+    }
+
+    @Test
+    fun testWriteToJSONFile() {
+        temporaryFolder.create()
+        val folder = temporaryFolder.newFolder(FOLDER_URL)
+        val testContent = Resource(0, emptyList())
+
+        IOHandler().writeToJSONFile(
+            fileURL =  "${folder.absolutePath}/test-file.json",
+            objectToSave = testContent)
+
+        val expected = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create().toJson(testContent)
+
+        assertEquals(
+            expected,
+            IOHandler().readFileAsString("${folder.absolutePath}/test-file.json")
+        )
+    }
+
+    // Test the function `getResultFolderString`
+
+    @Test
+    @ClearEnvironmentVariable.ClearEnvironmentVariables(
+        ClearEnvironmentVariable(key = "RESULTS_FOLDER"),
+        ClearEnvironmentVariable(key = "CREATE_RESULTS_FOLDER")
+    )
+    fun testGetResultFolderURL_emptyEnvironmentVars() {
+        assertEquals("",IOHandler().getResultFolderURL())
+    }
+
+
+    @Test()
+    @SetEnvironmentVariable.SetEnvironmentVariables(
+        SetEnvironmentVariable(key = "RESULTS_FOLDER", value = "./src/test/resources"),
+        SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "false")
+    )
+    fun testGetResultFolderURL_FolderExist() {
+        assertEquals("./src/test/resources/", IOHandler().getResultFolderURL())
+    }
+
+    @Test()
+    @SetEnvironmentVariable.SetEnvironmentVariables(
+        SetEnvironmentVariable(key = "RESULTS_FOLDER", value = "$FOLDER_URL-0"),
+        SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "false")
+    )
+    fun testGetResultFolderURL_FolderNotExist() {
+        var exceptionWasThrown = false
+        try {
+            IOHandler().getResultFolderURL()
+          } catch (e: Exception){
+              exceptionWasThrown = true
+              assertThat(e.toString(), containsString("Result folder not found"));
+          }
+        assertTrue(exceptionWasThrown)
+    }
+
+    @Test()
+    @SetEnvironmentVariable.SetEnvironmentVariables(
+        SetEnvironmentVariable(key = "RESULTS_FOLDER", value = FOLDER_URL),
+        SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "true")
+    )
+    fun testGetResultFolderURL_CreateFolderIfNotExist() {
+        assertEquals("$FOLDER_URL/",  IOHandler().getResultFolderURL())
+    }
+
+    @Test()
+    @ClearEnvironmentVariable(key = "RESULTS_FOLDER" )
+    @SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "true")
+    fun testGetResultFolderURL_CreateFolderButNoFolderGiven() {
+        assertEquals("",  IOHandler().getResultFolderURL())
+    }
+}
diff --git a/theodolite-quarkus/src/main/resources/testYaml/cpu-deployment.yaml b/theodolite-quarkus/src/test/resources/cpu-deployment.yaml
similarity index 100%
rename from theodolite-quarkus/src/main/resources/testYaml/cpu-deployment.yaml
rename to theodolite-quarkus/src/test/resources/cpu-deployment.yaml
diff --git a/theodolite-quarkus/src/main/resources/testYaml/cpu-memory-deployment.yaml b/theodolite-quarkus/src/test/resources/cpu-memory-deployment.yaml
similarity index 100%
rename from theodolite-quarkus/src/main/resources/testYaml/cpu-memory-deployment.yaml
rename to theodolite-quarkus/src/test/resources/cpu-memory-deployment.yaml
diff --git a/theodolite-quarkus/src/main/resources/testYaml/memory-deployment.yaml b/theodolite-quarkus/src/test/resources/memory-deployment.yaml
similarity index 100%
rename from theodolite-quarkus/src/main/resources/testYaml/memory-deployment.yaml
rename to theodolite-quarkus/src/test/resources/memory-deployment.yaml
diff --git a/theodolite-quarkus/src/main/resources/testYaml/no-resources-deployment.yaml b/theodolite-quarkus/src/test/resources/no-resources-deployment.yaml
similarity index 100%
rename from theodolite-quarkus/src/main/resources/testYaml/no-resources-deployment.yaml
rename to theodolite-quarkus/src/test/resources/no-resources-deployment.yaml