Добавлены тесты для CoreEnum
This commit is contained in:
@@ -24,6 +24,7 @@ class CoreEnum(StrEnum):
|
|||||||
:return: Список для выбора значения
|
:return: Список для выбора значения
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
cls._check_is_empty()
|
||||||
return [(item.value, item.name) for item in cls]
|
return [(item.value, item.name) for item in cls]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -34,6 +35,7 @@ class CoreEnum(StrEnum):
|
|||||||
:return: Список ключей
|
:return: Список ключей
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
cls._check_is_empty()
|
||||||
return [item.name for item in cls]
|
return [item.name for item in cls]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -44,4 +46,34 @@ class CoreEnum(StrEnum):
|
|||||||
:return: Список значений
|
:return: Список значений
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return [item.value for item in cls]
|
cls._check_is_empty()
|
||||||
|
return [item.value for item in cls.__members__.values()]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _check_is_empty(cls):
|
||||||
|
"""
|
||||||
|
Проверяет, что перечисление не пустое
|
||||||
|
|
||||||
|
:return: True, если перечисление не пустое
|
||||||
|
"""
|
||||||
|
|
||||||
|
count = len(cls)
|
||||||
|
if count == 0:
|
||||||
|
raise ValueError(f"The {cls.__name__} enum must not be empty.")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_string(cls, value: str) -> CoreEnum:
|
||||||
|
"""
|
||||||
|
Возвращает перечисление по строковому значению
|
||||||
|
|
||||||
|
:param value: Строковое значение
|
||||||
|
|
||||||
|
:return: Перечисление
|
||||||
|
"""
|
||||||
|
|
||||||
|
for item in cls:
|
||||||
|
if item.value == value:
|
||||||
|
return item
|
||||||
|
|
||||||
|
raise ValueError(f"The {cls.__name__} enum does not contain the value '{value}'")
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,9 @@
|
|||||||
"""
|
"""
|
||||||
Пакет описания тестов классов ядра
|
Пакет описания тестов классов ядра
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from .core_enum_check_is_empty_tests import CoreEnumCheckIsEmptyTests
|
||||||
|
from .core_enum_choices_tests import CoreEnumChoicesTests
|
||||||
|
from .core_enum_from_string_tests import CoreEnumFromStringTests
|
||||||
|
from .core_enum_keys_tests import CoreEnumKeysTests
|
||||||
|
from .core_enum_values_tests import CoreEnumValuesTests
|
||||||
|
|||||||
66
net/xeaf/rack/tests/core/_core_enum_mocks.py
Normal file
66
net/xeaf/rack/tests/core/_core_enum_mocks.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание mock-классов для CoreEnumChoicesTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core import CoreEnum
|
||||||
|
|
||||||
|
|
||||||
|
class TestEnum(CoreEnum):
|
||||||
|
"""
|
||||||
|
Тестовое перечисление для проверки методов choices, keys, values
|
||||||
|
"""
|
||||||
|
|
||||||
|
OPTION1 = "value1"
|
||||||
|
OPTION2 = "value2"
|
||||||
|
OPTION3 = "value3"
|
||||||
|
|
||||||
|
|
||||||
|
class TestOrderedEnum(CoreEnum):
|
||||||
|
"""
|
||||||
|
Тестовое перечисление с упорядоченными элементами
|
||||||
|
"""
|
||||||
|
|
||||||
|
FIRST = "first"
|
||||||
|
SECOND = "second"
|
||||||
|
THIRD = "third"
|
||||||
|
|
||||||
|
|
||||||
|
class TestDuplicateEnum(CoreEnum):
|
||||||
|
"""
|
||||||
|
Тестовое перечисление с дублирующимися значениями
|
||||||
|
"""
|
||||||
|
|
||||||
|
ONE = "same"
|
||||||
|
TWO = "same"
|
||||||
|
THREE = "different"
|
||||||
|
|
||||||
|
|
||||||
|
class TestCaseEnum(CoreEnum):
|
||||||
|
"""
|
||||||
|
Тестовое перечисление с элементами разных регистров
|
||||||
|
"""
|
||||||
|
|
||||||
|
LOW = "lower"
|
||||||
|
UPPER = "UPPER"
|
||||||
|
|
||||||
|
|
||||||
|
class TestSingleEnum(CoreEnum):
|
||||||
|
"""
|
||||||
|
Тестовое перечисление с одним элементом
|
||||||
|
"""
|
||||||
|
|
||||||
|
ONLY = "only_value"
|
||||||
|
|
||||||
|
|
||||||
|
class TestEmptyEnum(CoreEnum):
|
||||||
|
"""
|
||||||
|
Пустое тестовое перечисление
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
52
net/xeaf/rack/tests/core/core_enum_check_is_empty_tests.py
Normal file
52
net/xeaf/rack/tests/core/core_enum_check_is_empty_tests.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса CoreEnumCheckIsEmptyTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from ._core_enum_mocks import TestEmptyEnum
|
||||||
|
from ._core_enum_mocks import TestEnum
|
||||||
|
|
||||||
|
|
||||||
|
class CoreEnumCheckIsEmptyTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для метода CoreEnum._check_is_empty()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_check_is_empty_with_non_empty_enum_does_not_raise_error(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что _check_is_empty не выбрасывает исключение для непустого перечисления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
try:
|
||||||
|
TestEnum._check_is_empty()
|
||||||
|
except ValueError:
|
||||||
|
self.fail("_check_is_empty raised ValueError unexpectedly for non-empty enum")
|
||||||
|
|
||||||
|
def test_check_is_empty_with_empty_enum_raises_value_error(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что _check_is_empty выбрасывает ValueError для пустого перечисления"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum._check_is_empty()
|
||||||
|
|
||||||
|
self.assertIn("enum must not be empty", str(context.exception))
|
||||||
|
|
||||||
|
def test_check_is_empty_uses_correct_class_name_in_error(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что в сообщении об ошибке используется правильное имя класса
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum._check_is_empty()
|
||||||
|
|
||||||
|
self.assertNotIn("CoreEnum", str(context.exception))
|
||||||
77
net/xeaf/rack/tests/core/core_enum_choices_tests.py
Normal file
77
net/xeaf/rack/tests/core/core_enum_choices_tests.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса CoreEnumChoicesTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from ._core_enum_mocks import TestEmptyEnum
|
||||||
|
from ._core_enum_mocks import TestEnum
|
||||||
|
from ._core_enum_mocks import TestOrderedEnum
|
||||||
|
from ._core_enum_mocks import TestSingleEnum
|
||||||
|
|
||||||
|
|
||||||
|
class CoreEnumChoicesTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для CoreEnum.choices()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_choices_returns_list_of_tuples_with_value_and_name(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод choices возвращает список кортежей (значение, имя)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
expected = [("value1", "OPTION1"), ("value2", "OPTION2"), ("value3", "OPTION3")]
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestEnum.choices()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertIsInstance(result, list)
|
||||||
|
self.assertIsInstance(result[0], tuple)
|
||||||
|
self.assertEqual(len(result), 3)
|
||||||
|
|
||||||
|
def test_choices_returns_empty_list_for_empty_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что для пустого перечисления метод choices выбрасывает исключение
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum.choices()
|
||||||
|
|
||||||
|
self.assertIn("enum must not be empty", str(context.exception))
|
||||||
|
|
||||||
|
def test_choices_preserves_enum_member_order(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет сохранение порядка элементов перечисления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestOrderedEnum.choices()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result[0], ("first", "FIRST"))
|
||||||
|
self.assertEqual(result[1], ("second", "SECOND"))
|
||||||
|
self.assertEqual(result[2], ("third", "THIRD"))
|
||||||
|
|
||||||
|
def test_choices_handles_single_member_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет работу метода choices с перечислением из одного элемента
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
expected = [("only_value", "ONLY")]
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestSingleEnum.choices()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertEqual(len(result), 1)
|
||||||
123
net/xeaf/rack/tests/core/core_enum_from_string_tests.py
Normal file
123
net/xeaf/rack/tests/core/core_enum_from_string_tests.py
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса CoreEnumFromStringTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from ._core_enum_mocks import TestCaseEnum
|
||||||
|
from ._core_enum_mocks import TestDuplicateEnum
|
||||||
|
from ._core_enum_mocks import TestEmptyEnum
|
||||||
|
from ._core_enum_mocks import TestEnum
|
||||||
|
from ._core_enum_mocks import TestSingleEnum
|
||||||
|
|
||||||
|
|
||||||
|
class CoreEnumFromStringTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для CoreEnum.from_string()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_from_string_returns_correct_enum_member(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод from_string возвращает корректный элемент перечисления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestEnum.from_string("value2")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, TestEnum.OPTION2)
|
||||||
|
self.assertEqual(result.value, "value2")
|
||||||
|
self.assertEqual(result.name, "OPTION2")
|
||||||
|
|
||||||
|
def test_from_string_returns_first_matching_member_for_duplicate_values(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что при дублирующихся значениях возвращается первый найденный элемент
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestDuplicateEnum.from_string("same")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, TestDuplicateEnum.ONE)
|
||||||
|
self.assertEqual(result.value, "same")
|
||||||
|
self.assertEqual(result.name, "ONE")
|
||||||
|
|
||||||
|
def test_from_string_raises_error_for_non_existent_value(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что для несуществующего значения выбрасывается ValueError
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEnum.from_string("non_existent_value")
|
||||||
|
|
||||||
|
self.assertIn("enum does not contain the value 'non_existent_value'", str(context.exception))
|
||||||
|
|
||||||
|
def test_from_string_raises_error_for_empty_string(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что для пустой строки выбрасывается ValueError
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEnum.from_string("")
|
||||||
|
|
||||||
|
self.assertIn("enum does not contain the value ''", str(context.exception))
|
||||||
|
|
||||||
|
def test_from_string_raises_error_for_empty_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что для пустого перечисления выбрасывается ValueError
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum.from_string("any_value")
|
||||||
|
|
||||||
|
self.assertIn("enum does not contain the value 'any_value'", str(context.exception))
|
||||||
|
|
||||||
|
def test_from_string_works_with_single_member_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет работу метода from_string с перечислением из одного элемента
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestSingleEnum.from_string("only_value")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, TestSingleEnum.ONLY)
|
||||||
|
self.assertEqual(result.value, "only_value")
|
||||||
|
self.assertEqual(result.name, "ONLY")
|
||||||
|
|
||||||
|
def test_from_string_case_sensitive_matching(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что поиск значения чувствителен к регистру
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result_lower = TestCaseEnum.from_string("lower")
|
||||||
|
result_upper = TestCaseEnum.from_string("UPPER")
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result_lower, TestCaseEnum.LOW)
|
||||||
|
self.assertEqual(result_upper, TestCaseEnum.UPPER)
|
||||||
|
|
||||||
|
# Проверяем, что поиск с другим регистром вызывает ошибку
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
TestCaseEnum.from_string("Lower")
|
||||||
|
|
||||||
|
def test_from_string_uses_correct_class_name_in_error(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что в сообщении об ошибке используется правильное имя класса
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEnum.from_string("wrong")
|
||||||
|
|
||||||
|
self.assertIn("TestEnum", str(context.exception))
|
||||||
|
self.assertNotIn("CoreEnum", str(context.exception))
|
||||||
69
net/xeaf/rack/tests/core/core_enum_keys_tests.py
Normal file
69
net/xeaf/rack/tests/core/core_enum_keys_tests.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса CoreEnumKeysTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from ._core_enum_mocks import TestEmptyEnum
|
||||||
|
from ._core_enum_mocks import TestEnum
|
||||||
|
from ._core_enum_mocks import TestOrderedEnum
|
||||||
|
from ._core_enum_mocks import TestSingleEnum
|
||||||
|
|
||||||
|
|
||||||
|
class CoreEnumKeysTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для CoreEnum.keys()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_keys_returns_list_of_enum_member_names(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод keys возвращает список имен элементов перечисления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
expected = ["OPTION1", "OPTION2", "OPTION3"]
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestEnum.keys()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertIsInstance(result, list)
|
||||||
|
self.assertEqual(len(result), 3)
|
||||||
|
|
||||||
|
def test_keys_returns_empty_list_for_empty_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что для пустого перечисления метод keys выбрасывает исключение
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum.keys()
|
||||||
|
self.assertIn("enum must not be empty", str(context.exception))
|
||||||
|
|
||||||
|
def test_keys_returns_names_in_definition_order(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод keys возвращает имена в порядке объявления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestOrderedEnum.keys()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["FIRST", "SECOND", "THIRD"])
|
||||||
|
|
||||||
|
def test_keys_works_with_single_member_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет работу метода keys с перечислением из одного элемента
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestSingleEnum.keys()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["ONLY"])
|
||||||
85
net/xeaf/rack/tests/core/core_enum_values_tests.py
Normal file
85
net/xeaf/rack/tests/core/core_enum_values_tests.py
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# DRF Rack
|
||||||
|
# Библиотека классов расширений для Django REST Framework
|
||||||
|
#
|
||||||
|
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
|
||||||
|
# Все права защищены. Лицензия: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Описание класса CoreEnumValuesTests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from net.xeaf.rack.core.testing import CoreSimpleTestCase
|
||||||
|
from ._core_enum_mocks import TestDuplicateEnum
|
||||||
|
from ._core_enum_mocks import TestEmptyEnum
|
||||||
|
from ._core_enum_mocks import TestEnum
|
||||||
|
from ._core_enum_mocks import TestOrderedEnum
|
||||||
|
from ._core_enum_mocks import TestSingleEnum
|
||||||
|
|
||||||
|
|
||||||
|
class CoreEnumValuesTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс CoreEnum.values()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_values_returns_list_of_enum_member_values(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод values возвращает список значений элементов перечисления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
expected = ["value1", "value2", "value3"]
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestEnum.values()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertIsInstance(result, list)
|
||||||
|
self.assertEqual(len(result), 3)
|
||||||
|
|
||||||
|
def test_values_returns_empty_list_for_empty_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что для пустого перечисления метод values выбрасывает исключение
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act & Assert
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum.values()
|
||||||
|
self.assertIn("enum must not be empty", str(context.exception))
|
||||||
|
|
||||||
|
def test_values_returns_values_in_definition_order(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод values возвращает значения в порядке объявления
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestOrderedEnum.values()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["first", "second", "third"])
|
||||||
|
|
||||||
|
def test_values_handles_duplicate_values_in_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод values корректно обрабатывает дублирующиеся значения
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
expected = ["same", "same", "different"]
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestDuplicateEnum.values()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertEqual(len(result), 3)
|
||||||
|
|
||||||
|
def test_values_works_with_single_member_enum(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет работу метода values с перечислением из одного элемента
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Act
|
||||||
|
result = TestSingleEnum.values()
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(result, ["only_value"])
|
||||||
50
testing_2_llm.md
Normal file
50
testing_2_llm.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
Ты — специализированный интерактивный ИИ-ассистент, эксперт по тестированию веб-приложений на Django и Django REST Framework (DRF) для библиотеки DRF-Rack (пакет `net.xeaf.rack`).
|
||||||
|
|
||||||
|
Твоя задача — работать в режиме контекстного генератора по командам пользователя. После получения этого промпта ничего не генерируй, просто ответь: "Контекст DRF-Rack принят. Ожидаю исходный код класса."
|
||||||
|
|
||||||
|
### РЕЖИМЫ РАБОТЫ И КОМАНДЫ ПОЛЬЗОВАТЕЛЯ
|
||||||
|
Ты должен строго переключать логику работы в зависимости от текстовой команды, которую пришлет пользователь вместе с кодом:
|
||||||
|
|
||||||
|
---
|
||||||
|
КОМАНДА 1: "сгенерировать mock-файл"
|
||||||
|
Твоя задача — проанализировать структуру предоставленного класса и создать для него ЕДИНЫЙ изолированный файл вспомогательных служебных классов и моков (Mocks), которые будут использоваться во всех последующих автотестах для этого класса.
|
||||||
|
|
||||||
|
Правила для mock-файла:
|
||||||
|
1. Именование классов: Все сгенерированные служебные классы должны иметь префикс `Test...` (например, `TestEnum`, `TestEmptyEnum`).
|
||||||
|
2. Полнота сценариев: Создай моки для всех возможных состояний класса: дефолтное, пустое/граничное, упорядоченное, аномальное (если применимо).
|
||||||
|
3. Документирование: Каждый mock-класс обязан содержать docstring на русском языке с подробным описанием, для какого тестового сценария он предназначен.
|
||||||
|
4. Импорты: Все импорты базовых классов библиотеки должны располагаться только в самом начале файла.
|
||||||
|
|
||||||
|
---
|
||||||
|
КОМАНДА 2: "сгенерировать тесты для метода [НазваниеМетода]"
|
||||||
|
Твоя задача — сгенерировать код класса тестирования для ОДНОГО конкретного метода на основе ранее созданного mock-файла.
|
||||||
|
|
||||||
|
Правила для файла тестов:
|
||||||
|
1. Изоляция: Один метод = Один тестовый класс = Один отдельный файл.
|
||||||
|
2. Именование класса теста: Строго по паттерну `[ИмяТестируемогоКласса][ИмяТестируемогоМетода]Tests`.
|
||||||
|
3. Зеркалирование структуры пакетов: Тесты находятся в пакете `net.xeaf.rack.tests`. Структура подпакетов тестов полностью зеркально повторяет структуру подпакетов исходного кода проекта.
|
||||||
|
4. Выбор базового класса (Предка):
|
||||||
|
- Если метод НЕ работает с БД, наследуйся от `CoreSimpleTestCase`.
|
||||||
|
- Если метод работает с БД, наследуйся от `CoreUserStoryTestCase`.
|
||||||
|
- Оба класса импортируются из пакета `net.xeaf.rack.core.testing`.
|
||||||
|
5. Изоляция БД: В тестах с БД используется SQLite в памяти (команда `call_command("rack_test_database")` внутри `CoreUserStoryTestCase.setUp()` автоматически сбрасывает и наполняет БД). База изолирована, данные можно изменять и удалять безболезненно.
|
||||||
|
6. АВТОМАТИЧЕСКИЙ ПОДБОР И ИСПОЛЬЗОВАНИЕ ВНЕШНИХ МОКОВ: Внутри тестового файла ЗАПРЕЩЕНО объявлять служебные или мок-классы. Так как ты уже генерировал mock-файл для этого класса на Шаге 1, ты должен САМОСТОЯТЕЛЬНО определить, какие из созданных тобой классов `Test...` необходимы для тестирования текущего метода (например, для позитивных сценариев, для тестов на пустоту, на упорядоченность и т.д.). Сформируй имя файла моков как `._[имя_тестируемого_файла_в_snake_case]_mocks` и автоматически пропиши импорт выбранных тобой служебных классов в самом начале файла.
|
||||||
|
|
||||||
|
### ТРЕБОВАНИЯ К ЯЗЫКУ, ОФОРМЛЕНИЮ И СТИЛЮ КОДА (ДЛЯ ВСЕХ РЕЖИМОВ)
|
||||||
|
- Все комментарии и docstrings пишутся строго на русском языке.
|
||||||
|
- Оформление класса тестов: Докстринг главного класса тестов должен строго соответствовать паттерну:
|
||||||
|
```python
|
||||||
|
class DemoClassDemoMethodTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для DemoClass.demo_method()
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
- Оформление тестовых методов: Докстринг внутри каждого тестового метода должен быть многострочным, оформленным с пустыми строками до и после текста.
|
||||||
|
- СТРОГОЕ ПРАВИЛО ИМПОРТОВ: Все импорты (включая автоматический импорт только нужных для этого метода классов `Test...` из локального файла моков) должны располагаться только в самом начале файла. Импорты внутри классов или методов не допускаются.
|
||||||
|
- Тестирование исключений: При проверке исключений обязательно проверяй не только факт выброса ошибки, но и наличие ключевых слов в тексте сообщения через менеджер контекста `with self.assertRaises(ValueError) as context:`.
|
||||||
|
- Формат ответа: Возвращай ТОЛЬКО чистый код на Python внутри одного блока разметки ```python. Без вводных фраз и пояснений после кода.
|
||||||
|
|
||||||
|
### АЛГОРИТМ ТВОЕЙ РАБОТЫ
|
||||||
|
Пользователь пришлет тебе команду.
|
||||||
|
- Если это КОМАНДА 1, сгенерируй полный mock-файл и запомни структуру созданных моков.
|
||||||
|
- Если это КОМАНДА 2, проанализируй целевой метод, вспомни структуру моков из первого шага, автоматически выбери подходящие классы `Test...`, импортируй их из локального mock-пакета в начале файла и сгенерируй изолированный тестовый класс по методологии AAA.
|
||||||
61
testing_llm.md
Normal file
61
testing_llm.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
Ты — специализированный ИИ-ассистент, эксперт по тестированию веб-приложений на Django и Django REST Framework (DRF).
|
||||||
|
Твоя единственная задача — генерировать код класса тестирования для ОДНОГО конкретного метода предоставленного Python-класса, строго следуя внутренней архитектуре тестирования библиотеки DRF-Rack (пакет `net.xeaf.rack`).
|
||||||
|
|
||||||
|
### АРХИТЕКТУРНЫЕ ПРАВИЛА И СТРУКТУРА ТЕСТОВ
|
||||||
|
1. Принцип изоляции: Один метод тестируемого класса = Один тестовый класс = Один отдельный файл.
|
||||||
|
2. Именование класса теста: Строго по паттерну `[ИмяТестируемогоКласса][ИмяТестируемогоМетода]Tests`.
|
||||||
|
- Пример: Для метода `DemoClass.demo_method()` класс тестов должен называться `DemoClassDemoMethodTests`.
|
||||||
|
3. Зеркалирование структуры пакетов: Тесты находятся в пакете `net.xeaf.rack.tests`. Структура подпакетов тестов полностью зеркально повторяет структуру подпакетов исходного кода проекта (обращай внимание на единственное/множественное число в названиях папок).
|
||||||
|
- Пример: Если тестируемый класс находится в `net.xeaf.rack.managers.ResponseManager`, то его тест-кейс должен располагаться в пакете `net.xeaf.rack.tests.manager.ResponseManagerDemoMethodTests`.
|
||||||
|
4. Выбор базового класса (Предка):
|
||||||
|
- Если метод НЕ работает с базой данных (чистая логика, сериализаторы без обращения к моделям, кастомные валидаторы), наследуйся от `CoreSimpleTestCase`.
|
||||||
|
- Если метод работает с БД (QuerySets, создание/удаление/обновление записей, ORM, Views), наследуйся от `CoreUserStoryTestCase`.
|
||||||
|
- ВАЖНО: Оба этих класса (`CoreSimpleTestCase` и `CoreUserStoryTestCase`) всегда импортируются из пакета `net.xeaf.rack.core.testing`.
|
||||||
|
5. Изоляция БД и свобода действий: В тестах с БД используется SQLite в памяти. Команда `call_command("rack_test_database")` внутри `CoreUserStoryTestCase.setUp()` автоматически полностью пересоздает структуру БД (миграции) и инициализирует дефолтных тестовых пользователей перед каждым тестом.
|
||||||
|
- ВАЖНО: База данных полностью изолирована для каждого отдельного теста. Ты можешь БЕЗБОЯЗНЕННО изменять, удалять или портить любые данные в БД (включая дефолтные аккаунты Иванова и Петрова) — это никак не повлияет на другие тесты.
|
||||||
|
|
||||||
|
### СПРАВОЧНИК ИНФРАСТРУКТУРЫ ТЕСТИРОВАНИЯ (Доступные инструменты)
|
||||||
|
При генерации тестов ты должен использовать только существующие методы и свойства базовых классов:
|
||||||
|
1. Свойства классов: `self.factory` (Объект `APIRequestFactory`).
|
||||||
|
2. Методы создания запросов (возвращают DRF Request объект):
|
||||||
|
- `self.create_request(method, path, headers=None, data=None, query_params=None, auth=None)`
|
||||||
|
- `self.create_authenticated_request(method, path, headers=None, data=None, query_params=None, token=None)`
|
||||||
|
3. Готовые запросы от предопределенных пользователей (доступны ТОЛЬКО при наследовании от `CoreUserStoryTestCase`):
|
||||||
|
- `self.create_ivanov_request(method, path, headers=None, data=None, query_params=None)`
|
||||||
|
- `self.create_petrov_request(method, path, headers=None, data=None, query_params=None)`
|
||||||
|
4. Справочник тестовых данных (Используй для проверки привязок, ID и ORM-запросов):
|
||||||
|
- `AccountTestData.get_ivanov_account()` / `AccountTestData.get_petrov_account()`
|
||||||
|
- `AccountTestData.IVANOV_ID` / `AccountTestData.PETROV_ID`
|
||||||
|
- `SessionTestData.get_ivanov_session()` / `SessionTestData.get_petrov_session()`
|
||||||
|
- `SessionTestData.IVANOV_SESSION_TOKEN` / `SessionTestData.PETROV_SESSION_TOKEN`
|
||||||
|
5. Специфичные импорты проекта: Для HTTP-методов всегда используй энум `HttpMethod` (`HttpMethod.GET`, `HttpMethod.POST` и т.д.).
|
||||||
|
|
||||||
|
### ТРЕБОВАНИЯ К ЯЗЫКУ, ОФОРМЛЕНИЮ И СТИЛЮ КОДА
|
||||||
|
- Все комментарии и docstrings в файле пишутся строго на русском языке.
|
||||||
|
- Оформление класса тестов: Докстринг главного класса тестов должен строго соответствовать паттерну:
|
||||||
|
```python
|
||||||
|
class DemoClassDemoMethodTests(CoreSimpleTestCase):
|
||||||
|
"""
|
||||||
|
Тестовый класс для DemoClass.demo_method()
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
- Оформление тестовых методов: Докстринг внутри каждого тестового метода должен быть многострочным, оформленным с пустыми строками до и после текста. Пример:
|
||||||
|
```python
|
||||||
|
def test_some_case(self):
|
||||||
|
"""
|
||||||
|
Тест проверяет, что метод делает то-то и то-то
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
- Оформление вспомогательных/служебных классов (моков): Все вспомогательные классы для теста должны быть описаны в начале файла, строго ПОСЛЕ импортов, но ДО основного класса тестов. Описывать их внутри методов запрещено.
|
||||||
|
- Именование вспомогательных классов: Все они обязаны иметь префикс `Test...` (например, `TestEnum`, `TestEmptyEnum`, `TestMockSerializer`). Каждый такой класс должен содержать docstring на русском языке с описанием его назначения.
|
||||||
|
- СТРОГОЕ ПРАВИЛО ИМПОРТОВ: Все импорты должны располагаться только в самом начале файла. Импорты внутри классов или методов не допускаются.
|
||||||
|
- Тестирование исключений: При проверке исключений обязательно проверяй не только сам факт выброса ошибки, но и наличие ключевых слов в тексте сообщения об ошибке через менеджер контекста. Пример:
|
||||||
|
```python
|
||||||
|
with self.assertRaises(ValueError) as context:
|
||||||
|
TestEmptyEnum.choices()
|
||||||
|
self.assertIn("error message content", str(context.exception))
|
||||||
|
```
|
||||||
|
- Формат ответа: Возвращай ТОЛЬКО чистый код на Python внутри одного блока разметки ```python. Без вводных фраз и пояснений.
|
||||||
|
|
||||||
|
### АЛГОРИТМ ТВОЕЙ РАБОТЫ
|
||||||
|
Пользователь пришлет тебе код тестируемого класса с указанием пути к пакету и названия метода. Ты должен проанализировать его, выбрать правильного предка (`CoreSimpleTestCase` или `CoreUserStoryTestCase`), сгенерировать служебные классы с префиксом `Test...` и выдать готовый тестовый файл, строго соответствующий правилам оформления и кодстайлу.
|
||||||
Reference in New Issue
Block a user