""" Pruebas de la cartera de ejemplo: quien abre la aplicación por primera vez puede curiosear con datos inventados sin que su cartera se toque ni se mezcle. python3 -m unittest discover -s pruebas -v """ from __future__ import annotations import datetime as dt import sys import tempfile import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from cartera import servidor # noqa: E402 from cartera.operaciones import Cartera, ErrorOperacion # noqa: E402 class TestEjemplo(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.addCleanup(self.tmp.cleanup) self.carpeta = Path(self.tmp.name) / "datos" self.real = Cartera(self.carpeta) self.addCleanup(self.real.cerrar) self.real.guardar_activo({"nombre": "Mi fondo", "tipo": "Fondo"}) self.app = servidor.App(self.real) self.addCleanup(lambda: self.app.ejemplo(False)) def nombres(self): return [a["nombre"] for a in self.app.estado()["activos"]] def test_una_cartera_vacia_ofrece_el_ejemplo(self): e = self.app.estado() self.assertEqual((e["ejemplo"], e["hay_ejemplo"]), (False, True)) def test_entrar_ensena_la_de_mentira_y_salir_devuelve_la_tuya_intacta(self): antes = sorted(f.name for f in self.carpeta.iterdir()) self.assertEqual(self.app.ejemplo(True), {"ejemplo": True}) e = self.app.estado() self.assertTrue(e["ejemplo"]) self.assertNotIn("Mi fondo", self.nombres()) self.assertGreater(e["resumen"]["global"]["valor"], 0) temporal = self.app.cartera.carpeta self.assertNotEqual(temporal, self.carpeta) self.assertEqual(self.app.ejemplo(False), {"ejemplo": False}) self.assertEqual(self.nombres(), ["Mi fondo"]) self.assertIs(self.app.cartera, self.real) self.assertFalse(temporal.exists()) # lo del ejemplo se tira self.assertEqual(sorted(f.name for f in self.carpeta.iterdir()), antes) def test_lo_que_se_hace_en_el_ejemplo_no_llega_a_la_cartera_de_verdad(self): self.app.ejemplo(True) self.app.cartera.guardar_activo({"nombre": "Prueba dentro del ejemplo", "tipo": "Accion"}) self.assertIn("Prueba dentro del ejemplo", self.nombres()) self.app.ejemplo(False) self.assertEqual(self.nombres(), ["Mi fondo"]) self.assertNotIn("Prueba dentro del ejemplo", (self.carpeta / "activos.jsonl").read_text(encoding="utf-8")) def test_los_precios_del_ejemplo_estan_al_dia_y_no_se_descargan(self): self.app.ejemplo(True) hoy = dt.date.today().isoformat() # Los de mercado, de hoy; los que Caudal estima (inmuebles, la Letra) llevan su propia fecha precios = sorted(self.app.cartera.datos.vivos("precios"), key=lambda p: p["fecha"]) fechas = {p["activo"]: p["fecha"] for p in precios if p.get("fuente") == "ejemplo"} self.assertEqual(set(fechas.values()), {hoy}) self.assertEqual({p["fuente"] for p in precios} - {"ejemplo"}, {"IPV", "MAPA", "devengo", "compra"}) self.assertFalse([a for a in self.app.estado()["resumen"]["avisos"] if a["tipo"] == "precio"]) with self.assertRaises(ErrorOperacion): self.app.actualizar_precios() def test_el_ejemplo_solo_tiene_inversiones_corrientes_y_parece_al_dia(self): self.app.ejemplo(True) e = self.app.estado() hoy = dt.date.today() self.assertEqual(sorted({a["tipo"] for a in e["activos"]}), ["Accion", "Cripto", "Cuenta", "Deuda", "ETF", "Fondo", "Inmueble", "RentaFija"]) # Lo que se estima solo sale ya calculado, con las fechas desplazadas filas = {f["nombre"]: f for f in e["resumen"]["abiertos"]} self.assertEqual((filas["Piso alquilado"]["fuente_precio"], filas["Finca de cereal"]["fuente_precio"], filas["Letra del Tesoro a 12 meses"]["fuente_precio"]), ("IPV", "MAPA", "devengo")) self.assertGreater(e["resumen"]["global"]["deuda"], 0) letra = next(a for a in e["activos"] if a["tipo"] == "RentaFija") self.assertGreater(letra["renta_fija"]["vencimiento"], hoy.isoformat()) self.assertEqual(e["activos"][0]["nombre"], "Bitcoin") hoy = dt.date.today() ultima = max(dt.date.fromisoformat(m["fecha"]) for m in e["movimientos"]) self.assertLess((hoy - ultima).days, 45) # la última operación es de hace poco, se abra cuando se abra self.assertFalse(any(dt.date.fromisoformat(m["fecha"]) > hoy for m in e["movimientos"])) self.assertGreater(e["resumen"]["global"]["valor"], 10000) self.assertGreater(e["resumen"]["global"]["liquidez"], 0) self.assertGreater(len(e["resumen"]["evolucion"]), 6) fiscal = self.app.fiscal(str(hoy.year - 1)) self.assertTrue(fiscal["ejercicios"]) def test_entrar_dos_veces_o_salir_sin_haber_entrado_no_rompe_nada(self): self.assertEqual(self.app.ejemplo(False), {"ejemplo": False}) self.app.ejemplo(True) primera = self.app.cartera self.app.ejemplo(True) self.assertIs(self.app.cartera, primera) self.app.ejemplo(False) self.assertIs(self.app.cartera, self.real) if __name__ == "__main__": unittest.main()