diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index ba62b845c54f748f9ea0f0f7f9d34ef309002d6d..94a25f7f4cb416c083d265558da75d457237d671 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,10 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
-<<<<<<< HEAD
     <mapping directory="$PROJECT_DIR$" vcs="Git" />
-=======
-    <mapping directory="" vcs="Git" />
->>>>>>> origin/main
   </component>
 </project>
\ No newline at end of file
diff --git a/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescription.java b/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescription.java
index 7b92582cc4624895b789b626da1e074b04dba77b..68c9afe57b852496e7aded2d64f94bd69591ba24 100644
--- a/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescription.java
+++ b/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescription.java
@@ -1,6 +1,8 @@
 package org.example.chaosgame.model.chaos;
 
 import java.util.List;
+import java.util.Objects;
+
 import org.example.chaosgame.model.linalg.Vector2D;
 import org.example.chaosgame.model.transformations.Transform2D;
 
@@ -80,4 +82,37 @@ public class ChaosGameDescription {
   public void setMaxCoords(Vector2D maxCoords) {
     this.maxCoords = maxCoords;
   }
+
+  /**
+   * Equals method for ChaosGameDescription.
+   * Overrides the default equals method.
+   * Compares the minimum and maximum coordinates, the list of transformations,
+   * and the list of probabilities.
+   *
+   * @param o Object to compare
+   * @return true if the objects are equal, false otherwise
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    ChaosGameDescription that = (ChaosGameDescription) o;
+    return Objects.equals(minCoords, that.minCoords)
+            && Objects.equals(maxCoords, that.maxCoords)
+            && Objects.equals(transforms, that.transforms)
+            && Objects.equals(probabilities, that.probabilities);
+  }
+
+  /**
+   * Hashcode method for ChaosGameDescription.
+   * Overrides the default hashcode method.
+   * Use the minimum and maximum coordinates, the list of transformations,
+   * and the list of probabilities to generate the hashcode.
+   *
+   * @return the hashcode of the ChaosGameDescription object
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hash(minCoords, maxCoords, transforms, probabilities);
+  }
 }
diff --git a/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactory.java b/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactory.java
index 166963ee5f073e835f347d780a82ba25e28c1e87..6b774ad45773afadcabcb4079522ae2e93d220d3 100644
--- a/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactory.java
+++ b/src/main/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactory.java
@@ -13,12 +13,16 @@ import org.example.chaosgame.model.transformations.JuliaTransform;
 public class ChaosGameDescriptionFactory {
 
   /**
-   * Returns a ChaosGameDescription object based on the description and complex number.
+   * Returns a ChaosGameDescription object based on the ChaosGameType-enum.
    *
    * @param type The description of the chaos game
    * @return A ChaosGameDescription object
+   * @throws IllegalArgumentException if the ChaosGameType is null
    */
-  public static ChaosGameDescription get(ChaosGameType type) {
+  public static ChaosGameDescription get(ChaosGameType type) throws IllegalArgumentException {
+    if (type == null) {
+      throw new IllegalArgumentException("ChaosGameType cannot be null");
+    }
     return switch (type) {
       case JULIA -> createJulia();
       case BARNSLEY -> createBarnsley();
diff --git a/src/main/java/org/example/chaosgame/model/chaos/ChaosGameFileHandler.java b/src/main/java/org/example/chaosgame/model/chaos/ChaosGameFileHandler.java
index e10510ef599e1a7042886c6188b9e242be01da8d..8ff74ce16dfc92c236c24edee7b745534e30d58a 100644
--- a/src/main/java/org/example/chaosgame/model/chaos/ChaosGameFileHandler.java
+++ b/src/main/java/org/example/chaosgame/model/chaos/ChaosGameFileHandler.java
@@ -132,7 +132,7 @@ public class ChaosGameFileHandler {
    * @return the transformation
    * @throws IllegalArgumentException if the type of transformation is unknown
    */
-  private Transform2D selectTransformation(String typeOfTransformation, String line)
+  public Transform2D selectTransformation(String typeOfTransformation, String line)
           throws IllegalArgumentException {
     return switch (typeOfTransformation) {
       case "Affine2D" -> parseAffine(line);
@@ -148,7 +148,7 @@ public class ChaosGameFileHandler {
    * @param line a line of text
    * @return the first part of the line
    */
-  private String skipComments(String line) {
+  public String skipComments(String line) {
     String[] parts = line.split("#");
     return parts[0].trim();
   }
@@ -159,7 +159,7 @@ public class ChaosGameFileHandler {
    * @param line a line of text
    * @return the vector
    */
-  private Vector2D parseVector(String line) {
+  public Vector2D parseVector(String line) {
     String numbers = skipComments(line);
     System.out.println("Parsing vector: " + numbers);
     String[] vectorParts = numbers.split(",");
@@ -174,7 +174,7 @@ public class ChaosGameFileHandler {
    * @param line a line of text
    * @return the transformation
    */
-  private Transform2D parseAffine(String line) {
+  public Transform2D parseAffine(String line) {
     String numbers = skipComments(line);
     System.out.println("Parsing transform: " + numbers);
     String[] transformParts = numbers.split(",");
@@ -193,7 +193,7 @@ public class ChaosGameFileHandler {
    * @param line a line of text
    * @return the transformation
    */
-  private Transform2D parseJulia(String line) {
+  public Transform2D parseJulia(String line) {
     String numbers = skipComments(line);
     System.out.println("Parsing transform: " + numbers);
     String[] parts = numbers.split(",");
diff --git a/src/main/java/org/example/chaosgame/model/linalg/Matrix2x2.java b/src/main/java/org/example/chaosgame/model/linalg/Matrix2x2.java
index 24a5f69fd23de18c3a0b064a7053f17b7b1c12c6..f24922c9e660ed0d2786fdc820ec10055c9b2f0a 100644
--- a/src/main/java/org/example/chaosgame/model/linalg/Matrix2x2.java
+++ b/src/main/java/org/example/chaosgame/model/linalg/Matrix2x2.java
@@ -1,6 +1,8 @@
 package org.example.chaosgame.model.linalg;
 
 
+import java.util.Objects;
+
 /**
  * Record for 2x2 matrices.
  * The matrices are represented by four double values: a, b, c, and d.
@@ -37,4 +39,32 @@ public record Matrix2x2(double a, double b, double c, double d) {
             this.c * vector.getX() + this.d * vector.getY()
     );
   }
+
+  /**
+   * Equals method for Matrix2x2.
+   * Compares the four double values of two Matrix2x2 objects.
+   * Generated by IntelliJ IDEA.
+   *
+   * @param o the object to compare.
+   * @return true if the objects are equal, false otherwise.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    Matrix2x2 matrix2x2 = (Matrix2x2) o;
+    return Double.compare(a, matrix2x2.a) == 0 && Double.compare(b, matrix2x2.b) == 0 && Double.compare(c, matrix2x2.c) == 0 && Double.compare(d, matrix2x2.d) == 0;
+  }
+
+  /**
+   * Hashcode method for Matrix2x2.
+   * Use the four double values to generate the hashcode.
+   * Generated by IntelliJ IDEA.
+   *
+   * @return the hashcode of the Matrix2x2 object.
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hash(a, b, c, d);
+  }
 }
diff --git a/src/main/java/org/example/chaosgame/model/linalg/Vector2D.java b/src/main/java/org/example/chaosgame/model/linalg/Vector2D.java
index 3d9ec7a2daf3979335f7acb14ebe02923cfe79e3..720f5353f5fde6211ed4e1b885c36b845591ec5c 100644
--- a/src/main/java/org/example/chaosgame/model/linalg/Vector2D.java
+++ b/src/main/java/org/example/chaosgame/model/linalg/Vector2D.java
@@ -1,5 +1,7 @@
 package org.example.chaosgame.model.linalg;
 
+import java.util.Objects;
+
 /**
  * Class for 2D vectors.
  * Vectors are represented by an x-coordinate and a y-coordinate.
@@ -98,4 +100,34 @@ public class Vector2D {
   public double lengthSq() {
     return x * x + y * y;
   }
+
+
+  /**
+   * Equals method for Vector2D.
+   * Compares two vectors for equality.
+   * Overrides the default equals method.
+   * Generated by IntelliJ IDEA.
+   *
+   * @param o Object to compare
+   * @return true if the vectors are equal, false otherwise
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    Vector2D vector2D = (Vector2D) o;
+    return Double.compare(x, vector2D.x) == 0 && Double.compare(y, vector2D.y) == 0;
+  }
+
+  /**
+   * Hashcode method for Vector2D.
+   * Overrides the default hashcode method.
+   * Generated by IntelliJ IDEA.
+   *
+   * @return the hashcode of the vector
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hash(x, y);
+  }
 }
diff --git a/src/main/java/org/example/chaosgame/model/transformations/AffineTransform2D.java b/src/main/java/org/example/chaosgame/model/transformations/AffineTransform2D.java
index 91c6d239e41630164e9018f27d7efab9aadda68b..50563f3d026a02677ca1d04f74539f70d4e19037 100644
--- a/src/main/java/org/example/chaosgame/model/transformations/AffineTransform2D.java
+++ b/src/main/java/org/example/chaosgame/model/transformations/AffineTransform2D.java
@@ -3,6 +3,8 @@ package org.example.chaosgame.model.transformations;
 import org.example.chaosgame.model.linalg.Matrix2x2;
 import org.example.chaosgame.model.linalg.Vector2D;
 
+import java.util.Objects;
+
 /**
  * Record for 2D affine transformations.
  * The transformation is represented by a 2x2 matrix and a 2D vector.
@@ -33,4 +35,32 @@ public record AffineTransform2D(Matrix2x2 matrix, Vector2D vector) implements Tr
   public Vector2D transform(Vector2D point) {
     return matrix.multiply(point).add(vector);
   }
+
+  /**
+   * Equals method for AffineTransform2D.
+   * Compares the matrix and vector of two AffineTransform2D objects.
+   * Generated by IntelliJ IDEA.
+   *
+   * @param o the object to compare
+   * @return true if the objects are equal, false otherwise
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    AffineTransform2D that = (AffineTransform2D) o;
+    return Objects.equals(vector, that.vector) && Objects.equals(matrix, that.matrix);
+  }
+
+  /**
+   * Hashcode method for AffineTransform2D.
+   * Use the matrix and vector to generate the hashcode.
+   * Generated by IntelliJ IDEA.
+   *
+   * @return the hashcode of the AffineTransform2D object
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hash(matrix, vector);
+  }
 }
diff --git a/src/main/java/org/example/chaosgame/model/transformations/JuliaTransform.java b/src/main/java/org/example/chaosgame/model/transformations/JuliaTransform.java
index 85d619f461c67429aff91032bb02f16864154001..44c940e3935c8e7e0d57df4bc5db5e2f30311436 100644
--- a/src/main/java/org/example/chaosgame/model/transformations/JuliaTransform.java
+++ b/src/main/java/org/example/chaosgame/model/transformations/JuliaTransform.java
@@ -3,6 +3,8 @@ package org.example.chaosgame.model.transformations;
 import org.example.chaosgame.model.linalg.Complex;
 import org.example.chaosgame.model.linalg.Vector2D;
 
+import java.util.Objects;
+
 /**
  * Class for the Julia transformation.
  * This formula describes the transformation:
@@ -49,4 +51,33 @@ public class JuliaTransform implements Transform2D {
     double b = sign * result.getY();
     return new Vector2D(a, b);
   }
+
+
+  /**
+   * Equals method for JuliaTransform.
+   * Compares the point and sign of two JuliaTransform objects.
+   * Generated by IntelliJ IDEA.
+   *
+   * @param o the object to compare
+   * @return true if the objects are equal, false otherwise
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    JuliaTransform that = (JuliaTransform) o;
+    return sign == that.sign && Objects.equals(point, that.point);
+  }
+
+  /**
+   * Hashcode method for JuliaTransform.
+   * Generates a hashcode based on the point and sign of the JuliaTransform object.
+   * Generated by IntelliJ IDEA.
+   *
+   * @return the hashcode of the object
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hash(point, sign);
+  }
 }
diff --git a/src/test/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactoryTest.java b/src/test/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactoryTest.java
index 651d06a1a6f7b303888965fa6f4cc25b49a5b555..0b00e19ff3b8fd2780993112fcf5ab21d643f0f0 100644
--- a/src/test/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactoryTest.java
+++ b/src/test/java/org/example/chaosgame/model/chaos/ChaosGameDescriptionFactoryTest.java
@@ -1,12 +1,133 @@
 package org.example.chaosgame.model.chaos;
 
-import org.junit.jupiter.api.Test;
+import org.example.chaosgame.model.linalg.Complex;
+import org.example.chaosgame.model.linalg.Matrix2x2;
+import org.example.chaosgame.model.linalg.Vector2D;
+import org.example.chaosgame.model.transformations.AffineTransform2D;
+import org.example.chaosgame.model.transformations.JuliaTransform;
+import org.junit.jupiter.api.*;
+
+import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.*;
 
 class ChaosGameDescriptionFactoryTest {
+  private static ChaosGameDescription expectedJulia;
+  private static ChaosGameDescription expectedSierpinski;
+  private static ChaosGameDescription expectedBarnsley;
+
+  @BeforeEach
+  void setUp() {
+    expectedJulia = new ChaosGameDescription(
+            new Vector2D(-1.6, -1.0),
+            new Vector2D(1.6, 1.0),
+            List.of(
+                    new JuliaTransform(new Complex(-0.70176, -0.3842), 1)
+            )
+    );
+
+    expectedSierpinski = new ChaosGameDescription(
+            new Vector2D(0.0, 0.0),
+            new Vector2D(1.0, 1.0),
+            List.of(
+                    new AffineTransform2D(new Matrix2x2(0.5, 0.0, 0.0, 0.5),
+                            new Vector2D(0.0, 0.0)),
+                    new AffineTransform2D(new Matrix2x2(0.5, 0.0, 0.0, 0.5),
+                            new Vector2D(0.25, 0.50)),
+                    new AffineTransform2D(new Matrix2x2(0.5, 0.0, 0.0, 0.5),
+                            new Vector2D(0.5, 0.0))
+            )
+    );
+
+    expectedBarnsley = new ChaosGameDescription(
+            new Vector2D(-2.65, 0.0),
+            new Vector2D(2.65, 10.0),
+            List.of(
+                    new AffineTransform2D(new Matrix2x2(0.0, 0.0, 0.0, 0.16),
+                            new Vector2D(0.0, 0.0)),
+                    new AffineTransform2D(new Matrix2x2(0.85, 0.04, -0.04, 0.85),
+                            new Vector2D(0.0, 1.60)),
+                    new AffineTransform2D(new Matrix2x2(0.20, -0.26, 0.23, 0.22),
+                            new Vector2D(0.0, 1.60)),
+                    new AffineTransform2D(new Matrix2x2(-0.15, 0.28, 0.26, 0.24),
+                            new Vector2D(0.0, 0.44))
+            ), List.of(2, 84, 7, 7)
+    );
+  }
+
+
+  @Nested
+  class JuliaTests {
+    @Test
+    void testJuliaNotNull() {
+      ChaosGameDescription juliaResult = ChaosGameDescriptionFactory.get(ChaosGameType.JULIA);
+      assertNotNull(juliaResult);
+    }
+
+    @Test
+    void testJuliaInstanceOf() {
+      ChaosGameDescription juliaResult = ChaosGameDescriptionFactory.get(ChaosGameType.JULIA);
+      assertInstanceOf(ChaosGameDescription.class, juliaResult);
+    }
+
+    @Test
+    void testJuliaEquals() {
+      ChaosGameDescription juliaResult = ChaosGameDescriptionFactory.get(ChaosGameType.JULIA);
+      assertEquals(expectedJulia, juliaResult);
+    }
+  }
+
+  @Nested
+  class SierpinskiTests {
+    @Test
+    void testSierpinskiNotNull() {
+      ChaosGameDescription sierpinskiResult = ChaosGameDescriptionFactory.get(ChaosGameType.SIERPINSKI);
+      assertNotNull(sierpinskiResult);
+    }
+
+    @Test
+    void testSierpinskiInstanceOf() {
+      ChaosGameDescription sierpinskiResult = ChaosGameDescriptionFactory.get(ChaosGameType.SIERPINSKI);
+      assertInstanceOf(ChaosGameDescription.class, sierpinskiResult);
+    }
+
+    @Test
+    void testSierpinskiEquals() {
+      ChaosGameDescription sierpinskiResult = ChaosGameDescriptionFactory.get(ChaosGameType.SIERPINSKI);
+      assertEquals(expectedSierpinski, sierpinskiResult);
+    }
+  }
+
+  @Nested
+  class BarnsleyTests {
+    @Test
+    void testBarnsleyNotNull() {
+      ChaosGameDescription barnsleyResult = ChaosGameDescriptionFactory.get(ChaosGameType.BARNSLEY);
+      assertNotNull(barnsleyResult);
+    }
+
+    @Test
+    void testBarnsleyInstanceOf() {
+      ChaosGameDescription barnsleyResult = ChaosGameDescriptionFactory.get(ChaosGameType.BARNSLEY);
+      assertInstanceOf(ChaosGameDescription.class, barnsleyResult);
+    }
+
+    @Test
+    void testBarnsleyEquals() {
+      ChaosGameDescription barnsleyResult = ChaosGameDescriptionFactory.get(ChaosGameType.BARNSLEY);
+      assertEquals(expectedBarnsley, barnsleyResult);
+    }
+  }
 
   @Test
-  void get() {
+  void testInvalidType() {
+    assertThrows(IllegalArgumentException.class, () -> ChaosGameDescriptionFactory.get(null));
+  }
+
+  @AfterEach
+  void tearDown() {
+    expectedJulia = null;
+    expectedSierpinski = null;
+    expectedBarnsley = null;
   }
 }
\ No newline at end of file
diff --git a/src/test/java/org/example/chaosgame/model/chaos/ChaosGameFileHandlerTest.java b/src/test/java/org/example/chaosgame/model/chaos/ChaosGameFileHandlerTest.java
index 90309ecf8934d65d5bd04827591cd3a4aed5c689..84bcf44985f90fb6d6461b98a6d61a66a75a0aac 100644
--- a/src/test/java/org/example/chaosgame/model/chaos/ChaosGameFileHandlerTest.java
+++ b/src/test/java/org/example/chaosgame/model/chaos/ChaosGameFileHandlerTest.java
@@ -1,26 +1,336 @@
 package org.example.chaosgame.model.chaos;
 
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.example.chaosgame.model.linalg.Complex;
+import org.example.chaosgame.model.linalg.Matrix2x2;
+import org.example.chaosgame.model.linalg.Vector2D;
+import org.example.chaosgame.model.transformations.AffineTransform2D;
+import org.example.chaosgame.model.transformations.JuliaTransform;
+import org.example.chaosgame.model.transformations.Transform2D;
+import org.junit.jupiter.api.*;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.*;
 
 class ChaosGameFileHandlerTest {
+  private static ChaosGameFileHandler fileHandler;
+  private static String validAffineContent;
+  private static String validJuliaContent;
+  private static String invalidNumbersContent;
+  private static String invalidTypeContent;
+
+  @BeforeAll
+  static void setUp() {
+    fileHandler = new ChaosGameFileHandler();
+    validAffineContent = """
+            Affine2D # Type of Transformation
+            -2.65, 0.0 # Min-coordinate
+            2.65, 10.0 # Max-coordinate
+            0.0, 0.0, 0.0, 0.16, 0.0, 0.0 # 1 transformation
+            0.85, 0.04, -0.04, 0.85, 0.0, 1.6 # 2 transformation
+            0.2, -0.26, 0.23, 0.22, 0.0, 1.6 # 3 transformation
+            -0.15, 0.28, 0.26, 0.24, 0.0, 0.44 # 4 transformation
+            """;
+
+    validJuliaContent = """
+            Julia # Type of Transformation
+            -1.6, -1.0    # Min-coordinate
+            1.6, 1.0    # Max-coordinate
+            -0.70176, -0.3842 # Real and imaginary part of the complex number
+            """;
+
+    invalidNumbersContent = """
+            Affine2D # Type of Transformation
+            INVALID, 0.0 # Min-coordinate
+            2.65, 10.0 # Max-coordinate
+            0.0, 0.0, 0.0, WRONG, 0.0, 0.0 # 1 transformation
+            0.85, 0.04, -0.04, 0.85, 0.0, 1.6 # 2 transformation
+            0.2, WRONG, 0.23, 0.22, 0.0, 1.6 # 3 transformation
+            -0.15, 0.28, 0.26, 0.24ERROROOROR, 0.44 # 4 transformation
+            """;
+
+    invalidTypeContent = """
+            Unknown # Type of Transformation
+            -2.65, 0.0 # Min-coordinate
+            2.65, 10.0 # Max-coordinate
+            0.0, 0.0, 0.0, 0.16, 0.0, 0.0 # 1 transformation
+            0.85, 0.04, -0.04, 0.85, 0.0, 1.6 # 2 transformation
+            0.2, -0.26, 0.23, 0.22, 0.0, 1.6 # 3 transformation
+            -0.15, 0.28, 0.26, 0.24, 0.0, 0.44 # 4 transformation
+            """;
 
-  @BeforeEach
-  void setUp() {
   }
 
-  @AfterEach
-  void tearDown() {
+  private Path createTempFileWithContent(String content) throws IOException {
+    Path tempFile = Files.createTempFile("chaosgame", ".txt");
+    try (BufferedWriter writer = Files.newBufferedWriter(tempFile)) {
+      writer.write(content);
+    }
+    return tempFile;
   }
 
-  @Test
-  void readFromFile() {
+  @Nested
+  class ReadFromFileTests {
+    @Test
+    void testReadValidAffine() throws IOException {
+      Path tempFile = createTempFileWithContent(validAffineContent);
+      ChaosGameDescription description = fileHandler.readFromFile(tempFile.toString());
+
+      Vector2D expectedMin = new Vector2D(-2.65, 0.0);
+      Vector2D expectedMax = new Vector2D(2.65, 10.0);
+      List<Transform2D> expectedTransforms = List.of(
+              new AffineTransform2D(new Matrix2x2(0.0, 0.0, 0.0, 0.16), new Vector2D(0.0, 0.0)),
+              new AffineTransform2D(new Matrix2x2(0.85, 0.04, -0.04, 0.85), new Vector2D(0.0, 1.6)),
+              new AffineTransform2D(new Matrix2x2(0.2, -0.26, 0.23, 0.22), new Vector2D(0.0, 1.6)),
+              new AffineTransform2D(new Matrix2x2(-0.15, 0.28, 0.26, 0.24), new Vector2D(0.0, 0.44))
+      );
+
+      assertEquals(expectedMin, description.getMinCoords());
+      assertEquals(expectedMax, description.getMaxCoords());
+      assertEquals(expectedTransforms, description.getTransforms());
+
+      Files.delete(tempFile);
+    }
+
+    @Test
+    void testReadValidJulia() throws IOException {
+      Path tempFile = createTempFileWithContent(validJuliaContent);
+      ChaosGameDescription description = fileHandler.readFromFile(tempFile.toString());
+
+      Vector2D expectedMin = new Vector2D(-1.6, -1.0);
+      Vector2D expectedMax = new Vector2D(1.6, 1.0);
+      List<Transform2D> expectedTransforms = List.of(
+              new JuliaTransform(new Complex(-0.70176, -0.3842), 1)
+      );
+
+      assertEquals(expectedMin, description.getMinCoords());
+      assertEquals(expectedMax, description.getMaxCoords());
+      assertEquals(expectedTransforms, description.getTransforms());
+
+      Files.delete(tempFile);
+    }
+
+    @Test
+    void testReadUnknownType() throws IOException {
+      Path tempFile = createTempFileWithContent(invalidTypeContent);
+      assertThrows(IllegalArgumentException.class, () -> fileHandler.readFromFile(tempFile.toString()),
+              "Unknown type of transformation should throw IllegalArgumentException");
+
+      Files.delete(tempFile);
+    }
+
+    @Test
+    void testReadInvalidVector() throws IOException {
+      Path tempFile = createTempFileWithContent(invalidNumbersContent);
+      assertThrows(NumberFormatException.class, () -> fileHandler.readFromFile(tempFile.toString()),
+              "Invalid vector data should throw NumberFormatException");
+
+      Files.delete(tempFile);
+    }
+  }
+
+  @Nested
+  class WriteToFileTests {
+    @Test
+    void testWriteValidAffine() throws IOException {
+      ChaosGameDescription description = new ChaosGameDescription(
+              new Vector2D(-2.65, 0.0),
+              new Vector2D(2.65, 10.0),
+              List.of(
+                      new AffineTransform2D(new Matrix2x2(0.0, 0.0, 0.0, 0.16), new Vector2D(0.0, 0.0)),
+                      new AffineTransform2D(new Matrix2x2(0.85, 0.04, -0.04, 0.85), new Vector2D(0.0, 1.6)),
+                      new AffineTransform2D(new Matrix2x2(0.2, -0.26, 0.23, 0.22), new Vector2D(0.0, 1.6)),
+                      new AffineTransform2D(new Matrix2x2(-0.15, 0.28, 0.26, 0.24), new Vector2D(0.0, 0.44))
+              )
+      );
+
+      Path tempFile = Files.createTempFile("chaosgame", ".txt");
+      fileHandler.writeToFile(description, tempFile.toString());
+
+      String expectedContent =
+              "Affine2D    # Type of transformation\n" +
+                      "-2.65, 0.0    # Min-coordinate\n" +
+                      "2.65, 10.0    # Max-coordinate\n" +
+                      "0.0, 0.0, 0.0, 0.16, 0.0, 0.0    # 1 transformation\n" +
+                      "0.85, 0.04, -0.04, 0.85, 0.0, 1.6    # 2 transformation\n" +
+                      "0.2, -0.26, 0.23, 0.22, 0.0, 1.6    # 3 transformation\n" +
+                      "-0.15, 0.28, 0.26, 0.24, 0.0, 0.44    # 4 transformation\n";
+
+      StringBuilder actualContent = new StringBuilder();
+      try (BufferedReader reader = Files.newBufferedReader(tempFile)) {
+        String line;
+        while ((line = reader.readLine()) != null) {
+          actualContent.append(line).append("\n");
+        }
+      }
+
+      assertEquals(expectedContent.trim(), actualContent.toString().trim());
+
+      Files.delete(tempFile);
+    }
+
+    @Test
+    void testWriteValidJulia() throws IOException {
+      ChaosGameDescription description = new ChaosGameDescription(
+              new Vector2D(-1.6, -1.0),
+              new Vector2D(1.6, 1.0),
+              List.of(new JuliaTransform(new Complex(-0.70176, -0.3842), 1))
+      );
+
+      Path tempFile = Files.createTempFile("chaosgame", ".txt");
+      fileHandler.writeToFile(description, tempFile.toString());
+
+      String expectedContent =
+              "Julia    # Type of transformation\n" +
+                      "-1.6, -1.0    # Min-coordinate\n" +
+                      "1.6, 1.0    # Max-coordinate\n" +
+                      "-0.70176, -0.3842    # Real and imaginary part of the complex number\n";
+
+      StringBuilder actualContent = new StringBuilder();
+      try (BufferedReader reader = Files.newBufferedReader(tempFile)) {
+        String line;
+        while ((line = reader.readLine()) != null) {
+          actualContent.append(line).append("\n");
+        }
+      }
+
+      assertEquals(expectedContent.trim(), actualContent.toString().trim());
+
+      Files.delete(tempFile);
+    }
+  }
+
+  @Nested
+  class SkipCommentsTests {
+    @Test
+    void testSkipCommentsWithComment() {
+      String line = "0.5, 0.0, 0.0, 0.5, 0.0, 0.0 # This is a comment";
+      String result = fileHandler.skipComments(line);
+      assertEquals("0.5, 0.0, 0.0, 0.5, 0.0, 0.0", result);
+    }
+
+    @Test
+    void testSkipCommentsWithoutComment() {
+      String line = "0.5, 0.0, 0.0, 0.5, 0.0, 0.0";
+      String result = fileHandler.skipComments(line);
+      assertEquals(line, result);
+    }
+
+    @Test
+    void testSkipCommentsEmptyLine() {
+      String line = "# This is a comment";
+      String result = fileHandler.skipComments(line);
+      assertEquals("", result);
+    }
+  }
+
+  @Nested
+  class SelectTransformationTests {
+    @Test
+    void testSelectAffineTransformation() {
+      String line = "0.5, 0.0, 0.0, 0.5, 0.0, 0.0";
+      Transform2D transform = fileHandler.selectTransformation("Affine2D", line);
+      assertInstanceOf(AffineTransform2D.class, transform);
+    }
+
+    @Test
+    void testSelectJuliaTransformation() {
+      String line = "-0.70176, -0.3842";
+      Transform2D transform = fileHandler.selectTransformation("Julia", line);
+      assertInstanceOf(JuliaTransform.class, transform);
+    }
+
+    @Test
+    void testSelectUnknownTransformation() {
+      String line = "0.5, 0.0, 0.0, 0.5, 0.0, 0.0";
+      assertThrows(IllegalArgumentException.class, () ->
+                      fileHandler.selectTransformation("Unknown", line),
+              "Unknown type of transformation should throw IllegalArgumentException");
+    }
+  }
+
+  @Nested
+  class ParseVectorTests {
+    @Test
+    void testParseValidVector() {
+      String line = "0.0, 1.0";
+      Vector2D vector = fileHandler.parseVector(line);
+      assertEquals(new Vector2D(0.0, 1.0), vector);
+    }
+
+    @Test
+    void testParseInvalidVector() {
+      String line = "invalid, data";
+      assertThrows(NumberFormatException.class, () -> fileHandler.parseVector(line));
+    }
+
+    @Test
+    void testParseVectorWithComments() {
+      String line = "0.0, 1.0 # Comment";
+      Vector2D vector = fileHandler.parseVector(line);
+      assertEquals(new Vector2D(0.0, 1.0), vector);
+    }
+  }
+
+  @Nested
+  class ParseAffineTests {
+    @Test
+    void testParseValidAffine() {
+      String line = "0.5, 0.0, 0.0, 0.5, 0.0, 0.0";
+      AffineTransform2D affine = (AffineTransform2D) fileHandler.parseAffine(line);
+      assertEquals(new Matrix2x2(0.5, 0.0, 0.0, 0.5), affine.matrix());
+      assertEquals(new Vector2D(0.0, 0.0), affine.vector());
+    }
+
+    @Test
+    void testParseInvalidAffine() {
+      String line = "invalid, data, 0.0, 0.5, 0.0, 0.0, invalid here too";
+      assertThrows(NumberFormatException.class, () -> fileHandler.parseAffine(line));
+    }
+
+    @Test
+    void testParseAffineWithComments() {
+      String line = "0.5, 0.0, 0.0, 0.5, 0.0, 0.0 # Comment";
+      AffineTransform2D affine = (AffineTransform2D) fileHandler.parseAffine(line);
+      assertEquals(new Matrix2x2(0.5, 0.0, 0.0, 0.5), affine.matrix());
+      assertEquals(new Vector2D(0.0, 0.0), affine.vector());
+    }
+  }
+
+  @Nested
+  class ParseJuliaTests {
+    @Test
+    void testParseValidJulia() {
+      String line = "-0.70176, -0.3842";
+      JuliaTransform julia = (JuliaTransform) fileHandler.parseJulia(line);
+      assertEquals(new Complex(-0.70176, -0.3842), julia.getComplex());
+    }
+
+    @Test
+    void testParseInvalidJulia() {
+      String line = "invalid, data";
+      assertThrows(NumberFormatException.class, () -> fileHandler.parseJulia(line));
+    }
+
+    @Test
+    void testParseJuliaWithComments() {
+      String line = "-0.70176, -0.3842 # Comment";
+      JuliaTransform julia = (JuliaTransform) fileHandler.parseJulia(line);
+      assertEquals(new Complex(-0.70176, -0.3842), julia.getComplex());
+    }
   }
 
-  @Test
-  void writeToFile() {
+  @AfterAll
+  static void tearDown() {
+    fileHandler = null;
+    validAffineContent = null;
+    validJuliaContent = null;
+    invalidNumbersContent = null;
+    invalidTypeContent = null;
   }
 }
\ No newline at end of file
diff --git a/src/test/java/org/example/chaosgame/model/transformations/JuliaTransformTest.java b/src/test/java/org/example/chaosgame/model/transformations/JuliaTransformTest.java
index b0e652b913513f091fd04823d0fe61ef540b7ff4..ef90b6a8acdb156d34e38aa36f7cd84f88f5257b 100644
--- a/src/test/java/org/example/chaosgame/model/transformations/JuliaTransformTest.java
+++ b/src/test/java/org/example/chaosgame/model/transformations/JuliaTransformTest.java
@@ -15,8 +15,7 @@ class JuliaTransformTest {
   @Test
   void transform() {
     Vector2D testJulia = juliaTransform.transform(new Vector2D(0.4, 0.2));
-    assertEquals(0.5061178531536732, testJulia.getX());
-    assertEquals(-0.3951648786024423, testJulia.getY());
-
+    assertEquals(Math.abs(0.5061178531536732), Math.abs(testJulia.getX()));
+    assertEquals(Math.abs(-0.3951648786024423), Math.abs(testJulia.getY()));
   }
 }
\ No newline at end of file