Преглед на файлове

Merge branch 'feature/exceptions' of 1ffy/sp-1 into master

Всеволод Левитан преди 1 година
родител
ревизия
e857d6b903

+ 5 - 0
src/errors/argument_exception.py

@@ -0,0 +1,5 @@
+from src.errors.base_exception import base_exception
+
+class argument_exception(base_exception):
+    def __init__(self, *args):
+        super().__init__(args)

+ 14 - 0
src/errors/base_exception.py

@@ -0,0 +1,14 @@
+from src.errors.error_proxy import error_proxy
+
+
+class base_exception(Exception):
+    __inner_error: error_proxy = error_proxy()
+    
+    def __init__(self, *args: object) -> None:
+        super().__init__(*args)
+        self.__inner_error.set_error(self)
+        
+    @property    
+    def error(self):
+        return self.__inner_error      
+    

+ 90 - 0
src/errors/error_proxy.py

@@ -0,0 +1,90 @@
+
+
+class error_proxy:
+    __error_text = ""
+    __error_source = ""
+    __is_error = False
+    
+    
+    def __init__(self, error_text: str = "", error_source: str = "") -> None:
+        self.error_source = error_source
+        self.error_text = error_text
+        
+    
+    @property    
+    def error_text(self):
+        """
+            Текст сообщения
+        Returns:
+            _type_: _description_
+        """
+        return self.__error_text
+    
+    
+    @error_text.setter
+    def error_text(self, value: str):
+        if not isinstance(value, str):
+            raise Exception("Некорректно передан аргумент!")
+        
+        if(value.strip() ==""):
+            self.__is_error = False
+            return
+            
+        self.__error_text = value.strip()
+        self.__is_error = True
+        
+        
+    @property    
+    def error_source(self):
+        """
+            Источник ошибки
+        Returns:
+            _type_: _description_
+        """
+        return self.__error_source
+    
+    
+    @error_source.setter
+    def error_source(self, value: str):
+        if not isinstance(value, str):
+            raise Exception("Некорректно передан аргумент!")
+        
+        if(value.strip() ==""):
+            return
+            
+        self.__error_source = value.strip()
+    
+        
+    @property
+    def is_error(self):
+        """
+            Флаг. Есть ошибка
+        """
+        return self.__is_error  
+        
+        
+    def set_error(self, exception: Exception):
+        """
+            Сохранить ошибку
+        Args:
+            exception (Exception): _description_
+        """
+        if not isinstance(exception, Exception):
+            self.error_text = "Некорректно переданы параметры!"
+            self.error_source = "set_error" 
+            return
+
+        if exception is not None:        
+            self.error_text = f"ОШИБКА! {str(exception)}"
+            self.error_source = f"ИСКЛЮЧЕНИЕ! {type(exception)}"
+        else:
+            self.error_text = ""
+            
+                
+        
+        
+                    
+        
+        
+        
+        

+ 5 - 0
src/errors/file_exception.py

@@ -0,0 +1,5 @@
+from src.errors.base_exception import base_exception
+
+class file_exception(base_exception):
+    def __init__(self, *args):
+        super().__init__(args)

+ 5 - 0
src/errors/instance_exception.py

@@ -0,0 +1,5 @@
+from src.errors.base_exception import base_exception
+
+class instance_exception(base_exception):
+    def __init__(self, *args):
+        super().__init__(args)

+ 53 - 0
src/models/abstract_reference.py

@@ -0,0 +1,53 @@
+import uuid
+from abc import ABC
+from src.errors.error_proxy import error_proxy
+from src.validation.validator import validator
+
+class abstract_reference(ABC):
+    __id: uuid.UUID
+    __name:str = ""
+    __error: error_proxy = error_proxy()
+
+    # Валидатор
+    __vtor = validator()
+    
+    def __init__(self, name: str = None) -> None:
+        self.name = name
+        self.__id = uuid.uuid4()
+        
+    @property    
+    def error(self):
+        """
+           Работа с ошибками
+
+        Returns:
+            _type_: _description_
+        """
+        return self.__error    
+        
+    @property    
+    def id(self):
+        """
+            Уникальный код
+        Returns:
+            _type_: _description_
+        """
+        return self.__id    
+        
+    @property    
+    def name(self):
+        """
+           Наименование
+        Returns:
+            _type_: _description_
+        """
+        return self.__name.strip()    
+   
+    @name.setter 
+    def name(self, value: str):
+        self.__vtor.check_type(value, str)
+        value = value.strip()
+        self.__vtor.check_length_bound(value, 1, 50)
+        
+        self.__name = value
+        

+ 55 - 0
src/models/company_model.py

@@ -0,0 +1,55 @@
+from src.models.abstract_reference import abstract_reference
+from src.settings.settings import settings
+from src.validation.validator import validator
+
+class company_model (abstract_reference):
+    # ИНН
+    __tax_id = 0
+    # БИК
+    __bank_id = 0
+    # Счет
+    __bank_account_id = 0
+    # Форма собственности
+    __property_type = ""
+
+    # Валидатор
+    __vtor = validator()
+
+
+    def __init__(self, name, data: settings):
+        """
+        Args:
+            data (settings): Объект настроек с данными организации
+        """
+        self.__vtor.check_type(data, settings)
+        
+        self.__tax_id = data.tax_id
+        self.__bank_id = data.bank_id
+        self.__bank_account_id = data.bank_account_id
+        self.__property_type = data.property_type
+
+        super().__init__(name)
+
+    @property
+    def tax_id(self):
+        """ИНН"""
+
+        return self.__tax_id
+    
+    @property
+    def bank_id(self):
+        """БИК"""
+
+        return self.__bank_id
+    
+    @property
+    def bank_account_id(self):
+        """Банковский счет"""
+
+        return self.__bank_account_id
+    
+    @property
+    def property_type(self):
+        """Вид собственности"""
+
+        return self.__property_type

+ 83 - 0
src/models/measurement_unit_model.py

@@ -0,0 +1,83 @@
+from src.models.abstract_reference import abstract_reference
+from src.validation.validator import validator
+
+class measurement_unit_model (abstract_reference):
+    # Базовая единица измерения
+    __base_measurement_unit = None
+    # Базовый коэффициент
+    __base_coefficient = None
+
+    # Валидатор
+    __vtor = validator()
+
+    def __init__(self, name, base_coefficient = 1, base_measurement=None):
+        """
+        Args:
+            base_measurement (measurement_unit_model): Базовая единица измерения
+            base_coefficint (number): Базовый коэффициент
+        """
+
+        self.__vtor.check_type_any(base_measurement, measurement_unit_model, None)
+        self.__vtor.check_number(base_coefficient)
+
+        self.__base_measurement_unit = base_measurement
+        self.__base_coefficient = base_coefficient
+
+        super().__init__(name)
+        
+
+    @property
+    def base_measurement_unit(self):
+        """
+            Базовая единица измерения
+        """
+
+        if self.__base_measurement_unit is None:
+            return self
+
+        return self.__base_measurement_unit
+    
+    @base_measurement_unit.setter
+    def base_measurement_unit(self, value):
+        """
+            Базовая единица измерения
+        Args:
+            value (base_measurement_unit/None): Базовая единица измерения
+        Raises:
+            argument_exception: Несоответствие типа аргумента
+        """
+
+        self.__vtor.check_type_any(value, measurement_unit_model, None)
+
+        self.__base_measurement_unit = value
+
+    
+    @property
+    def base_coefficient(self):
+        """
+            Коэффициент относительно базовой единицы измерения
+        """
+
+        return self.__base_coefficient
+    
+    @base_coefficient.setter
+    def base_coefficient(self, value):
+        """
+            Коэффициент относительно базовой единицы измерения
+        Args:
+            value (Number): Базовый коэффициент
+        Raises:
+            argument_exception: Аргумент не является числом
+        """
+
+        self.__vtor.check_number(value)
+
+        self.__base_coefficient = value
+    
+
+    def to_base_unit(self, value):
+        """
+            Значение в базовой единице измерения
+        """
+
+        return value * self.base_coefficient

+ 5 - 0
src/models/nomenclature_group_model.py

@@ -0,0 +1,5 @@
+from src.models.abstract_reference import abstract_reference
+
+class nomenclature_group_model (abstract_reference):
+    def __init__(self, name):
+        super().__init__(name)

+ 97 - 0
src/models/nomenclature_model.py

@@ -0,0 +1,97 @@
+from src.models.abstract_reference import abstract_reference
+from src.models.measurement_unit_model import measurement_unit_model
+from src.models.nomenclature_group_model import nomenclature_group_model
+from src.validation.validator import validator
+
+class nomenclature_model(abstract_reference):
+    # Полное наименование
+    __full_name = ""
+    # Единица измерения
+    __measurement_unit = None
+    # Группа номенклатуры
+    __nomenclature_group = None
+
+    # Валидатор
+    __vtor = validator()
+
+
+    def __init__(self, name, full_name, measurement_unit, nomenclature_group):
+        """
+        Args:
+            full_name (str): Полное наименование (до 256 символов)
+            measurement_unit (measurement_unit_model): Единица измерения
+            nomenclature_group (nomenclature_group_model): Группа номенклатуры
+        """
+
+        self.__vtor.check_type(full_name, str)
+        self.__vtor.check_length_less(full_name, 256)
+        self.__vtor.check_type(measurement_unit, measurement_unit_model)
+        self.__vtor.check_type(nomenclature_group, nomenclature_group_model)
+
+        self.__full_name = full_name
+        self.__measurement_unit = measurement_unit
+        self.__nomenclature_group = nomenclature_group
+
+        super().__init__(name)
+
+    @property
+    def full_name(self):
+        """Полное наименование (до 256 символов)"""
+        
+        return self.__full_name
+    
+    @full_name.setter
+    def full_name(self, value: str):
+        """
+        Полное наименование (до 256 символов)
+        Args:
+            value (str): Полное наименование
+        Raises:
+            argument_exception: Несоответствие типа аргумента
+            argument_exception: Превышена длина аргумента
+        """
+
+        self.__vtor.check_type(value, str)
+        self.__vtor.check_length_less(256)
+
+        self.__full_name = value
+    
+    @property
+    def measurement_unit(self):
+        """Единица измерения"""
+
+        return self.__measurement_unit
+    
+    @measurement_unit.setter
+    def measurement_unit(self, value: measurement_unit_model):
+        """
+        Единица измерения
+        Args:
+            value (measurement_unit_model): Единица измерения
+        Raises:
+            argument_exception: Несоответствие типа аргумента
+        """
+
+        self.__vtor.check_type(value, measurement_unit_model)
+
+        self.__measurement_unit = value
+    
+    @property
+    def nomenclature_group(self):
+        """Группа номенклатуры"""
+
+        return self.__nomenclature_group
+    
+    @nomenclature_group.setter
+    def nomenclature_group(self, value: nomenclature_group_model):
+        """
+        Группа номенклатуры
+        Args:
+            value (nomenclature_group_model): Группа номенклатуры
+        Raises:
+            argument_exception: Несоответствие типа аргумента
+        """
+
+        self.__vtor.check_type(value, nomenclature_group_model)
+
+        self.__nomenclature_group = value

+ 5 - 0
src/models/warehouse_model.py

@@ -0,0 +1,5 @@
+from src.models.abstract_reference import abstract_reference
+
+class warehouse_model (abstract_reference):
+    def __init__(self, name):
+        super().__init__(name)

+ 1 - 1
src/settings.py → src/settings/settings.py

@@ -1,4 +1,4 @@
-from src.validator import validator
+from src.validation.validator import validator
 
 
 class settings:

+ 11 - 7
src/settings_manager.py → src/settings/settings_manager.py

@@ -1,5 +1,8 @@
 import os, json
-from src.settings import settings
+from src.settings.settings import settings
+from src.errors.instance_exception import instance_exception
+from src.validation.validator import validator
+from src.errors.file_exception import file_exception
 
 class settings_manager (object):
     # Объект настроек
@@ -9,6 +12,9 @@ class settings_manager (object):
     # Словарь со считанными данными
     __data = {}
 
+    # Валидатор
+    __vtor = validator()
+
 
     # Возвращаем существующий инстанс при вызове new() (singleton)
     def __new__(cls):
@@ -35,7 +41,7 @@ class settings_manager (object):
             self.__settings = settings()
         # Выбрасываем ошибку, если тип __settings не соответствует нужному
         if not isinstance(self.__settings, settings):
-            raise Exception("Невозможно создать экземпляр класса настроек")
+            raise instance_exception("Невозможно создать экземпляр класса настроек")
         # Переносим считанные значения в инстанс настроек
         for key in self.__data.keys():
             # Пропускаем, если у settings нет соответствующего свойства
@@ -52,12 +58,10 @@ class settings_manager (object):
             ValueError: Неверная длина аргумента
         """
         # Проверяем, чтобы путь был строкой
-        if not isinstance(filename, str):
-            raise TypeError("Неверный тип аргумента")
+        self.__vtor.check_type(filename, str)
         
         # Проверяем, чтобы путь не был пуст
-        if len(filename) == 0:
-            raise ValueError("Неверная длина аргумента")
+        self.__vtor.check_length_greater(filename, 0)
         
         # Убираем leading/trailing пробелы
         self.__filename = filename.strip()
@@ -74,7 +78,7 @@ class settings_manager (object):
 
         # Проверяем, существует ли файл по данному пути
         if not os.path.exists(settings_file):
-            raise FileNotFoundError("Невозможно загрузить файл настроек")
+            raise file_exception("Файл не найден")
         
         # Открываем файл и парсим JSON
         with open(settings_file, "r", encoding="UTF-8") as read_file:

+ 62 - 16
src/validator.py → src/validation/validator.py

@@ -1,6 +1,14 @@
 import re
+from numbers import Number
+from src.errors.argument_exception import argument_exception
 
 class validator:
+    # Singleton
+    def __new__(cls):
+        if not hasattr(cls, "instance"):
+            cls.instance = super(validator, cls).__new__(cls)
+        return cls.instance
+
     def check_type(self, value, exp_type):
         """
             Валидация аргумента по типу
@@ -8,11 +16,35 @@ class validator:
             value (any): Передаваемый аргумент
             type(Type): Ожидаемый тип
         Raises:
-            TypeError: Некорректный тип аргумента
+            argument_exception: Некорректный тип аргумента
         """
 
         if not isinstance(value, exp_type):
-            raise TypeError(f"Некорректный тип аргумента ({type(value)}, expected {exp_type})")
+            raise argument_exception(f"Некорректный тип аргумента ({type(value)}, expected {exp_type})")
+
+        return True
+    
+    def check_type_any(self, value, *types):
+        """
+            Валидация аргумента по соответствию одному из типов
+        Args:
+            value (any): Передаваемый аргумент
+            *types (Type): Ожидаемые типы
+        Raises:
+            argument_exception: Аргумент не соответствует ни одному из ожидаемых типов
+        """
+
+        flag = False
+        for t in types:
+            if t is None:
+                t = type(None)
+            if isinstance(value, t):
+                flag = True
+                break
+
+        if not flag:
+            raise argument_exception("Аргумент не соответствует ни одному из ожидаемых типов "\
+                                     + f"({type(value)}, expected={', '.join(types)})")
 
         return True
 
@@ -23,18 +55,18 @@ class validator:
             value (any): Передаваемый аргумент
             length (int): Ожидаемая длина
         Raises:
-            ValueError: Несоответствующая длина аргумента
+            argument_exception: Несоответствующая длина аргумента
         """
 
         if isinstance(value, int):
             value = str(value)
 
         if len(value) != length:
-            raise ValueError(f"Несоответствующая длина аргумента ({len(value)}, expected {length})")
+            raise argument_exception(f"Несоответствующая длина аргумента ({len(value)}, expected {length})")
 
         return True
 
-    def check_length_less(self, value, length: int, inclusive=True):
+    def check_length_less(self, value, length: int, inclusive=False):
         """
             Валидация аргумента по максимальной длине
         Args:
@@ -42,7 +74,7 @@ class validator:
             length (int): Максимальная допустимая длина
             inclusive (bool): Сравнивать включительно? default=True
         Raises:
-            ValueError: Превышена длина аргумента
+            argument_exception: Превышена длина аргумента
         """
 
         if value is int:
@@ -50,11 +82,11 @@ class validator:
         
         if (len(value) > length if inclusive \
                 else len(value) >= length):
-                    raise ValueError(f"Превышена длина аргумента ({len(value)}, max={length})")
+                    raise argument_exception(f"Превышена длина аргумента ({len(value)}, max={length})")
 
         return True
 
-    def check_length_greater(self, value, length: int, inclusive=True):
+    def check_length_greater(self, value, length: int, inclusive=False):
         """
             Валидация аргумента по минимальной длине
         Args:
@@ -62,7 +94,7 @@ class validator:
             length (int): Максимальная допустимая длина
             inclusive (bool): Сравнивать включительно? default=True
         Raises:
-            ValueError: Недостаточная длина аргумента
+            argument_exception: Недостаточная длина аргумента
         """
 
         if value is int:
@@ -70,7 +102,7 @@ class validator:
 
         if (len(value) < length if inclusive \
                 else len(value) <= length):
-            raise ValueError("Недостаточная длина аргумента ({len(value)}, min={length})")
+            raise argument_exception("Недостаточная длина аргумента ({len(value)}, min={length})")
 
         return True
 
@@ -84,8 +116,8 @@ class validator:
             inclusive_min (bool): Сравнимать минимальную длину включительно? default=True
             inclusive_max (bool): Сравнивать максимальную длину включительно? default=True
         Raises:
-            ValueError: Недостаточная длина аргумента
-            ValueError: Превышена длина аргумента
+            argument_exception: Недостаточная длина аргумента
+            argument_exception: Превышена длина аргумента
         """
 
         self.check_length_less(value, max_length, inclusive_max)
@@ -101,8 +133,8 @@ class validator:
             exp_type (Type): Ожидаемый тип
             length (int): Ожидаемая длина
         Raises:
-            TypeError: Несоответствие типа аргумента
-            ValueError: Несоответствие длины аргумента
+            argument_exception: Несоответствие типа аргумента
+            argument_exception: Несоответствие длины аргумента
         """
 
         self.check_type(value, exp_type)
@@ -117,10 +149,24 @@ class validator:
             value (any): Передаваемый аргумент
             expression (str): Регулярное выражение
         Raises:
-            ValueError: Аргумент не соответствует регулярному выражению
+            argument_exception: Аргумент не соответствует регулярному выражению
         """
 
         if re.match(expression, value) is None:
-            raise ValueError(f"Аргумент не соответствует регулярному выражению ({str(value)}, regex: {expression})")
+            raise argument_exception(f"Аргумент не соответствует регулярному выражению ({str(value)}, regex: {expression})")
 
         return True
+
+    def check_number(self, value):
+        """
+            Валидация аргумента по соответствию типу Число
+        Args:
+            value: Передаваемый аргумент
+        Raises:
+            argument_exception: Аргумент не является числом
+        """
+
+        if not isinstance(value, Number):
+            raise argument_exception(f"Аргумент не является числом (type={type(value)})")
+        
+        return True

+ 49 - 0
tests/test_errors.py

@@ -0,0 +1,49 @@
+from src.errors.error_proxy import error_proxy
+import unittest
+from src.errors.argument_exception import argument_exception
+
+
+
+class test_errors(unittest.TestCase):
+    
+    def test_check_argument_exception(self):
+        # Подготовка
+        
+        # Действие
+        try:
+            raise argument_exception("Test")
+        except argument_exception as ex:
+            # Проверка
+            print(ex.error.error_text)
+            print(ex.error.error_source)
+            
+            
+            assert ex.error.is_error
+            return
+            
+        assert False  
+        
+    
+    def test_check_set_exception(self):
+        # Подготовка
+        error = error_proxy()
+              
+        
+        # Действие
+        try:
+            result = 1 / 0
+        except Exception as ex  :
+            error.set_error(ex)
+            
+        # Проверки
+        assert error.is_error
+        
+    
+    def test_check_set_error_text(self):
+        # Подготовка
+        error = error_proxy("Test", "Test")
+        
+        # Действие
+        
+        # Проверки
+        assert error.is_error

+ 71 - 0
tests/test_models.py

@@ -0,0 +1,71 @@
+import unittest
+from src.models.company_model import company_model
+from src.settings.settings_manager import settings_manager
+from src.models.measurement_unit_model import measurement_unit_model
+from src.models.nomenclature_group_model import nomenclature_group_model
+from src.models.nomenclature_model import nomenclature_model
+from src.models.warehouse_model import warehouse_model
+from src.models.abstract_reference import abstract_reference
+from src.errors.argument_exception import argument_exception
+from os import path
+
+
+class test_models(unittest.TestCase):
+    def test_company(self):
+        # Подготовка
+        setman = settings_manager()
+        setman.open(path.dirname(__file__) + "/../config/settings.json")
+        sts = setman.settings
+    
+        # Действие
+        company = company_model("Test company", sts)
+    
+        # Проверка
+        assert isinstance(company, company_model)
+        print("c", company.tax_id)
+        print("s", sts.tax_id)
+        assert company.tax_id == sts.tax_id
+        assert company.bank_id == sts.bank_id
+        assert company.bank_account_id == sts.bank_account_id
+        assert company.property_type == sts.property_type
+        
+    def test_measurement_unit(self):
+        # Подготовка
+        g = measurement_unit_model("Граммы")
+        kg = measurement_unit_model("Килограммы", 1000, g)
+    
+        # Действие
+        
+    
+        # Проверка
+        assert isinstance(g, measurement_unit_model)
+        assert isinstance(kg, measurement_unit_model)
+        assert g.to_base_unit(1) == 1
+        assert kg.to_base_unit(1) == 1000
+
+    def test_nomenclature(self):
+        # Подготовка
+        munit = measurement_unit_model("Test munit")
+        fn = "abc"
+        nom = nomenclature_model("Test nomenclature", fn, munit, nomenclature_group_model("Test ng"))
+    
+        # Действие
+        
+    
+        # Проверка
+        assert isinstance(nom, nomenclature_model)
+        assert nom.full_name == fn
+        
+    def test_base_name_validation(self):
+        # Подготовка
+        fn = "abc"
+        some = abstract_reference(fn)
+        fn *= 2
+    
+        # Действие
+        some.name = fn
+    
+        # Проверка
+        assert some.name == fn
+    
+    

+ 2 - 72
tests/test_settings.py

@@ -1,6 +1,5 @@
-from src.settings import settings
-from src.settings_manager import settings_manager
-from src.validator import validator as settings_validator
+from src.settings.settings import settings
+from src.settings.settings_manager import settings_manager
 import unittest, os, random
     
 
@@ -84,72 +83,3 @@ class test_settings(unittest.TestCase):
         # Очистка
         os.remove(filename)
         os.removedirs(dirname)
-
-
-    def test_settings_validator_typeguard(self):
-        """Проверить работоспособность settings_validation.check_type()"""
-        # Подготовка
-        validator = settings_validator()
-
-        # Действие
-
-        # Проверка
-        assert validator.check_type("", str)
-        self.assertRaises(TypeError, lambda: validator.check_type("", int))
-
-    def test_settings_validator_len_exact(self):
-        """Проверить работоспособность settings_validator.check_length()"""
-        # Подготовка
-        validator = settings_validator()
-
-        # Действие
-
-        # Проверка
-        assert validator.check_length("aa", 2)
-        self.assertRaises(ValueError, lambda: validator.check_length("aa", 1))
-        self.assertRaises(ValueError, lambda: validator.check_length("aa", 3))
-
-    def test_settings_validator_len_int(self):
-        """Проверить работоспособность settings_validator.check_length() при передаче int"""
-        # Подготовка
-        validator = settings_validator()
-
-        # Действие
-
-        # Проверка
-        assert validator.check_length(10, 2)
-        self.assertRaises(ValueError, lambda: validator.check_length(10, 1))
-        self.assertRaises(ValueError, lambda: validator.check_length(10, 3))
-
-    def test_settings_validator_len_bound(self):
-        """Проверить работоспособность settings_validator.check_length_bound()"""
-        # Подготовка
-        validator = settings_validator()
-
-        # Действие
-
-        # Проверка
-
-        # Вхождение в минимум
-        assert validator.check_length_bound("abc", 3, 10)
-        # Вхождение в максимум
-        assert validator.check_length_bound("abc", 1, 3)
-        # Невхождение в максимум
-        self.assertRaises(ValueError, lambda: validator.check_length_bound("abc", 1, 2))
-        # Невхождение в минимум
-        self.assertRaises(ValueError, lambda: validator.check_length_bound("abc", 4, 5))
-        # Невхождение в исключительный минимум
-        self.assertRaises(ValueError, lambda: validator.check_length_bound("abc", 3, 5, inclusive_min=False))
-        # Невхождение в исключительный максимум
-        self.assertRaises(ValueError, lambda: validator.check_length_bound("abc", 1, 3, inclusive_max=False))
-
-    def test_settings_validator_regex(self):
-        """Проверить работоспособность settings_validator.check_regex()"""
-        # Подготовка
-        validator = settings_validator()
-
-        # Действие
-
-        # Проверка
-        assert validator.check_regex("abc", ".*b[c]+")
-        self.assertRaises(ValueError, lambda: validator.check_regex("abc", ".*b[c]+[a]+"))

+ 73 - 0
tests/test_validator.py

@@ -0,0 +1,73 @@
+from src.validation.validator import validator
+from src.errors.argument_exception import argument_exception
+import unittest
+
+class test_validator(unittest.TestCase):
+
+    def test_validator_typeguard(self):
+        """Проверить работоспособность settings_validation.check_type()"""
+        # Подготовка
+        vtor = validator()
+
+        # Действие
+
+        # Проверка
+        assert vtor.check_type("", str)
+        self.assertRaises(argument_exception, lambda: vtor.check_type("", int))
+
+    def test_validator_len_exact(self):
+        """Проверить работоспособность settings_validator.check_length()"""
+        # Подготовка
+        vtor = validator()
+
+        # Действие
+
+        # Проверка
+        assert vtor.check_length("aa", 2)
+        self.assertRaises(argument_exception, lambda: vtor.check_length("aa", 1))
+        self.assertRaises(argument_exception, lambda: vtor.check_length("aa", 3))
+
+    def test_validator_len_int(self):
+        """Проверить работоспособность settings_validator.check_length() при передаче int"""
+        # Подготовка
+        vtor = validator()
+
+        # Действие
+
+        # Проверка
+        assert vtor.check_length(10, 2)
+        self.assertRaises(argument_exception, lambda: vtor.check_length(10, 1))
+        self.assertRaises(argument_exception, lambda: vtor.check_length(10, 3))
+
+    def test_validator_len_bound(self):
+        """Проверить работоспособность settings_validator.check_length_bound()"""
+        # Подготовка
+        vtor = validator()
+
+        # Действие
+
+        # Проверка
+
+        # Вхождение в минимум
+        assert vtor.check_length_bound("abc", 3, 10)
+        # Вхождение в максимум
+        assert vtor.check_length_bound("abc", 1, 3)
+        # Невхождение в максимум
+        self.assertRaises(argument_exception, lambda: vtor.check_length_bound("abc", 1, 2))
+        # Невхождение в минимум
+        self.assertRaises(argument_exception, lambda: vtor.check_length_bound("abc", 4, 5))
+        # Невхождение в исключительный минимум
+        self.assertRaises(argument_exception, lambda: vtor.check_length_bound("abc", 3, 5, inclusive_min=False))
+        # Невхождение в исключительный максимум
+        self.assertRaises(argument_exception, lambda: vtor.check_length_bound("abc", 1, 3, inclusive_max=False))
+
+    def test_validator_regex(self):
+        """Проверить работоспособность settings_validator.check_regex()"""
+        # Подготовка
+        vtor = validator()
+
+        # Действие
+
+        # Проверка
+        assert vtor.check_regex("abc", ".*b[c]+")
+        self.assertRaises(argument_exception, lambda: vtor.check_regex("abc", ".*b[c]+[a]+"))