Добавлены тесты для Environment

This commit is contained in:
2026-07-20 15:33:46 +03:00
parent 781e885ffb
commit 304fa18bce
16 changed files with 928 additions and 14 deletions

View File

@@ -7,6 +7,7 @@ omit =
*/migrations/* */migrations/*
*/tests/* */tests/*
*/testing/* */testing/*
*/configs/*
*/apps.py */apps.py
manage.py manage.py

View File

@@ -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.*
# То, что мы ПРИНУДИТЕЛЬНО возвращаем назад (маски включения) # То, что мы ПРИНУДИТЕЛЬНО возвращаем назад (маски включения)
# Этот список имеет наивысший приоритет! # Этот список имеет наивысший приоритет!

View File

@@ -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

View File

@@ -0,0 +1,11 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Пакет описания тестов для служебных классов
"""
from .settings import *

View 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

View File

@@ -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")

View File

@@ -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")

View 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))

View File

@@ -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)

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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"])

View 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)

View File

@@ -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)

View File

@@ -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.")