- tests/test_compactor.py: 24 tests (estimate_tokens, extract_facts, build_summary, summarize_tool_output, compact_sections) - tests/test_key_data_extraction.py: 11 tests (extracción de tables, records, sections, modules, pages desde tool executions) - tests/test_fingerprint.py: 8 tests (deduplicación MD5, sort_keys, nested args) - tests/test_cost_calculation.py: 8 tests (pricing formula, custom pricing, rounding) - README.md: sección Tests con instrucciones de ejecución Todos offline, sin Docker/Redis/LLM. Ejecutar: python3 -m pytest tests/ -v Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
"""Tests para la logica de fingerprinting/deduplicacion de tool calls.
|
|
|
|
Replica la logica de BaseAgent.execute() (lineas con hashlib.md5) sin
|
|
necesidad de instanciar BaseAgent ni sus dependencias.
|
|
"""
|
|
|
|
import hashlib
|
|
import json
|
|
|
|
import pytest
|
|
|
|
|
|
def compute_fingerprint(tool_name: str, args: dict) -> str:
|
|
"""Replica exacta de la logica de fingerprint en BaseAgent.execute()."""
|
|
fp_raw = f"{tool_name}:{json.dumps(args, sort_keys=True)}"
|
|
return hashlib.md5(fp_raw.encode()).hexdigest()
|
|
|
|
|
|
class TestFingerprint:
|
|
def test_same_tool_same_args_same_fingerprint(self):
|
|
fp1 = compute_fingerprint("read_file", {"path": "/index.html"})
|
|
fp2 = compute_fingerprint("read_file", {"path": "/index.html"})
|
|
assert fp1 == fp2
|
|
|
|
def test_same_tool_different_args_different_fingerprint(self):
|
|
fp1 = compute_fingerprint("read_file", {"path": "/index.html"})
|
|
fp2 = compute_fingerprint("read_file", {"path": "/style.css"})
|
|
assert fp1 != fp2
|
|
|
|
def test_different_tool_same_args_different_fingerprint(self):
|
|
fp1 = compute_fingerprint("read_file", {"path": "/index.html"})
|
|
fp2 = compute_fingerprint("write_file", {"path": "/index.html"})
|
|
assert fp1 != fp2
|
|
|
|
def test_fingerprint_is_md5_hex_32_chars(self):
|
|
fp = compute_fingerprint("any_tool", {"key": "value"})
|
|
assert len(fp) == 32
|
|
assert all(c in "0123456789abcdef" for c in fp)
|
|
|
|
def test_arg_order_does_not_matter(self):
|
|
"""json.dumps con sort_keys=True normaliza el orden."""
|
|
fp1 = compute_fingerprint("tool", {"b": 2, "a": 1})
|
|
fp2 = compute_fingerprint("tool", {"a": 1, "b": 2})
|
|
assert fp1 == fp2
|
|
|
|
def test_empty_args(self):
|
|
fp = compute_fingerprint("tool", {})
|
|
assert len(fp) == 32
|
|
# Debe ser determinista
|
|
assert fp == compute_fingerprint("tool", {})
|
|
|
|
def test_nested_args(self):
|
|
args = {"filter": {"table": "pages", "status": "active"}, "limit": 10}
|
|
fp1 = compute_fingerprint("search", args)
|
|
fp2 = compute_fingerprint("search", args)
|
|
assert fp1 == fp2
|
|
|
|
def test_different_nested_values(self):
|
|
fp1 = compute_fingerprint("search", {"filter": {"status": "active"}})
|
|
fp2 = compute_fingerprint("search", {"filter": {"status": "draft"}})
|
|
assert fp1 != fp2
|