From 494dac6ef0efd031d493b5f9232132177f8cd299 Mon Sep 17 00:00:00 2001 From: Jose Tomas Robles Hahn Date: Wed, 10 Sep 2025 21:14:20 -0300 Subject: [PATCH] chore(tests): Refactor and improve constants tests Refactor several test files for enum and constant classes to improve maintainability, consistency, and clarity. The main changes involve shifting from direct imports and usage of module-level constants/enums to storing them as class variables set up in `setUpClass()`, and enhancing the tests to check type consistency and equality for enum members. Key improvements include: - Consistent use of `setUpClass` to initialize class variables for constants and enums. - Enhanced type and equality checks for enum members in test cases. - Refactoring tests to use class variables instead of direct imports or module references. The most important changes are: **Test structure and setup improvements:** - Refactored all test classes in `test_dte_constants.py`, `test_rcv_constants.py`, `test_rtc_constants.py`, and `test_rut_constants.py` to use `setUpClass()` and store constants/enums as class variables, promoting consistency and easier maintenance. **Enum and constant validation enhancements:** - Updated enum tests to include checks for member value types (e.g., ensuring all values are of type `int` or `str`) and to verify that enum members are equal to their values or names where appropriate. - Improved tests for enums with integer values (like `TipoDte` and `RcvTipoDocto`) to confirm that enum members are also instances of `int`, and that casting their values to `int` yields the member itself. - For enums with string values, added checks to ensure that member values match their names. **Test code simplification:** - Replaced repetitive direct constant access in test methods with class variables, simplifying test code and reducing import clutter. **Documentation and clarity:** - Added docstrings and comments to clarify test purposes, such as in `TipoDteCediblesTest` for `TIPO_DTE_CEDIBLES`. These changes collectively make the test suite more robust, readable, and maintainable. --- src/tests/test_dte_constants.py | 52 ++++---- src/tests/test_rcv_constants.py | 208 +++++++++++++++----------------- src/tests/test_rtc_constants.py | 23 +++- src/tests/test_rut_constants.py | 27 +++-- 4 files changed, 166 insertions(+), 144 deletions(-) diff --git a/src/tests/test_dte_constants.py b/src/tests/test_dte_constants.py index 3fdc00dd..fc509aeb 100644 --- a/src/tests/test_dte_constants.py +++ b/src/tests/test_dte_constants.py @@ -1,26 +1,34 @@ +from __future__ import annotations + import unittest +from typing import ClassVar -from cl_sii.dte import constants # noqa: F401 -from cl_sii.dte.constants import TipoDte +from cl_sii.dte import constants class TipoDteTest(unittest.TestCase): - def test_members(self) -> None: - self.assertSetEqual( - {x for x in TipoDte}, - { - TipoDte.FACTURA_ELECTRONICA, - TipoDte.FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA, - TipoDte.LIQUIDACION_FACTURA_ELECTRONICA, - TipoDte.FACTURA_COMPRA_ELECTRONICA, - TipoDte.GUIA_DESPACHO_ELECTRONICA, - TipoDte.NOTA_DEBITO_ELECTRONICA, - TipoDte.NOTA_CREDITO_ELECTRONICA, - }, - ) + TipoDte: ClassVar[type[constants.TipoDte]] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.TipoDte = constants.TipoDte + + def test_enum_member_value_types(self) -> None: + expected_type = int + for member in self.TipoDte: + with self.subTest(name=member.name): + self.assertIsInstance(member.value, expected_type) + + def test_enum_members_are_also_integers(self) -> None: + for member in self.TipoDte: + with self.subTest(name=member.name): + self.assertEqual(int(member.value), member) + self.assertIsInstance(member, int) def test_FACTURA_ELECTRONICA(self) -> None: - value = TipoDte.FACTURA_ELECTRONICA + value = self.TipoDte.FACTURA_ELECTRONICA self.assertEqual(value.name, 'FACTURA_ELECTRONICA') self.assertEqual(value.value, 33) @@ -38,7 +46,7 @@ def test_FACTURA_ELECTRONICA(self) -> None: self.assertEqual(result, expected) def test_FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA(self) -> None: - value = TipoDte.FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA + value = self.TipoDte.FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA self.assertEqual(value.name, 'FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA') self.assertEqual(value.value, 34) @@ -56,7 +64,7 @@ def test_FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA(self) -> None: self.assertTrue(result is expected) def test_LIQUIDACION_FACTURA_ELECTRONICA(self) -> None: - value = TipoDte.LIQUIDACION_FACTURA_ELECTRONICA + value = self.TipoDte.LIQUIDACION_FACTURA_ELECTRONICA self.assertEqual(value.name, 'LIQUIDACION_FACTURA_ELECTRONICA') self.assertEqual(value.value, 43) @@ -74,7 +82,7 @@ def test_LIQUIDACION_FACTURA_ELECTRONICA(self) -> None: self.assertEqual(result, expected) def test_FACTURA_COMPRA_ELECTRONICA(self) -> None: - value = TipoDte.FACTURA_COMPRA_ELECTRONICA + value = self.TipoDte.FACTURA_COMPRA_ELECTRONICA self.assertEqual(value.name, 'FACTURA_COMPRA_ELECTRONICA') self.assertEqual(value.value, 46) @@ -92,7 +100,7 @@ def test_FACTURA_COMPRA_ELECTRONICA(self) -> None: self.assertTrue(result is expected) def test_GUIA_DESPACHO_ELECTRONICA(self) -> None: - value = TipoDte.GUIA_DESPACHO_ELECTRONICA + value = self.TipoDte.GUIA_DESPACHO_ELECTRONICA self.assertEqual(value.name, 'GUIA_DESPACHO_ELECTRONICA') self.assertEqual(value.value, 52) @@ -110,7 +118,7 @@ def test_GUIA_DESPACHO_ELECTRONICA(self) -> None: self.assertTrue(result is expected) def test_NOTA_DEBITO_ELECTRONICA(self) -> None: - value = TipoDte.NOTA_DEBITO_ELECTRONICA + value = self.TipoDte.NOTA_DEBITO_ELECTRONICA self.assertEqual(value.name, 'NOTA_DEBITO_ELECTRONICA') self.assertEqual(value.value, 56) @@ -128,7 +136,7 @@ def test_NOTA_DEBITO_ELECTRONICA(self) -> None: self.assertTrue(result is expected) def test_NOTA_CREDITO_ELECTRONICA(self) -> None: - value = TipoDte.NOTA_CREDITO_ELECTRONICA + value = self.TipoDte.NOTA_CREDITO_ELECTRONICA self.assertEqual(value.name, 'NOTA_CREDITO_ELECTRONICA') self.assertEqual(value.value, 61) diff --git a/src/tests/test_rcv_constants.py b/src/tests/test_rcv_constants.py index ab5ede8d..2c3c2e32 100644 --- a/src/tests/test_rcv_constants.py +++ b/src/tests/test_rcv_constants.py @@ -1,24 +1,36 @@ +from __future__ import annotations + import unittest +from typing import ClassVar -from cl_sii.dte.constants import TipoDte # noqa: F401 -from cl_sii.rcv import constants # noqa: F401 -from cl_sii.rcv.constants import RcEstadoContable, RcTipoCompra, RcvKind, RcvTipoDocto, RvTipoVenta +from cl_sii.dte.constants import TipoDte +from cl_sii.rcv import constants class RcvKindTest(unittest.TestCase): - def test_members(self) -> None: - self.assertSetEqual( - {x for x in RcvKind}, - { - RcvKind.COMPRAS, - RcvKind.VENTAS, - }, - ) + RcvKind: ClassVar[type[constants.RcvKind]] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() - def test_values_type(self) -> None: - self.assertSetEqual({type(x.value) for x in RcvKind}, {str}) + cls.RcvKind = constants.RcvKind + + def test_enum_member_value_types(self) -> None: + expected_type = str + for member in self.RcvKind: + with self.subTest(name=member.name): + self.assertIsInstance(member.value, expected_type) + + def test_enum_members_equal_names_and_values(self) -> None: + for member in self.RcvKind: + with self.subTest(name=member.name): + self.assertEqual(member.value, member.name) def test_is_estado_contable_compatible(self) -> None: + RcvKind = self.RcvKind + RcEstadoContable = constants.RcEstadoContable + self.assertTrue(RcvKind.VENTAS.is_estado_contable_compatible(None)) self.assertTrue(RcvKind.COMPRAS.is_estado_contable_compatible(RcEstadoContable.REGISTRO)) self.assertTrue(RcvKind.COMPRAS.is_estado_contable_compatible(RcEstadoContable.NO_INCLUIR)) @@ -33,129 +45,103 @@ def test_is_estado_contable_compatible(self) -> None: class RcEstadoContableTest(unittest.TestCase): - def test_members(self) -> None: - self.assertSetEqual( - {x for x in RcEstadoContable}, - { - RcEstadoContable.REGISTRO, - RcEstadoContable.NO_INCLUIR, - RcEstadoContable.RECLAMADO, - RcEstadoContable.PENDIENTE, - }, - ) + RcEstadoContable: ClassVar[type[constants.RcEstadoContable]] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.RcEstadoContable = constants.RcEstadoContable - def test_values_type(self) -> None: - self.assertSetEqual({type(x.value) for x in RcEstadoContable}, {str}) + def test_enum_member_value_types(self) -> None: + expected_type = str + for member in self.RcEstadoContable: + with self.subTest(name=member.name): + self.assertIsInstance(member.value, expected_type) + + def test_enum_members_equal_names_and_values(self) -> None: + for member in self.RcEstadoContable: + with self.subTest(name=member.name): + self.assertEqual(member.value, member.name) class RcTipoCompraTest(unittest.TestCase): - def test_members(self) -> None: - self.assertSetEqual( - {x for x in RcTipoCompra}, - { - RcTipoCompra.DEL_GIRO, - RcTipoCompra.SUPERMERCADOS, - RcTipoCompra.BIENES_RAICES, - RcTipoCompra.ACTIVO_FIJO, - RcTipoCompra.IVA_USO_COMUN, - RcTipoCompra.IVA_NO_RECUPERABLE, - RcTipoCompra.NO_CORRESPONDE_INCLUIR, - }, - ) + RcTipoCompra: ClassVar[type[constants.RcTipoCompra]] - def test_values_type(self) -> None: - self.assertSetEqual({type(x.value) for x in RcTipoCompra}, {str}) + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.RcTipoCompra = constants.RcTipoCompra + + def test_enum_member_value_types(self) -> None: + expected_type = str + for member in self.RcTipoCompra: + with self.subTest(name=member.name): + self.assertIsInstance(member.value, expected_type) + + def test_enum_members_equal_names_and_values(self) -> None: + for member in self.RcTipoCompra: + with self.subTest(name=member.name): + self.assertEqual(member.value, member.name) class RcvTipoDoctoTest(unittest.TestCase): - def test_members(self) -> None: - self.assertSetEqual( - {x for x in RcvTipoDocto}, - { - RcvTipoDocto.FACTURA_INICIO, - RcvTipoDocto.FACTURA, - RcvTipoDocto.FACTURA_ELECTRONICA, - RcvTipoDocto.FACTURA_NO_AFECTA_O_EXENTA, - RcvTipoDocto.FACTURA_NO_AFECTA_O_EXENTA_ELECTRONICA, - RcvTipoDocto.FACTURA_COMPRA, - RcvTipoDocto.FACTURA_COMPRA_ELECTRONICA, - RcvTipoDocto.FACTURA_EXPORTACION, - RcvTipoDocto.FACTURA_EXPORTACION_ELECTRONICA, - # - RcvTipoDocto.NOTA_DEBITO, - RcvTipoDocto.NOTA_DEBITO_ELECTRONICA, - RcvTipoDocto.NOTA_CREDITO, - RcvTipoDocto.NOTA_CREDITO_ELECTRONICA, - RcvTipoDocto.NOTA_DEBITO_EXPORTACION, - RcvTipoDocto.NOTA_DEBITO_EXPORTACION_ELECTRONICA, - RcvTipoDocto.NOTA_CREDITO_EXPORTACION, - RcvTipoDocto.NOTA_CREDITO_EXPORTACION_ELECTRONICA, - # - RcvTipoDocto.LIQUIDACION_FACTURA, - RcvTipoDocto.LIQUIDACION_FACTURA_ELECTRONICA, - # - RcvTipoDocto.TOTAL_OP_DEL_MES_BOLETA_AFECTA, - RcvTipoDocto.TOTAL_OP_DEL_MES_BOLETA_EXENTA, - RcvTipoDocto.TOTAL_OP_DEL_MES_BOLETA_EXENTA_ELECTR, - RcvTipoDocto.TOTAL_OP_DEL_MES_BOLETA_ELECTR, - # - RcvTipoDocto.TIPO_47, - RcvTipoDocto.TIPO_48, - RcvTipoDocto.TIPO_102, - RcvTipoDocto.TIPO_103, - RcvTipoDocto.TIPO_105, - RcvTipoDocto.TIPO_108, - RcvTipoDocto.TIPO_109, - RcvTipoDocto.TIPO_901, - RcvTipoDocto.TIPO_902, - RcvTipoDocto.TIPO_903, - RcvTipoDocto.TIPO_904, - RcvTipoDocto.TIPO_905, - RcvTipoDocto.TIPO_906, - RcvTipoDocto.TIPO_907, - RcvTipoDocto.TIPO_909, - RcvTipoDocto.TIPO_910, - RcvTipoDocto.TIPO_911, - RcvTipoDocto.TIPO_914, - RcvTipoDocto.TIPO_919, - RcvTipoDocto.TIPO_920, - RcvTipoDocto.TIPO_922, - RcvTipoDocto.TIPO_924, - }, - ) + RcvTipoDocto: ClassVar[type[constants.RcvTipoDocto]] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.RcvTipoDocto = constants.RcvTipoDocto - def test_values_type(self) -> None: - self.assertSetEqual({type(x.value) for x in RcvTipoDocto}, {int}) + def test_enum_member_value_types(self) -> None: + expected_type = int + for member in self.RcvTipoDocto: + with self.subTest(name=member.name): + self.assertIsInstance(member.value, expected_type) + + def test_enum_members_are_also_integers(self) -> None: + for member in self.RcvTipoDocto: + with self.subTest(name=member.name): + self.assertEqual(int(member.value), member) + self.assertIsInstance(member, int) def test_of_some_member(self) -> None: - value = RcvTipoDocto.FACTURA_ELECTRONICA + value = self.RcvTipoDocto.FACTURA_ELECTRONICA self.assertEqual(value.name, 'FACTURA_ELECTRONICA') self.assertEqual(value.value, 33) def test_as_tipo_dte(self) -> None: self.assertEqual( - RcvTipoDocto.FACTURA_ELECTRONICA.as_tipo_dte(), + self.RcvTipoDocto.FACTURA_ELECTRONICA.as_tipo_dte(), TipoDte.FACTURA_ELECTRONICA, ) with self.assertRaises(ValueError) as cm: - RcvTipoDocto.FACTURA.as_tipo_dte() + self.RcvTipoDocto.FACTURA.as_tipo_dte() self.assertEqual( cm.exception.args, ("There is no equivalent 'TipoDte' for 'RcvTipoDocto.FACTURA'.",) ) class RvTipoVentaTest(unittest.TestCase): - def test_members(self) -> None: - self.assertSetEqual( - {x for x in RvTipoVenta}, - { - RvTipoVenta.DEL_GIRO, - RvTipoVenta.BIENES_RAICES, - RvTipoVenta.ACTIVO_FIJO, - }, - ) + RvTipoVenta: ClassVar[type[constants.RvTipoVenta]] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.RvTipoVenta = constants.RvTipoVenta + + def test_enum_member_value_types(self) -> None: + expected_type = str + for member in self.RvTipoVenta: + with self.subTest(name=member.name): + self.assertIsInstance(member.value, expected_type) - def test_values_type(self) -> None: - self.assertSetEqual({type(x.value) for x in RvTipoVenta}, {str}) + def test_enum_members_equal_names_and_values(self) -> None: + for member in self.RvTipoVenta: + with self.subTest(name=member.name): + self.assertEqual(member.value, member.name) diff --git a/src/tests/test_rtc_constants.py b/src/tests/test_rtc_constants.py index 056a74cb..1d773f8f 100644 --- a/src/tests/test_rtc_constants.py +++ b/src/tests/test_rtc_constants.py @@ -1,14 +1,29 @@ +from __future__ import annotations + import unittest +from typing import ClassVar -from cl_sii.rtc.constants import TIPO_DTE_CEDIBLES +from cl_sii.dte.constants import TipoDte +from cl_sii.rtc import constants class TipoDteCediblesTest(unittest.TestCase): - # For 'TIPO_DTE_CEDIBLES' + """ + Tests for `TIPO_DTE_CEDIBLES`. + """ + + TIPO_DTE_CEDIBLES: ClassVar[frozenset[TipoDte]] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.TIPO_DTE_CEDIBLES = constants.TIPO_DTE_CEDIBLES def test_all_are_factura(self) -> None: - for element in TIPO_DTE_CEDIBLES: - self.assertTrue(element.is_factura) + for element in self.TIPO_DTE_CEDIBLES: + with self.subTest(name=element.name): + self.assertTrue(element.is_factura) # TODO: implement test that check that the values correspond to those defined in # XML type 'SiiDte:DTEFacturasType' in official schema 'SiiTypes_v10.xsd'. diff --git a/src/tests/test_rut_constants.py b/src/tests/test_rut_constants.py index 12e90a79..84e62a7e 100644 --- a/src/tests/test_rut_constants.py +++ b/src/tests/test_rut_constants.py @@ -1,23 +1,36 @@ from __future__ import annotations import unittest +from typing import ClassVar from cl_sii.rut import constants class RutDigitsConstantsTestCase(unittest.TestCase): + RUT_DIGITS_MIN_VALUE: ClassVar[int] + RUT_DIGITS_MAX_VALUE: ClassVar[int] + PERSONA_JURIDICA_MIN_RUT_DIGITS: ClassVar[int] + + @classmethod + def setUpClass(cls) -> None: + super().setUpClass() + + cls.RUT_DIGITS_MIN_VALUE = constants.RUT_DIGITS_MIN_VALUE + cls.RUT_DIGITS_MAX_VALUE = constants.RUT_DIGITS_MAX_VALUE + cls.PERSONA_JURIDICA_MIN_RUT_DIGITS = constants.PERSONA_JURIDICA_MIN_RUT_DIGITS + def test_min_value(self) -> None: - min_rut_digits = constants.RUT_DIGITS_MIN_VALUE + min_rut_digits = self.RUT_DIGITS_MIN_VALUE - self.assertLessEqual(min_rut_digits, constants.RUT_DIGITS_MAX_VALUE) + self.assertLessEqual(min_rut_digits, self.RUT_DIGITS_MAX_VALUE) def test_max_value(self) -> None: - max_rut_digits = constants.RUT_DIGITS_MAX_VALUE + max_rut_digits = self.RUT_DIGITS_MAX_VALUE - self.assertGreaterEqual(max_rut_digits, constants.RUT_DIGITS_MIN_VALUE) + self.assertGreaterEqual(max_rut_digits, self.RUT_DIGITS_MIN_VALUE) def test_persona_juridica_min_value(self) -> None: - min_rut_digits = constants.PERSONA_JURIDICA_MIN_RUT_DIGITS + min_rut_digits = self.PERSONA_JURIDICA_MIN_RUT_DIGITS - self.assertGreaterEqual(min_rut_digits, constants.RUT_DIGITS_MIN_VALUE) - self.assertLessEqual(min_rut_digits, constants.RUT_DIGITS_MAX_VALUE) + self.assertGreaterEqual(min_rut_digits, self.RUT_DIGITS_MIN_VALUE) + self.assertLessEqual(min_rut_digits, self.RUT_DIGITS_MAX_VALUE)