Repository: bo4e/BO4E-python (language: python)

Issue:
Implement COM Regionskriterium
https://www.bo4e.de/dokumentation/komponenten/com-regionskriterium

[Regionskriterium](https://www.bo4e.de/dokumentation/komponenten/com-regionskriterium)
- #85 
- #135 


Discussion / hints:

Fix patch:
diff --git a/src/bo4e/com/regionskriterium.py b/src/bo4e/com/regionskriterium.py
new file mode 100644
index 000000000..8818ced25
--- /dev/null
+++ b/src/bo4e/com/regionskriterium.py
@@ -0,0 +1,50 @@
+"""
+Contains Regionskriterium class and corresponding marshmallow schema for de-/serialization
+"""
+
+
+# pylint: disable=too-few-public-methods
+import attr
+from marshmallow import fields, post_load
+from marshmallow_enum import EnumField  # type:ignore[import]
+
+from bo4e.com.com import COM, COMSchema
+from bo4e.enum.gueltigkeitstyp import Gueltigkeitstyp
+from bo4e.enum.regionskriteriumtyp import Regionskriteriumtyp
+
+
+@attr.s(auto_attribs=True, kw_only=True)
+class Regionskriterium(COM):
+    """
+    Komponente zur Abbildung eines Regionskriteriums
+    """
+
+    # required attributes
+    gueltigkeitstyp: Gueltigkeitstyp = attr.ib(
+        validator=attr.validators.instance_of(Gueltigkeitstyp)
+    )  #: Hier wird festgelegt, ob es sich um ein einschließendes oder ausschließendes Kriterium handelt.
+    regionskriteriumtyp: Regionskriteriumtyp = attr.ib(
+        validator=attr.validators.instance_of(Regionskriteriumtyp)
+    )  #: Hier wird das Kriterium selbst angegeben, z.B. Bundesland.
+    wert: str = attr.ib(validator=attr.validators.instance_of(str))
+    """
+    Der Wert, den das Kriterium annehmen kann, z.B. NRW.
+    Im Falle des Regionskriteriumstyp BUNDESWEIT spielt dieser Wert keine Rolle.
+    """
+
+
+class RegionskriteriumSchema(COMSchema):
+    """
+    Schema for de-/serialization of Regionskriterium.
+    """
+
+    # required attributes
+    gueltigkeitstyp = EnumField(Gueltigkeitstyp)
+    regionskriteriumtyp = EnumField(Regionskriteriumtyp)
+    wert = fields.String()
+
+    # pylint: disable=no-self-use, unused-argument
+    @post_load
+    def deserialize(self, data, **kwargs) -> Regionskriterium:
+        """Deserialize JSON to Regionskriterium object"""
+        return Regionskriterium(**data)


Test patch:
diff --git a/tests/serialization_helper.py b/tests/serialization_helper.py
new file mode 100644
index 000000000..985661c4b
--- /dev/null
+++ b/tests/serialization_helper.py
@@ -0,0 +1,26 @@
+"""
+A module that simplifies assertions for json serialization
+"""
+import json
+from typing import TypeVar
+
+from marshmallow import Schema
+
+T = TypeVar("T")
+
+
+def assert_serialization_roundtrip(serializable_object: T, schema: Schema, expected_json_dict: dict) -> T:
+    """
+    Serializes the serializable_object using the provided schema,
+    asserts, that the result is equal to the expected_json_dict
+    then deserializes it again and asserts on equality with the original serializable_object
+    :returns the deserialized_object
+    """
+    json_string = schema.dumps(serializable_object)
+    assert json_string is not None
+    actual_json_dict = json.loads(json_string)
+    assert actual_json_dict == expected_json_dict
+    deserialized_object = schema.loads(json_data=json_string)
+    assert isinstance(deserialized_object, type(serializable_object))
+    assert deserialized_object == serializable_object
+    return deserialized_object
diff --git a/tests/test_regionskriterium.py b/tests/test_regionskriterium.py
new file mode 100644
index 000000000..8ada2874c
--- /dev/null
+++ b/tests/test_regionskriterium.py
@@ -0,0 +1,38 @@
+import pytest  # type:ignore[import]
+
+from bo4e.com.regionskriterium import Regionskriterium, RegionskriteriumSchema
+from bo4e.enum.gueltigkeitstyp import Gueltigkeitstyp
+from bo4e.enum.regionskriteriumtyp import Regionskriteriumtyp
+from tests.serialization_helper import assert_serialization_roundtrip  # type:ignore[import]
+
+
+class TestRegionskriterium:
+    @pytest.mark.parametrize(
+        "regionskriterium, expected_json_dict",
+        [
+            pytest.param(
+                Regionskriterium(
+                    regionskriteriumtyp=Regionskriteriumtyp.REGELGEBIET_NAME,
+                    gueltigkeitstyp=Gueltigkeitstyp.NICHT_IN,
+                    wert="Was ist ein Regionskriterium?",
+                ),
+                {
+                    "gueltigkeitstyp": "NICHT_IN",
+                    "regionskriteriumtyp": "REGELGEBIET_NAME",
+                    "wert": "Was ist ein Regionskriterium?",
+                },
+            ),
+        ],
+    )
+    def test_regionskriterium_serialization_roundtrip(
+        self, regionskriterium: Regionskriterium, expected_json_dict: dict
+    ):
+        """
+        Test de-/serialisation of Regionskriterium with minimal attributes.
+        """
+        assert_serialization_roundtrip(regionskriterium, RegionskriteriumSchema(), expected_json_dict)
+
+    def test_regionskriterium_missing_required_attribute(self):
+        with pytest.raises(TypeError) as excinfo:
+            _ = Regionskriterium()
+        assert "missing 3 required" in str(excinfo.value)