v5.1.0: тесты builder(20), extractor(15), scanner(20), replacer(10) — 65 тестов, 0 ошибок
Deploy drhider / validate (push) Waiting to run
Deploy drhider / validate (push) Waiting to run
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Тесты builder.py — создание ZIP и mapping.csv.
|
||||
|
||||
Запуск: python3 tests/test_builder.py
|
||||
"""
|
||||
|
||||
import io
|
||||
import zipfile
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from drhider.builder import build_zip, build_mapping_csv
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
def check(name, condition):
|
||||
global passed, failed
|
||||
if condition:
|
||||
passed += 1
|
||||
print(f" ✅ {name}")
|
||||
else:
|
||||
failed += 1
|
||||
print(f" ❌ {name}")
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Test build_zip
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
print("\n=== build_zip ===")
|
||||
|
||||
# 1. Базовый ZIP с одним файлом
|
||||
zip_data = build_zip([("test.md", b"content")])
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
names = zf.namelist()
|
||||
check("один файл в ZIP", len(names) == 1)
|
||||
check("имя test.md", "test.md" in names)
|
||||
check("контент верный", zf.read("test.md") == b"content")
|
||||
|
||||
# 2. ZIP с несколькими файлами
|
||||
zip_data = build_zip([
|
||||
("договор_obfuscated.md", "# Договор\nТекст".encode("utf-8")),
|
||||
("спецификация_obfuscated.md", "| Услуга | Цена |".encode("utf-8")),
|
||||
])
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
names = zf.namelist()
|
||||
check("два файла", len(names) == 2)
|
||||
check("mapping.csv нет", "mapping.csv" not in names)
|
||||
check("договор читается", "Договор" in zf.read("договор_obfuscated.md").decode("utf-8"))
|
||||
|
||||
# 3. ZIP с mapping.csv
|
||||
zip_data = build_zip(
|
||||
[("file.md", b"data")],
|
||||
mapping_csv="тип,оригинал,замена\nperson,Иванов,Иванов_0001\n"
|
||||
)
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
names = zf.namelist()
|
||||
check("mapping.csv есть", "mapping.csv" in names)
|
||||
csv_content = zf.read("mapping.csv").decode("utf-8")
|
||||
check("mapping с BOM", csv_content.startswith('\ufeff'))
|
||||
check("данные в mapping", "Иванов_0001" in csv_content)
|
||||
|
||||
# 4. ZIP с кириллицей в именах
|
||||
zip_data = build_zip([("договор_№123.md", "текст".encode("utf-8"))])
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
check("кириллическое имя читается", "договор_№123.md" in zf.namelist())
|
||||
|
||||
# 5. ZIP с бинарными данными
|
||||
binary = bytes(range(256))
|
||||
zip_data = build_zip([("binary.bin", binary)])
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
check("бинарный файл сохранён", zf.read("binary.bin") == binary)
|
||||
|
||||
# 6. Пустой mapping
|
||||
zip_data = build_zip([("f.md", b"x")], mapping_csv="")
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
check("пустой mapping не добавляется", "mapping.csv" not in zf.namelist())
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Test build_mapping_csv
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
print("\n=== build_mapping_csv ===")
|
||||
|
||||
# 1. Простой mapping
|
||||
mapping = {"Иванов И.И.": "Иванов_0001"}
|
||||
csv_str = build_mapping_csv(mapping)
|
||||
check("заголовок есть", csv_str.startswith("тип_данных,оригинал,замена"))
|
||||
check("данные есть", "Иванов_0001" in csv_str)
|
||||
|
||||
# 2. Пустой mapping
|
||||
csv_str = build_mapping_csv({})
|
||||
lines = csv_str.strip().split("\n")
|
||||
check("пустой — только заголовок", len(lines) == 1)
|
||||
|
||||
# 3. Сортировка
|
||||
mapping = {"Б": "Б_0001", "А": "А_0001"}
|
||||
csv_str = build_mapping_csv(mapping)
|
||||
check("сортировка А перед Б", csv_str.index("А_0001") < csv_str.index("Б_0001"))
|
||||
|
||||
# 4. Кавычки в значениях
|
||||
mapping = {'ООО "Ромашка"': "ООО_Технология_0001"}
|
||||
csv_str = build_mapping_csv(mapping)
|
||||
check("кавычки экранированы", 'ООО "Ромашка"' in csv_str or 'ООО ""Ромашка""' in csv_str)
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Test: интеграция build_zip + build_mapping_csv
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
print("\n=== build_zip + build_mapping_csv ===")
|
||||
|
||||
mapping = {"Иванов И.И.": "Иванов_0001", "ООО Ромашка": "ООО_Технология_0001"}
|
||||
csv = build_mapping_csv(mapping)
|
||||
zip_data = build_zip([("doc.md", "# Договор с Иванов_0001".encode("utf-8"))], mapping_csv=csv)
|
||||
|
||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||
check("два файла в ZIP", len(zf.namelist()) == 2)
|
||||
doc = zf.read("doc.md").decode("utf-8")
|
||||
check("doc с заменой", "Иванов_0001" in doc)
|
||||
csv_content = zf.read("mapping.csv").decode("utf-8")
|
||||
check("CSV с обеими заменами", "Иванов_0001" in csv_content and "ООО_Технология_0001" in csv_content)
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
print(f"\n{'='*50}")
|
||||
print(f"Результат: {passed} OK, {failed} FAIL из {passed + failed}")
|
||||
if failed > 0:
|
||||
print("❌ ТЕСТЫ ПРОВАЛЕНЫ")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("✅ ВСЕ ТЕСТЫ ПРОЙДЕНЫ")
|
||||
Reference in New Issue
Block a user