Добавлены тесты для Environment
This commit is contained in:
@@ -7,6 +7,7 @@ omit =
|
|||||||
*/migrations/*
|
*/migrations/*
|
||||||
*/tests/*
|
*/tests/*
|
||||||
*/testing/*
|
*/testing/*
|
||||||
|
*/configs/*
|
||||||
*/apps.py
|
*/apps.py
|
||||||
manage.py
|
manage.py
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ exclude =
|
|||||||
*.__*
|
*.__*
|
||||||
*.get_absolute_url
|
*.get_absolute_url
|
||||||
net.xeaf.rack.core.testing.*
|
net.xeaf.rack.core.testing.*
|
||||||
net.xeaf.rack.core.views.experimental.*
|
net.xeaf.rack.utils.settings.config.*
|
||||||
|
|
||||||
# То, что мы ПРИНУДИТЕЛЬНО возвращаем назад (маски включения)
|
# То, что мы ПРИНУДИТЕЛЬНО возвращаем назад (маски включения)
|
||||||
# Этот список имеет наивысший приоритет!
|
# Этот список имеет наивысший приоритет!
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
Пакет описания тестов классов ядра
|
Пакет описания тестов классов ядра
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from .core_command_clear_database_tests import CoreCommandClearDatabaseTests
|
||||||
|
from .core_command_is_debug_or_test_tests import CoreCommandIsDebugOrTestTests
|
||||||
|
from .core_command_report_int_value_tests import CoreCommandReportIntValueTests
|
||||||
|
from .core_command_report_separator_tests import CoreCommandReportSeparatorTests
|
||||||
from .core_enum_check_is_empty_tests import CoreEnumCheckIsEmptyTests
|
from .core_enum_check_is_empty_tests import CoreEnumCheckIsEmptyTests
|
||||||
from .core_enum_choices_tests import CoreEnumChoicesTests
|
from .core_enum_choices_tests import CoreEnumChoicesTests
|
||||||
from .core_enum_from_string_tests import CoreEnumFromStringTests
|
from .core_enum_from_string_tests import CoreEnumFromStringTests
|
||||||
|
|||||||
11
net/xeaf/rack/tests/utils/__init__.py
Normal file
11
net/xeaf/rack/tests/utils/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Пакет описания тестов для служебных классов
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .settings import *
|
||||||
20
net/xeaf/rack/tests/utils/settings/__init__.py
Normal file
20
net/xeaf/rack/tests/utils/settings/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Пакет описания классов тестов классов работ с настройками
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .environment_check_initialization_tests import EnvironmentCheckInitializationTests
|
||||||
|
from .environment_env_name_tests import EnvironmentEnvNameTests
|
||||||
|
from .environment_env_tests import EnvironmentEnvTests
|
||||||
|
from .environment_get_bool_tests import EnvironmentGetBoolTests
|
||||||
|
from .environment_get_int_tests import EnvironmentGetIntTests
|
||||||
|
from .environment_get_str_as_dir_tests import EnvironmentGetStrAsDirTests
|
||||||
|
from .environment_get_str_as_file_tests import EnvironmentGetStrAsFileTests
|
||||||
|
from .environment_get_str_as_list_tests import EnvironmentGetStrAsListTests
|
||||||
|
from .environment_get_str_tests import EnvironmentGetStrTests
|
||||||
|
from .environment_initialize_tests import EnvironmentInitializeTests
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentCheckInitializationTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
class EnvironmentCheckInitializationTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment._check_initialization()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = False
|
||||||
|
|
||||||
|
def test_check_initialization_raises_error_when_not_initialized(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет выбрасывание ошибки при отсутствии инициализации
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ImproperlyConfigured) as context:
|
||||||
|
Environment._check_initialization()
|
||||||
|
|
||||||
|
self.assertIn("not initialized", str(context.exception))
|
||||||
|
|
||||||
|
def test_check_initialization_does_not_raise_when_initialized(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет отсутствие ошибки при инициализации
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
Environment._is_initialized = True
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
try:
|
||||||
|
Environment._check_initialization()
|
||||||
|
except ImproperlyConfigured:
|
||||||
|
self.fail("_check_initialization raised ImproperlyConfigured unexpectedly")
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentEnvNameTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentEnvNameTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment._env_name()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
|
||||||
|
def test_env_name_adds_prefix(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет добавление префикса к имени переменной
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
Environment._env_prefix = "PREFIX_"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment._env_name("VAR_NAME")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "PREFIX_VAR_NAME")
|
||||||
|
|
||||||
|
def test_env_name_with_empty_prefix(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет обработку пустого префикса
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
Environment._env_prefix = ""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment._env_name("VAR_NAME")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "VAR_NAME")
|
||||||
|
|
||||||
|
def test_env_name_handles_empty_name(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет обработку пустого имени переменной
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
Environment._env_prefix = "PREFIX_"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment._env_name("")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "PREFIX_")
|
||||||
|
|
||||||
|
def test_env_name_preserves_case(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет сохранение регистра имени переменной
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
Environment._env_prefix = "PREFIX_"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment._env_name("ApiKey")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "PREFIX_ApiKey")
|
||||||
55
net/xeaf/rack/tests/utils/settings/environment_env_tests.py
Normal file
55
net/xeaf/rack/tests/utils/settings/environment_env_tests.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentEnvTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentEnvTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.env()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды: сброс состояния Environment
|
||||||
|
"""
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
|
||||||
|
def test_env_returns_env_object_when_initialized(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что env() возвращает объект Env при инициализации
|
||||||
|
"""
|
||||||
|
# Arrange
|
||||||
|
mock_env = Mock()
|
||||||
|
Environment._env = mock_env
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.env()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, mock_env)
|
||||||
|
|
||||||
|
def test_env_raises_error_when_not_initialized(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что env() выбрасывает ошибку при отсутствии инициализации
|
||||||
|
"""
|
||||||
|
# Arrange
|
||||||
|
Environment._is_initialized = False
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ImproperlyConfigured) as context:
|
||||||
|
Environment.env()
|
||||||
|
self.assertIn("not initialized", str(context.exception))
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentGetBoolTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from environ import Env
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentGetBoolTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.get_bool()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
Environment._env_prefix = "APP_"
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_bool_returns_boolean_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение логического значения переменной окружения
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.bool.return_value = True
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_bool("DEBUG")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertTrue(result)
|
||||||
|
mock_env_instance.bool.assert_called_once_with("APP_DEBUG", Env.NOTSET)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_bool_with_default_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение логического значения с указанием значения по умолчанию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.bool.return_value = False
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_bool("DEBUG", False)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertFalse(result)
|
||||||
|
mock_env_instance.bool.assert_called_once_with("APP_DEBUG", False)
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentGetIntTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from environ import Env
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentGetIntTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.get_int()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
Environment._env_prefix = "APP_"
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_int_returns_integer_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение целочисленного значения переменной окружения
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.int.return_value = 42
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_int("PORT")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, 42)
|
||||||
|
mock_env_instance.int.assert_called_once_with("APP_PORT", Env.NOTSET)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_int_with_default_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение целочисленного значения с указанием значения по умолчанию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.int.return_value = 8080
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_int("PORT", 8080)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, 8080)
|
||||||
|
mock_env_instance.int.assert_called_once_with("APP_PORT", 8080)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_int_raises_error_for_invalid_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет выбрасывание ошибки при невалидном целочисленном значении
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.int.side_effect = ValueError("Invalid integer")
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
Environment.get_int("PORT")
|
||||||
|
self.assertIn("Invalid integer", str(context.exception))
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentGetStrAsDirTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentGetStrAsDirTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.get_str_as_dir()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
Environment._env_prefix = "APP_"
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
@patch('os.makedirs')
|
||||||
|
def test_get_str_as_dir_creates_directory(self, mock_makedirs, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет создание директории
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "/tmp/test_dir"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_dir("STORAGE_PATH")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "/tmp/test_dir")
|
||||||
|
mock_makedirs.assert_called_once_with("/tmp/test_dir", exist_ok=True)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
@patch('os.makedirs')
|
||||||
|
def test_get_str_as_dir_with_default_value(self, mock_makedirs, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет создание директории со значением по умолчанию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "/default/path"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_dir("STORAGE_PATH", "/default/path")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "/default/path")
|
||||||
|
mock_makedirs.assert_called_once_with("/default/path", exist_ok=True)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
@patch('os.makedirs')
|
||||||
|
def test_get_str_as_dir_handles_relative_path(self, mock_makedirs, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет создание директории с относительным путем
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "media/uploads"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_dir("UPLOAD_DIR")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "media/uploads")
|
||||||
|
mock_makedirs.assert_called_once_with("media/uploads", exist_ok=True)
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentGetStrAsFileTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentGetStrAsFileTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.get_str_as_file()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
Environment._env_prefix = "APP_"
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
@patch('os.path.dirname')
|
||||||
|
@patch('os.makedirs')
|
||||||
|
def test_get_str_as_file_creates_directory_for_file(self, mock_makedirs, mock_dirname, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет создание директории для файла
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "/logs/app.log"
|
||||||
|
mock_dirname.return_value = "/logs"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_file("LOG_FILE")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "/logs/app.log")
|
||||||
|
mock_dirname.assert_called_once_with("/logs/app.log")
|
||||||
|
mock_makedirs.assert_called_once_with("/logs", exist_ok=True)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
@patch('os.path.dirname')
|
||||||
|
@patch('os.makedirs')
|
||||||
|
def test_get_str_as_file_with_default_value(self, mock_makedirs, mock_dirname, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет создание директории для файла со значением по умолчанию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "/default/app.log"
|
||||||
|
mock_dirname.return_value = "/default"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_file("LOG_FILE", "/default/app.log")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "/default/app.log")
|
||||||
|
mock_makedirs.assert_called_once_with("/default", exist_ok=True)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
@patch('os.path.dirname')
|
||||||
|
@patch('os.makedirs')
|
||||||
|
def test_get_str_as_file_handles_filename_only(self, mock_makedirs, mock_dirname, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет создание директории для файла без пути
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "app.log"
|
||||||
|
mock_dirname.return_value = ""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_file("LOG_FILE")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "app.log")
|
||||||
|
mock_dirname.assert_called_once_with("app.log")
|
||||||
|
# Для пустой директории makedirs должен обработать корректно
|
||||||
|
mock_makedirs.assert_called_once_with("", exist_ok=True)
|
||||||
|
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentGetStrAsListTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentGetStrAsListTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.get_str_as_list()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
Environment._env_prefix = "APP_"
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_returns_list_from_comma_separated(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет преобразование строки с разделителями-запятыми в список
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "item1,item2,item3"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["item1", "item2", "item3"])
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_strips_spaces(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет удаление пробелов вокруг элементов
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = " item1 , item2 , item3 "
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["item1", "item2", "item3"])
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_returns_empty_list_for_empty_string(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет возврат пустого списка для пустой строки
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = ""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_filters_empty_items(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет фильтрацию пустых элементов
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "item1,,item2,,,item3"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["item1", "item2", "item3"])
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_returns_single_item(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет возврат списка с одним элементом
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "single_item"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["single_item"])
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_with_default_value(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет обработку списка со значением по умолчанию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "default1,default2"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS", "default1,default2")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["default1", "default2"])
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.get_str')
|
||||||
|
def test_get_str_as_list_handles_multiple_spaces_between_items(self, mock_get_str):
|
||||||
|
"""
|
||||||
|
Тест проверяет обработку множественных пробелов между элементами
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_get_str.return_value = "item1 , item2 , item3"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str_as_list("ITEMS")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["item1", "item2", "item3"])
|
||||||
118
net/xeaf/rack/tests/utils/settings/environment_get_str_tests.py
Normal file
118
net/xeaf/rack/tests/utils/settings/environment_get_str_tests.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentGetStrTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from environ import Env
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentGetStrTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.get_str()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды
|
||||||
|
"""
|
||||||
|
super().setUp()
|
||||||
|
Environment._is_initialized = True
|
||||||
|
Environment._env_prefix = "APP_"
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_str_returns_string_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение строкового значения переменной окружения
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.str.return_value = "test_value"
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str("TEST_VAR")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "test_value")
|
||||||
|
mock_env_instance.str.assert_called_once_with("APP_TEST_VAR", Env.NOTSET)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_str_with_default_value(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение строкового значения с указанием значения по умолчанию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.str.return_value = "default_value"
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str("TEST_VAR", "default_value")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "default_value")
|
||||||
|
mock_env_instance.str.assert_called_once_with("APP_TEST_VAR", "default_value")
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_str_with_env_notset(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение строкового значения с Env.NOTSET
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env_instance.str.return_value = "value"
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = Environment.get_str("TEST_VAR", Env.NOTSET)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, "value")
|
||||||
|
mock_env_instance.str.assert_called_once_with("APP_TEST_VAR", Env.NOTSET)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_str_adds_prefix_to_name(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет добавление префикса к имени переменной
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
Environment.get_str("API_KEY")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
mock_env_instance.str.assert_called_once_with("APP_API_KEY", Env.NOTSET)
|
||||||
|
|
||||||
|
@patch('net.xeaf.rack.utils.settings.Environment.env')
|
||||||
|
def test_get_str_with_empty_prefix(self, mock_env):
|
||||||
|
"""
|
||||||
|
Тест проверяет получение значения без префикса
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
Environment._env_prefix = ""
|
||||||
|
mock_env_instance = Mock()
|
||||||
|
mock_env.return_value = mock_env_instance
|
||||||
|
|
||||||
|
# Act
|
||||||
|
Environment.get_str("TEST_VAR")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
mock_env_instance.str.assert_called_once_with("TEST_VAR", Env.NOTSET)
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса EnvironmentInitializeTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from environ import Env
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from net.xeaf.rack.utils.settings import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentInitializeTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для Environment.initialize()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Подготовка тестовой среды: сброс состояния Environment
|
||||||
|
"""
|
||||||
|
|
||||||
|
super().setUp()
|
||||||
|
# Сбрасываем состояние класса перед каждым тестом
|
||||||
|
Environment._is_initialized = False
|
||||||
|
Environment._base_dir = ""
|
||||||
|
Environment._env = Env()
|
||||||
|
Environment._env_prefix = ""
|
||||||
|
|
||||||
|
@patch('environ.Env')
|
||||||
|
@patch('os.path.join')
|
||||||
|
def test_initialize_sets_base_dir_and_env(self, mock_join, mock_env_class):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что initialize корректно устанавливает базовую директорию и объект Env
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
base_dir = "/app/project"
|
||||||
|
env_prefix = "APP_"
|
||||||
|
mock_join.return_value = "/app/project/.env"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
Environment.initialize(base_dir, env_prefix)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(Environment._base_dir, base_dir)
|
||||||
|
self.assertEqual(Environment._env_prefix, env_prefix)
|
||||||
|
self.assertTrue(Environment._is_initialized)
|
||||||
|
mock_env_class.read_env.assert_called_once_with("/app/project/.env")
|
||||||
|
|
||||||
|
@patch('environ.Env')
|
||||||
|
@patch('os.path.join')
|
||||||
|
def test_initialize_with_empty_prefix(self, mock_join, mock_env_class):
|
||||||
|
"""
|
||||||
|
Тест проверяет инициализацию с пустым префиксом
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
base_dir = "/app/project"
|
||||||
|
env_prefix = ""
|
||||||
|
mock_join.return_value = "/app/project/.env"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
Environment.initialize(base_dir, env_prefix)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(Environment._env_prefix, "")
|
||||||
|
mock_env_class.read_env.assert_called_once_with("/app/project/.env")
|
||||||
|
|
||||||
|
@patch('environ.Env')
|
||||||
|
@patch('os.path.join')
|
||||||
|
def test_initialize_called_multiple_times(self, mock_join, mock_env_class):
|
||||||
|
"""
|
||||||
|
Тест проверяет повторную инициализацию
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
mock_join.return_value = "/app/project/.env"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
Environment.initialize("/app/project", "PREFIX_")
|
||||||
|
first_env = Environment._env
|
||||||
|
|
||||||
|
# Меняем поведение join для второго вызова, если это необходимо по вашей логике
|
||||||
|
mock_join.return_value = "/app/other/.env"
|
||||||
|
Environment.initialize("/app/other", "OTHER_")
|
||||||
|
second_env = Environment._env
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(first_env, second_env) # Оба должны указывать на наш mock_env_class
|
||||||
|
self.assertEqual(Environment._base_dir, "/app/other")
|
||||||
|
self.assertEqual(Environment._env_prefix, "OTHER_")
|
||||||
|
self.assertEqual(mock_env_class.read_env.call_count, 2)
|
||||||
|
|
||||||
|
@patch('environ.Env')
|
||||||
|
@patch('os.path.join')
|
||||||
|
def test_initialize_reads_dot_env_file(self, mock_join, mock_env_class):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что initialize читает файл .env через класс-метод
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
base_dir = "/app/project"
|
||||||
|
expected_env_path = "/app/project/.env"
|
||||||
|
mock_join.return_value = expected_env_path
|
||||||
|
|
||||||
|
# Act
|
||||||
|
Environment.initialize(base_dir)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
mock_env_class.read_env.assert_called_once_with(expected_env_path)
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
# Все права защищены. Лицензия: MIT
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Описание класса EnvUtils
|
Описание класса Environment
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -21,16 +21,16 @@ class Environment:
|
|||||||
Реализация доступа к параметрам и переменным окружения
|
Реализация доступа к параметрам и переменным окружения
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__base_dir: str
|
_base_dir: str
|
||||||
""" Путь к корневой директории приложения """
|
""" Путь к корневой директории приложения """
|
||||||
|
|
||||||
__is_initialized: bool
|
_is_initialized: bool
|
||||||
""" Признак инициализации конфигурации """
|
""" Признак инициализации конфигурации """
|
||||||
|
|
||||||
__env: Env
|
_env: Env
|
||||||
""" Хранилище переменных окружения """
|
""" Хранилище переменных окружения """
|
||||||
|
|
||||||
__env_prefix: str
|
_env_prefix: str
|
||||||
""" Префикс переменных окружения """
|
""" Префикс переменных окружения """
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -42,11 +42,12 @@ class Environment:
|
|||||||
:param env_prefix: Префикс переменных окружения
|
:param env_prefix: Префикс переменных окружения
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cls.__base_dir = base_dir
|
cls._base_dir = base_dir
|
||||||
cls.__env = environ.Env()
|
cls._env = environ.Env()
|
||||||
cls.__env_prefix = env_prefix
|
cls._env_prefix = env_prefix
|
||||||
environ.Env.read_env(os.path.join(cls.__base_dir, '.env'))
|
env_path = os.path.join(cls._base_dir, '.env')
|
||||||
cls.__is_initialized = True
|
environ.Env.read_env(env_path)
|
||||||
|
cls._is_initialized = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def env(cls) -> Env:
|
def env(cls) -> Env:
|
||||||
@@ -57,7 +58,7 @@ class Environment:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
cls._check_initialization()
|
cls._check_initialization()
|
||||||
return cls.__env
|
return cls._env
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_str(cls, name: str, default_value: str | NoValue = Env.NOTSET) -> str:
|
def get_str(cls, name: str, default_value: str | NoValue = Env.NOTSET) -> str:
|
||||||
@@ -158,7 +159,7 @@ class Environment:
|
|||||||
:return: Имя переменной окружения
|
:return: Имя переменной окружения
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return f"{cls.__env_prefix}{name}"
|
return f"{cls._env_prefix}{name}"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _check_initialization(cls) -> None:
|
def _check_initialization(cls) -> None:
|
||||||
@@ -166,5 +167,5 @@ class Environment:
|
|||||||
Проверяет завершение инициализации
|
Проверяет завершение инициализации
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not cls.__is_initialized:
|
if not cls._is_initialized:
|
||||||
raise ImproperlyConfigured(f"Class {__class__.__name__} is not initialized.")
|
raise ImproperlyConfigured(f"Class {__class__.__name__} is not initialized.")
|
||||||
|
|||||||
Reference in New Issue
Block a user