|
| 1 | +""" |
| 2 | +Pruebas para el módulo `formato_dbf` del paquete `pyafipws`. |
| 3 | +
|
| 4 | +Este módulo contiene pruebas para las funciones `definir_campos`, `dar_nombre_campo`, `leer` y `escribir` en el módulo `formato_dbf`. |
| 5 | +Las pruebas utilizan datos simulados y fixtures para verificar el comportamiento esperado de estas funciones. |
| 6 | +
|
| 7 | +La función `test_definir_campos` prueba la función `definir_campos`, que define los nombres de los campos y los formatos de los campos para un archivo DBF. |
| 8 | +
|
| 9 | +La función `test_dar_nombre_campo` prueba la función `dar_nombre_campo`, que genera un nombre de campo abreviado a partir de un nombre de campo largo. |
| 10 | +
|
| 11 | +La función `test_leer` prueba la función `leer`, que lee datos de uno o más archivos DBF y devuelve un diccionario que contiene los datos. |
| 12 | +
|
| 13 | +La función `test_escribir` prueba la función `escribir`, que escribe datos en un archivo DBF. |
| 14 | +
|
| 15 | +La función `test_ayuda` prueba la función `ayuda`, que imprime un mensaje de ayuda describiendo el formato del archivo DBF. |
| 16 | +""" |
| 17 | +import os |
| 18 | +import pytest |
| 19 | +from pyafipws.formatos import formato_dbf |
| 20 | +from unittest.mock import Mock |
| 21 | + |
| 22 | +# Datos de prueba y fixtures |
| 23 | +TEST_DATA_DIR = "tests/data" |
| 24 | +TEST_DBF_FILES = { |
| 25 | + "encabezado": os.path.join(TEST_DATA_DIR, "encabeza.dbf"), |
| 26 | + "detalle": os.path.join(TEST_DATA_DIR, "detalle.dbf"), |
| 27 | + # Agregar más archivos DBF de prueba según sea necesario |
| 28 | +} |
| 29 | + |
| 30 | +# Prueba de definir_campos |
| 31 | +@pytest.mark.dontusefix |
| 32 | +def test_definir_campos(): |
| 33 | + test_formato = [ |
| 34 | + ("campo1", 10, formato_dbf.N), |
| 35 | + ("campo2", 20, formato_dbf.A) |
| 36 | + ] |
| 37 | + claves, campos = formato_dbf.definir_campos(test_formato) |
| 38 | + |
| 39 | + # Asegurar la salida esperada |
| 40 | + assert claves == ["campo1", "campo2"] |
| 41 | + assert campos[0] == "campo1 N(10,0)" |
| 42 | + assert campos[1] == "campo2 C(20)" |
| 43 | + |
| 44 | +# Prueba de definir_campos con formato vacío |
| 45 | +@pytest.mark.dontusefix |
| 46 | +def test_definir_campos_empty(): |
| 47 | + claves, campos = formato_dbf.definir_campos([]) |
| 48 | + assert claves == [] |
| 49 | + assert campos == [] |
| 50 | + |
| 51 | +# Prueba de definir_campos con nombres de campos largos |
| 52 | +@pytest.mark.dontusefix |
| 53 | +def test_definir_campos_long_field(): |
| 54 | + test_formato = [ |
| 55 | + ("campo1", 300, formato_dbf.N), # Longitud del campo > 250 |
| 56 | + ("campo2", 20, formato_dbf.A) |
| 57 | + ] |
| 58 | + claves, campos = formato_dbf.definir_campos(test_formato) |
| 59 | + assert campos[0] == "campo1 M" # Campo de tipo Memo |
| 60 | + |
| 61 | +# Prueba de definir_campos con campo decimal |
| 62 | +@pytest.mark.dontusefix |
| 63 | +def test_definir_campos_decimal_field(): |
| 64 | + test_formato = [ |
| 65 | + ("campo1", (10, 2), formato_dbf.N), # Campo numérico con 2 decimales |
| 66 | + ("campo2", 20, formato_dbf.A) |
| 67 | + ] |
| 68 | + claves, campos = formato_dbf.definir_campos(test_formato) |
| 69 | + assert campos[0] == "campo1 N(10,0)" # Campo numérico con 2 decimales |
| 70 | + |
| 71 | +# Prueba de definir_campos con campo de caracteres |
| 72 | +@pytest.mark.dontusefix |
| 73 | +def test_definir_campos_character_field(): |
| 74 | + test_formato = [ |
| 75 | + ("campo1", 10, formato_dbf.A), # Campo de caracteres |
| 76 | + ("campo2", 20, formato_dbf.A) |
| 77 | + ] |
| 78 | + claves, campos = formato_dbf.definir_campos(test_formato) |
| 79 | + assert campos[0] == "campo1 C(10)" # Campo de caracteres |
| 80 | + |
| 81 | +# Prueba de definir_campos con campo numérico |
| 82 | +@pytest.mark.dontusefix |
| 83 | +def test_definir_campos_numeric_field(): |
| 84 | + test_formato = [ |
| 85 | + ("campo1", 10, formato_dbf.N), # Campo numérico |
| 86 | + ("campo2", 20, formato_dbf.A) |
| 87 | + ] |
| 88 | + claves, campos = formato_dbf.definir_campos(test_formato) |
| 89 | + assert campos[0] == "campo1 N(10,0)" # Campo numérico |
| 90 | + |
| 91 | +# Prueba de dar_nombre_campo |
| 92 | +@pytest.mark.dontusefix |
| 93 | +@pytest.mark.parametrize("clave, expected", [ |
| 94 | + ("campo_largo", "campolargo"), |
| 95 | + ("Dato_adicional1", "datoadic01"), |
| 96 | + ("campo_corto", "campocorto"), |
| 97 | +]) |
| 98 | +def test_dar_nombre_campo(clave, expected): |
| 99 | + assert formato_dbf.dar_nombre_campo(clave) == expected |
| 100 | + |
| 101 | +@pytest.mark.dontusefix |
| 102 | +def test_leer_empty_dbf_files(monkeypatch): |
| 103 | + # Simular la clase dbf.Table para devolver un objeto mock vacío |
| 104 | + mock_table = MockTable() |
| 105 | + monkeypatch.setattr("pyafipws.formatos.formato_dbf.dbf.Table", lambda *args, **kwargs: mock_table) |
| 106 | + |
| 107 | + # Llamar a leer y asegurar la salida |
| 108 | + output = formato_dbf.leer(TEST_DBF_FILES, TEST_DATA_DIR) |
| 109 | + |
| 110 | + # Si los archivos DBF están vacíos, la salida debe ser un diccionario vacío |
| 111 | + assert output == {} |
| 112 | + |
| 113 | +@pytest.mark.dontusefix |
| 114 | +def test_leer_non_empty_dbf_files(monkeypatch): |
| 115 | + # Simular la clase dbf.Table para devolver un objeto mock con datos |
| 116 | + mock_table = MockTable() |
| 117 | + mock_table.records = [MockRecord({"campo1": 123, "campo2": "test_value"})] |
| 118 | + monkeypatch.setattr("pyafipws.formatos.formato_dbf.dbf.Table", lambda *args, **kwargs: mock_table) |
| 119 | + |
| 120 | + # Llamar a leer y asegurar la salida |
| 121 | + output = formato_dbf.leer(TEST_DBF_FILES, TEST_DATA_DIR) |
| 122 | + |
| 123 | + # Si los archivos DBF no están vacíos, asegurar que la salida no está vacía |
| 124 | + assert len(output) > 0 |
| 125 | + first_key = list(output.keys())[0] |
| 126 | + assert "detalles" in output[first_key] |
| 127 | + |
| 128 | +# Prueba de leer con múltiples archivos DBF |
| 129 | +@pytest.mark.dontusefix |
| 130 | +def test_leer_multiple_dbf_files(monkeypatch): |
| 131 | + # Simular la clase dbf.Table para devolver un objeto mock con datos |
| 132 | + mock_table = MockTable() |
| 133 | + mock_table.records = [ |
| 134 | + MockRecord({"campo1": 123, "campo2": "test_value"}), |
| 135 | + MockRecord({"campo1": 456, "campo2": "another_value"}) |
| 136 | + ] |
| 137 | + monkeypatch.setattr("pyafipws.formatos.formato_dbf.dbf.Table", lambda *args, **kwargs: mock_table) |
| 138 | + |
| 139 | + # Llamar a leer y asegurar la salida |
| 140 | + output = formato_dbf.leer(TEST_DBF_FILES, TEST_DATA_DIR) |
| 141 | + |
| 142 | + # Asegurar que la salida es un diccionario con múltiples claves |
| 143 | + assert len(output) == 2 |
| 144 | + assert "detalles" in output["encabezado"] |
| 145 | + assert "detalles" in output["detalle"] |
| 146 | + |
| 147 | +@pytest.mark.dontusefix |
| 148 | +def test_escribir(tmp_path, monkeypatch): |
| 149 | + # Crear un directorio temporal para pruebas |
| 150 | + test_dir = tmp_path / "test_dbf" |
| 151 | + test_dir.mkdir() |
| 152 | + |
| 153 | + # Simular la clase dbf.Table para rastrear los datos escritos |
| 154 | + written_data = [] |
| 155 | + mock_table = MockTable(written_data) |
| 156 | + monkeypatch.setattr("pyafipws.formatos.formato_dbf.dbf.Table", lambda *args, **kwargs: mock_table) |
| 157 | + |
| 158 | + # Definir datos de prueba y llamar a escribir |
| 159 | + test_data = [{ |
| 160 | + "id": 1, |
| 161 | + "detalles": [{"campo1": 123, "campo2": "test_value"}], |
| 162 | + "ivas": [], |
| 163 | + "tributos": [], |
| 164 | + "permisos": [], |
| 165 | + "cbtes_asoc": [], |
| 166 | + "datos": [] |
| 167 | + }] |
| 168 | + formato_dbf.escribir(test_data, {"encabezado": "encabeza.dbf"}, str(test_dir)) |
| 169 | + |
| 170 | + # Asegurar que los datos fueron escritos en el archivo DBF |
| 171 | + assert len(written_data) == 2 |
| 172 | + assert written_data[0] == {'tiporeg': 0, 'webservice': b'', 'fechacbte': b'', 'tipocbte': 0, 'puntovta': 0, 'cbtenro': 0, 'tipoexpo': 0, 'permisoexi': b'', 'paisdstcmp': 0, 'nombreclie': b'', 'tipodoc': 0, 'nrodoc': 0, 'domicilioc': b'', 'idimpositi': b'', 'imptotal': 0, 'imptotconc': 0, 'impneto': 0, 'imptoliq': 0, 'imptoliqnr': 0, 'impopex': 0, 'imptoperc': 0, 'impiibb': 0, 'imptopercm': 0, 'impinterno': 0, 'imptrib': 0, 'monedaid': b'', 'monedactz': 0, 'obscomerci': b'', 'obsgeneral': b'', 'formapago': b'', 'incoterms': b'', 'incotermsd': b'', 'idiomacbte': b'', 'zona': b'', 'fechavencp': b'', 'prestaserv': 0, 'fechaservd': b'', 'fechaservh': b'', 'cae': b'', 'fechavto': b'', 'resultado': b'', 'reproceso': b'', 'motivosobs': b'', 'id': 1, 'telefonocl': b'', 'localidadc': b'', 'provinciac': b'', 'formatoid': 0, 'email': b'', 'pdf': b'', 'errcode': b'', 'errmsg': b'', 'datoadic01': b'', 'datoadic02': b'', 'datoadic03': b'', 'datoadic04': b'', 'descuento': 0, 'cbtdesde': 0, 'cbthasta': 0, 'concepto': 0, 'nousar': 0, 'impiva': 0, 'emisiontip': b'', 'impsubtota': 0, 'cativa': 0, 'tipocodaut': b''} |
| 173 | + assert written_data[1] == {'id': 1, 'tiporeg': 0, 'codigo': b'', 'qty': 0, 'umed': 0, 'precio': 0, 'importe': 0, 'ivaid': 0, 'ds': b'', 'ncm': b'', 'sec': b'', 'bonif': 0, 'impiva': 0, 'despacho': b'', 'umtx': 0, 'codmtx': 0, 'datoa': b'', 'datob': b'', 'datoc': b'', 'datod': b'', 'datoe': b''} |
| 174 | + |
| 175 | +# Prueba de ayuda (se puede capturar la salida y asegurar el contenido esperado) |
| 176 | +@pytest.mark.dontusefix |
| 177 | +def test_ayuda(capsys): |
| 178 | + formato_dbf.ayuda() |
| 179 | + captured = capsys.readouterr() |
| 180 | + assert "Formato DBF:" in captured.out |
| 181 | + assert "Encabezado" in captured.out |
| 182 | + assert "Detalle Item" in captured.out |
| 183 | + |
| 184 | +class MockRecord: |
| 185 | + def __init__(self, data): |
| 186 | + self.data = data |
| 187 | + |
| 188 | + def scatter_fields(self): |
| 189 | + return self.data |
| 190 | + |
| 191 | +class MockTable: |
| 192 | + def __init__(self, records=None): |
| 193 | + self.records = records or [] |
| 194 | + self.current_index = 0 |
| 195 | + |
| 196 | + def __iter__(self): |
| 197 | + return self |
| 198 | + |
| 199 | + def __next__(self): |
| 200 | + if self.current_index >= len(self.records): |
| 201 | + raise StopIteration |
| 202 | + record = self.records[self.current_index] |
| 203 | + self.current_index += 1 |
| 204 | + return record |
| 205 | + |
| 206 | + def append(self, data): |
| 207 | + record = MockRecord(data) |
| 208 | + self.records.append(record) |
| 209 | + |
| 210 | + def close(self): |
| 211 | + pass |
0 commit comments