Jelajahi Sumber

Moved settings validation to settings_validator; Added corresponding unittests; Refactored comments for unittests; Simplified naming for unittests

Vsevolod Levitan 1 tahun lalu
induk
melakukan
5e841ecbff
2 mengubah file dengan 147 tambahan dan 30 penghapusan
  1. 126 0
      src/settings_validator.py
  2. 21 30
      tests/test_settings.py

+ 126 - 0
src/settings_validator.py

@@ -0,0 +1,126 @@
+import re
+
+class settings_validator:
+    def check_type(self, value, exp_type):
+        """
+            Валидация аргумента по типу
+        Args:
+            value (any): Передаваемый аргумент
+            type(Type): Ожидаемый тип
+        Raises:
+            TypeError: Некорректный тип аргумента
+        """
+
+        if not isinstance(value, exp_type):
+            raise TypeError(f"Некорректный тип аргумента ({type(value)}, expected {exp_type})")
+
+        return True
+
+    def check_length(self, value, length: int):
+        """
+            Валидация аргумента по длине
+        Args:
+            value (any): Передаваемый аргумент
+            length (int): Ожидаемая длина
+        Raises:
+            ValueError: Несоответствующая длина аргумента
+        """
+
+        if isinstance(value, int):
+            value = str(value)
+
+        if len(value) != length:
+            raise ValueError(f"Несоответствующая длина аргумента ({len(value)}, expected {length})")
+
+        return True
+
+    def check_length_less(self, value, length: int, inclusive=True):
+        """
+            Валидация аргумента по максимальной длине
+        Args:
+            value (any): Передаваемый аргумент
+            length (int): Максимальная допустимая длина
+            inclusive (bool): Сравнивать включительно? default=True
+        Raises:
+            ValueError: Превышена длина аргумента
+        """
+
+        if value is int:
+            value = str(value)
+        
+        if (len(value) > length if inclusive \
+                else len(value) >= length):
+                    raise ValueError(f"Превышена длина аргумента ({len(value)}, max={length})")
+
+        return True
+
+    def check_length_greater(self, value, length: int, inclusive=True):
+        """
+            Валидация аргумента по минимальной длине
+        Args:
+            value (any): Передаваемый аргумент
+            length (int): Максимальная допустимая длина
+            inclusive (bool): Сравнивать включительно? default=True
+        Raises:
+            ValueError: Недостаточная длина аргумента
+        """
+
+        if value is int:
+            value = str(value)
+
+        if (len(value) < length if inclusive \
+                else len(value) <= length):
+            raise ValueError("Недостаточная длина аргумента ({len(value)}, min={length})")
+
+        return True
+
+    def check_length_bound(self, value, min_length: int, max_length: int, inclusive_min=True, inclusive_max=True):
+        """
+            Валидация аргумента по минимальной и максимальной длинам
+        Args:
+            value (any): Передаваемый аргумент
+            min_length (int): Минимальная длина
+            max_length (int): Максимальная длина
+            inclusive_min (bool): Сравнимать минимальную длину включительно? default=True
+            inclusive_max (bool): Сравнивать максимальную длину включительно? default=True
+        Raises:
+            ValueError: Недостаточная длина аргумента
+            ValueError: Превышена длина аргумента
+        """
+
+        self.check_length_less(value, max_length, inclusive_max)
+        self.check_length_greater(value, min_length, inclusive_min)
+
+        return True
+
+    def check_type_length(self, value, exp_type, length: int):
+        """
+            Валидация аргумента по типу и длине
+        Args:
+            value (any): Передаваемый аргумент
+            exp_type (Type): Ожидаемый тип
+            length (int): Ожидаемая длина
+        Raises:
+            TypeError: Несоответствие типа аргумента
+            ValueError: Несоответствие длины аргумента
+        """
+
+        self.check_type(value, exp_type)
+        self.check_length(value, length)
+
+        return True
+
+    def check_regex(self, value, expression: str):
+        """
+            Валидация аргумента по регулярному выражению
+        Args:
+            value (any): Передаваемый аргумент
+            expression (str): Регулярное выражение
+        Raises:
+            ValueError: Аргумент не соответствует регулярному выражению
+        """
+
+        if re.match(expression, value) is None:
+            raise ValueError(f"Аргумент не соответствует регулярному выражению ({str(value)}, regex: {expression})")
+
+        return True

+ 21 - 30
tests/test_settings.py

@@ -8,10 +8,8 @@ class test_settings(unittest.TestCase):
     projdir = os.path.dirname(__file__) + "/.."
     projdir = os.path.dirname(__file__) + "/.."
     
     
     
     
-    #
-    # Провеиить корректность заполнения поля first_name
-    #
-    def test_check_first_name(self):
+    def first_name_setter(self):
+        """Проверить корректность заполнения поля first_name"""
         # Подготовка
         # Подготовка
         item = settings()
         item = settings()
         
         
@@ -21,10 +19,8 @@ class test_settings(unittest.TestCase):
         # Проверка
         # Проверка
         assert item.first_name == "a"
         assert item.first_name == "a"
 
 
-    #
-    # Проверить, что settings_manager инстанциируется только один раз
-    #
-    def test_check_settings_manager_singleton(self):
+    def settings_manager_singleton(self):
+        """Проверить, что settings_manager имплементирует singleton"""
         # Подготовка
         # Подготовка
         man1 = settings_manager()
         man1 = settings_manager()
         man2 = settings_manager()
         man2 = settings_manager()
@@ -34,11 +30,8 @@ class test_settings(unittest.TestCase):
         # Проверка
         # Проверка
         assert man1 is man2
         assert man1 is man2
 
 
-    
-    #
-    # Проверить корректность загрузки настроек
-    #
-    def test_check_open_settings(self):
+    def open_settings(self):
+        """Проверить корректность загрузки настроек"""
         # Подготовка
         # Подготовка
         man = settings_manager()
         man = settings_manager()
         
         
@@ -48,11 +41,8 @@ class test_settings(unittest.TestCase):
         # Проверка
         # Проверка
         assert result == True
         assert result == True
 
 
-
-    # 
-    # Проверить, что все поля настроек не пусты
-    #
-    def test_check_settings_fields_nonempty(self):
+    def settings_fields_nonempty(self):
+        """Проверить, что все поля настроек не пусты после считывания настроек"""
         # Подготовка
         # Подготовка
         man = settings_manager()
         man = settings_manager()
         settings = None
         settings = None
@@ -65,12 +55,9 @@ class test_settings(unittest.TestCase):
         # Проверка
         # Проверка
         for key in dict.keys():
         for key in dict.keys():
             assert len(str(dict[key])) != 0
             assert len(str(dict[key])) != 0
-    
-    #
-    #   Проверить, что менеджер настроек может открыть файл
-    #       с любым названием и в любой папке
-    #
-    def test_settings_any_filename(self):
+            
+    def settings_any_filename(self):
+        """Проверить, что менеджер настроек может открыть файл с любым названием и в любой папке"""
         # Подготовка
         # Подготовка
         if not os.path.exists(f"{self.projdir}/.test_data"):
         if not os.path.exists(f"{self.projdir}/.test_data"):
             os.mkdir(f"{self.projdir}/.test_data")
             os.mkdir(f"{self.projdir}/.test_data")
@@ -99,8 +86,8 @@ class test_settings(unittest.TestCase):
         os.removedirs(dirname)
         os.removedirs(dirname)
 
 
 
 
-    # Проверить, что валидатор не допускает значения неподходящей длины
-    def test_check_validator_typeguard(self):
+    def settings_validator_typeguard(self):
+        """Проверить работоспособность settings_validation.check_type()"""
         # Подготовка
         # Подготовка
         validator = settings_validator()
         validator = settings_validator()
 
 
@@ -110,7 +97,8 @@ class test_settings(unittest.TestCase):
         assert validator.check_type("", str)
         assert validator.check_type("", str)
         self.assertRaises(TypeError, lambda: validator.check_type("", int))
         self.assertRaises(TypeError, lambda: validator.check_type("", int))
 
 
-    def test_check_validator_len_exact(self):
+    def settings_validator_len_exact(self):
+        """Проверить работоспособность settings_validator.check_length()"""
         # Подготовка
         # Подготовка
         validator = settings_validator()
         validator = settings_validator()
 
 
@@ -121,7 +109,8 @@ class test_settings(unittest.TestCase):
         self.assertRaises(ValueError, lambda: validator.check_length("aa", 1))
         self.assertRaises(ValueError, lambda: validator.check_length("aa", 1))
         self.assertRaises(ValueError, lambda: validator.check_length("aa", 3))
         self.assertRaises(ValueError, lambda: validator.check_length("aa", 3))
 
 
-    def test_check_validator_len_int(self):
+    def settings_validator_len_int(self):
+        """Проверить работоспособность settings_validator.check_length() при передаче int"""
         # Подготовка
         # Подготовка
         validator = settings_validator()
         validator = settings_validator()
 
 
@@ -132,7 +121,8 @@ class test_settings(unittest.TestCase):
         self.assertRaises(ValueError, lambda: validator.check_length(10, 1))
         self.assertRaises(ValueError, lambda: validator.check_length(10, 1))
         self.assertRaises(ValueError, lambda: validator.check_length(10, 3))
         self.assertRaises(ValueError, lambda: validator.check_length(10, 3))
 
 
-    def test_check_validator_len_bound(self):
+    def settings_validator_len_bound(self):
+        """Проверить работоспособность settings_validator.check_length_bound()"""
         # Подготовка
         # Подготовка
         validator = settings_validator()
         validator = settings_validator()
 
 
@@ -153,7 +143,8 @@ class test_settings(unittest.TestCase):
         # Невхождение в исключительный максимум
         # Невхождение в исключительный максимум
         self.assertRaises(ValueError, lambda: validator.check_length_bound("abc", 1, 3, inclusive_max=False))
         self.assertRaises(ValueError, lambda: validator.check_length_bound("abc", 1, 3, inclusive_max=False))
 
 
-    def test_check_regex(self):
+    def settings_validator_regex(self):
+        """Проверить работоспособность settings_validator.check_regex()"""
         # Подготовка
         # Подготовка
         validator = settings_validator()
         validator = settings_validator()