Phase 2 of the modernization plan: lock the current behavior of the pure math so the Phase 3 refactor cannot silently change it. Unit characterization tests (Tier 0, 64 new): - test_characterization_latents.py: chunk_batch / merge_chunks padding, truncation, and identity contracts. - test_characterization_controlnet.py: expand_inputs / no_control / extract_residual_kwargs / chunk_control shape, dtype, and zero-fill behavior, including the [None]*target contract. - test_characterization_inputs.py: CoreMLInputs.chunks / coreml_kwargs for SD1.5, SDXL base (time_ids len 6), SDXL refiner (time_ids len 5), and LCM (timestep_cond). - test_characterization_sdxl_options.py: add_sdxl_model_options time_ids / text_embeds assembly via a SimpleNamespace fake ModelPatcher and inspect.getclosurevars on the returned model_function_wrapper. - test_characterization_out_name.py: CoreMLConverter out_name encoding for attn_impl suffix, batch/size, ControlNet, LoRA (sorted), SDXL. M2 [Tier 2] golden image anchor (1 new): - test_golden_image.py: posts the SD1.5+CoreML workflow to a local ComfyUI server (auto-skips if unreachable), asserts SHA256 of the generated PNG against tests/m2/goldens/sd15_seed42.sha256; falls back to PSNR >= 40 dB if the hash drifts. Test infra: - pyproject.toml [tool.pytest.ini_options]: unit / m2 / smoke markers, testpaths=tests; rootdir is now this package (was ComfyUI's pytest.ini). - tests/conftest.py: bootstraps sys.path for comfy imports, auto-marks tests by directory, and ignores the maintainer's WIP scaffolds (test_experiments / test_unet_conversion / standalone_test) so they don't break collection. All 85 collected tests pass; two consecutive runs produced identical results (run1: 3.55s, run2: 3.40s).
51 lines
1.5 KiB
Python
51 lines
1.5 KiB
Python
"""Pytest bootstrap for ComfyUI-CoreMLSuite tests.
|
|
|
|
- Adds the ComfyUI checkout to sys.path so production modules that
|
|
transitively import `comfy.*` resolve when pytest is invoked from this
|
|
package's root. Phase 3 will split pure logic into a comfy-free core and
|
|
this hack can go.
|
|
- Auto-applies tier markers based on the directory a test lives in, so
|
|
individual files don't have to repeat @pytest.mark.unit / .m2.
|
|
- Skips the maintainer's in-progress test scaffolds so they don't break
|
|
collection (they reference modules / venv layouts that aren't part of
|
|
Phase 2 scope).
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
COMFY_DIR = REPO_ROOT.parents[1]
|
|
|
|
for p in (str(COMFY_DIR), str(REPO_ROOT)):
|
|
if p not in sys.path:
|
|
sys.path.insert(0, p)
|
|
|
|
|
|
# Skip WIP test scaffolds left in the tree by the maintainer; they import
|
|
# modules (coreml_suite.experiments, convert_apple) that are not part of
|
|
# Phase 2 scope.
|
|
collect_ignore_glob = [
|
|
"unit/test_experiments.py",
|
|
"unit/test_unet_conversion.py",
|
|
"unit/standalone_test.py",
|
|
]
|
|
|
|
|
|
_TIER_BY_DIR = {
|
|
"tests/unit": "unit",
|
|
"tests/m2": "m2",
|
|
"tests/integration": "m2",
|
|
"tests/smoke": "smoke",
|
|
}
|
|
|
|
|
|
def pytest_collection_modifyitems(config, items):
|
|
for item in items:
|
|
path = str(item.fspath).replace("\\", "/")
|
|
for fragment, marker in _TIER_BY_DIR.items():
|
|
if f"/{fragment}/" in path:
|
|
item.add_marker(getattr(pytest.mark, marker))
|
|
break
|