diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/PraxisprojektModernDev.iml b/.idea/PraxisprojektModernDev.iml
new file mode 100644
index 0000000000000000000000000000000000000000..0065e628be1ecb98edd03e0933b7ba67b9665271
--- /dev/null
+++ b/.idea/PraxisprojektModernDev.iml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/ModernDev" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea35d863fafb149a54df9e5426144f5c32d5793c
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,20 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoredPackages">
+        <value>
+          <list size="7">
+            <item index="0" class="java.lang.String" itemvalue="pypdf2" />
+            <item index="1" class="java.lang.String" itemvalue="future" />
+            <item index="2" class="java.lang.String" itemvalue="tk" />
+            <item index="3" class="java.lang.String" itemvalue="pytesseract" />
+            <item index="4" class="java.lang.String" itemvalue="DateTime" />
+            <item index="5" class="java.lang.String" itemvalue="bcrypt" />
+            <item index="6" class="java.lang.String" itemvalue="Pillow" />
+          </list>
+        </value>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b90781060a784d8ff4d501d3b91a20ecd9ebe680
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (PraxisprojektModernDev)" project-jdk-type="Python SDK" />
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8483bb34f8e9b6e9d1d75271aa056d56aa879f0f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/PraxisprojektModernDev.iml" filepath="$PROJECT_DIR$/.idea/PraxisprojektModernDev.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/src/__pycache__/__init__.cpython-310.pyc b/src/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d4155c6cc3f22b5cdf03255ec978f442867072db
Binary files /dev/null and b/src/__pycache__/__init__.cpython-310.pyc differ
diff --git a/src/__pycache__/interfaces.cpython-310.pyc b/src/__pycache__/interfaces.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..95e7981751754055c5e10944cc00468b50941e10
Binary files /dev/null and b/src/__pycache__/interfaces.cpython-310.pyc differ
diff --git a/src/__pycache__/romannumerals.cpython-310.pyc b/src/__pycache__/romannumerals.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f6197cf9b2af49383222064fa3d7a160c943eea6
Binary files /dev/null and b/src/__pycache__/romannumerals.cpython-310.pyc differ
diff --git a/src/interfaces.py b/src/interfaces.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc645736ebe7edf2091db66c3738825f50fd923f
--- /dev/null
+++ b/src/interfaces.py
@@ -0,0 +1,6 @@
+from abc import ABC, abstractmethod
+
+class IRomanNumerals(ABC):
+    @abstractmethod
+    def to_roman(self, num):
+        pass
\ No newline at end of file
diff --git a/src/romannumerals.py b/src/romannumerals.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f3eaf1e8e956ca023c64ae71e38caefb1198940
--- /dev/null
+++ b/src/romannumerals.py
@@ -0,0 +1,23 @@
+from src.interfaces import IRomanNumerals
+
+
+class RomanNumerals(IRomanNumerals):
+    def to_roman(self, num):
+        if not isinstance(num, int):
+            raise ValueError("Eingabe muss eine ganze Zahl sein")
+        if num <= 0 or num >= 4000:
+            raise ValueError("Zahl muss zwischen 1 und 3999 liegen")
+
+        val = [
+            (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"),
+            (100, "C"), (90, "XC"), (50, "L"), (40, "XL"),
+            (10, "X"), (9, "IX"), (5, "V"), (4, "IV"),
+            (1, "I")
+        ]
+
+        result = ""
+        for (value, numeral) in val:
+            while num >= value:
+                result += numeral
+                num -= value
+        return result
\ No newline at end of file
diff --git a/src/romannumerlas.py b/src/romannumerlas.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/tests/__pycache__/test_romannumerals.cpython-310.pyc b/tests/__pycache__/test_romannumerals.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e14f2572a91805d1b33f9c03c0890bd6a036010c
Binary files /dev/null and b/tests/__pycache__/test_romannumerals.cpython-310.pyc differ
diff --git a/tests/test_romannumerals.py b/tests/test_romannumerals.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a774cc92787102f3ef685b0c6a80138e5bbcedf
--- /dev/null
+++ b/tests/test_romannumerals.py
@@ -0,0 +1,108 @@
+# Basisfälle
+# Bei Eingabe der Zahl 1, erhalte ich das Ergebnis I
+# Bei Eingabe der Zahl 5, erhalte ich das Ergebnis V
+# Bei Eingabe der Zahl 10, erhalte ich das Ergebnis X
+# Bei Eingabe der Zahl 50, erhalte ich das Ergebnis L
+# Bei Eingabe der Zahl 100, erhalte ich das Ergebnis C
+# Bei Eingabe der Zahl 500, erhalte ich das Ergebnis D
+# Bei Eingabe der Zahl 1000, erhalte ich das Ergebnis M
+# Substraktionsregel
+# Bei Eingabe der Zahl 4, erhalte ich das Ergebnis IV
+# Bei Eingabe der Zahl 9, erhalte ich das Ergebnis IX
+# Bei Eingabe der Zahl 40, erhalte ich das Ergebnis XL
+# Bei Eingabe der Zahl 90, erhalte ich das Ergebnis XC
+# Bei Eingabe der Zahl 400, erhalte ich das Ergebnis CD
+# Bei Eingabe der Zahl 900, erhalte ich das Ergebnis CM
+# Additionsregel
+# Bei Eingabe der Zahl 2 erhalte ich das Ergebnis "II"
+# Bei Eingabe der Zahl 3 erhalte ich das Ergebnis "III"
+# Bei Eingabe der Zahl 6 erhalte ich das Ergebnis "VI"
+# Bei Eingabe der Zahl 8 erhalte ich das Ergebnis "VIII"
+# Bei Eingabe der Zahl 30 erhalte ich das Ergebnis "XXX"
+# Bei Eingabe der Zahl 80 erhalte ich das Ergebnis "LXXX"
+# Kombination aus Addition und Subtraktion
+# Bei Eingabe der Zahl 14 erhalte ich das Ergebnis "XIV"
+# Bei Eingabe der Zahl 19 erhalte ich das Ergebnis "XIX"
+# Bei Eingabe der Zahl 29 erhalte ich das Ergebnis "XXIX"
+# Bei Eingabe der Zahl 44 erhalte ich das Ergebnis "XLIV"
+# Bei Eingabe der Zahl 99 erhalte ich das Ergebnis "XCIX"
+# Bei Eingabe der Zahl 444 erhalte ich das Ergebnis "CDXLIV"
+# Bei Eingabe der Zahl 999 erhalte ich das Ergebnis "CMXCIX"
+# Größere Zahlen
+# Bei Eingabe der Zahl 1001 erhalte ich das Ergebnis "MI"
+# Bei Eingabe der Zahl 1987 erhalte ich das Ergebnis "MCMLXXXVII"
+# Bei Eingabe der Zahl 2023 erhalte ich das Ergebnis "MMXXIII"
+# Bei Eingabe der Zahl 3999 erhalte ich das Ergebnis "MMMCMXCIX"
+# Fehlerfälle
+# Bei Eingabe der Zahl 0 erhalte ich eine Fehlermeldung
+# Bei Eingabe der Zahl -1 erhalte ich eine Fehlermeldung
+# Bei Eingabe der Zahl 4000 erhalte ich eine Fehlermeldung
+# Bei Eingabe der Zeichenfolge "ABC" erhalte ich eine Fehlermeldung
+# Bei Eingabe von None erhalte ich eine Fehlermeldung
+# Bei Eingabe der Zahl 3.14 erhalte ich eine Fehlermeldung
+
+import unittest
+from src.romannumerals import RomanNumerals
+
+
+class TestRomanNumerals(unittest.TestCase):
+    def setUp(self):
+        self.converter = RomanNumerals()
+
+    def test_to_roman_basic(self):
+        self.assertEqual(self.converter.to_roman(1), "I")
+        self.assertEqual(self.converter.to_roman(5), "V")
+        self.assertEqual(self.converter.to_roman(10), "X")
+        self.assertEqual(self.converter.to_roman(50), "L")
+        self.assertEqual(self.converter.to_roman(100), "C")
+        self.assertEqual(self.converter.to_roman(500), "D")
+        self.assertEqual(self.converter.to_roman(1000), "M")
+
+    def test_to_roman_subtraction(self):
+        self.assertEqual(self.converter.to_roman(4), "IV")
+        self.assertEqual(self.converter.to_roman(9), "IX")
+        self.assertEqual(self.converter.to_roman(40), "XL")
+        self.assertEqual(self.converter.to_roman(90), "XC")
+        self.assertEqual(self.converter.to_roman(400), "CD")
+        self.assertEqual(self.converter.to_roman(900), "CM")
+
+    def test_to_roman_addition(self):
+        self.assertEqual(self.converter.to_roman(2), "II")
+        self.assertEqual(self.converter.to_roman(3), "III")
+        self.assertEqual(self.converter.to_roman(6), "VI")
+        self.assertEqual(self.converter.to_roman(8), "VIII")
+        self.assertEqual(self.converter.to_roman(30), "XXX")
+        self.assertEqual(self.converter.to_roman(80), "LXXX")
+
+    def test_to_roman_mixed(self):
+        self.assertEqual(self.converter.to_roman(14), "XIV")
+        self.assertEqual(self.converter.to_roman(19), "XIX")
+        self.assertEqual(self.converter.to_roman(29), "XXIX")
+        self.assertEqual(self.converter.to_roman(44), "XLIV")
+        self.assertEqual(self.converter.to_roman(99), "XCIX")
+        self.assertEqual(self.converter.to_roman(444), "CDXLIV")
+        self.assertEqual(self.converter.to_roman(999), "CMXCIX")
+
+    def test_to_roman_large_numbers(self):
+        self.assertEqual(self.converter.to_roman(1001), "MI")
+        self.assertEqual(self.converter.to_roman(1987), "MCMLXXXVII")
+        self.assertEqual(self.converter.to_roman(2023), "MMXXIII")
+        self.assertEqual(self.converter.to_roman(3999), "MMMCMXCIX")
+
+    def test_to_roman_invalid(self):
+        with self.assertRaises(ValueError):
+            self.converter.to_roman(0)
+        with self.assertRaises(ValueError):
+            self.converter.to_roman(-1)
+        with self.assertRaises(ValueError):
+            self.converter.to_roman(4000)
+        with self.assertRaises(ValueError):
+            self.converter.to_roman("ABC")
+        with self.assertRaises(ValueError):
+            self.converter.to_roman(None)
+        with self.assertRaises(ValueError):
+            self.converter.to_roman(3.14)
+
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file