Files
darth-veitcher-comfydv/tests
James VeitchandClaude Sonnet 5 1e9a8a3b6a fix: comfydv failed to load in real ComfyUI since PR #17 (critical)
Every internal `from comfydv._llm.X import Y`-style absolute
self-import broke the entire plugin the moment ComfyUI actually
loaded it — every node, not just the LLM ones, since the whole
src/comfydv/__init__.py chain aborted on the first such import.

ComfyUI's custom_nodes loader imports this plugin via a *relative*
chain (repo-root __init__.py does `from .src.comfydv import ...`),
nesting comfydv under whatever top-level name the folder gets —
never `comfydv` itself. An absolute `from comfydv...` self-import
only resolves if `src/` has separately been placed on sys.path,
which conftest.py does for every test — masking this completely.
No test ever exercised the real loading shape.

Confirmed via git bisection against the actual docker-compose dev
harness (built and ran real ComfyUI): this predates spec 008
entirely — checking out the commit right after PR #17 merged,
before llamacpp.py existed, reproduces the identical failure at
ollama.py's own absolute import. Fixed by converting every internal
self-import across src/comfydv/ to a relative import, which resolves
correctly under both loading shapes. Verified fixed by rebuilding
the harness and confirming all 21 nodes register via /object_info.

Added tests/test_comfyui_import_compat.py: a subprocess-based test
reproducing ComfyUI's exact nested-relative-import shape (not
conftest.py's sys.path-patched shape), plus a static AST guard
against any future absolute self-import creeping back in.

Also fixed, found via the same live-harness investigation:
- src/js/ollama.js matched on pre-rename node names
  (OllamaModelSelector/OllamaLoadModel/OllamaChatCompletion), so the
  "Refresh models" button and live structured-output socket preview
  were silently absent from every node in the real UI.
- The /dv/ollama/models route always spoke Ollama's wire protocol
  regardless of which backend was actually connected — pointing it
  at a llama.cpp host could never populate real models. Route now
  takes a `backend` param; getHostAndBackendFromNode() in ollama.js
  determines it from the connected client node's registered type;
  LlamaCppProvider gained a matching _fetch_models() name-only view
  (mirrors OllamaProvider's, same graceful-degradation contract).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0132ojafeazQ3ephcBejEWFj
2026-07-11 17:48:20 +01:00
..

Tests

This directory contains comprehensive pytest tests for the comfydv package.

Running Tests

# Run all tests
uv run pytest

# Run with verbose output
uv run pytest -v

# Run with coverage report
uv run pytest --cov=src/comfydv --cov-report=html

# Run specific test file
uv run pytest tests/test_format_string.py

# Run specific test class
uv run pytest tests/test_format_string.py::TestVariableExtraction

# Run specific test
uv run pytest tests/test_format_string.py::TestVariableExtraction::test_extract_simple_single_variable

# Run tests matching a pattern
uv run pytest -k "jinja2"

Coverage reports are available in htmlcov/index.html after running with --cov-report=html.

Test Coverage

Current: 75% (203 statements total, 51 missed)

  • format_string.py: 78% coverage
  • __init__.py: 100% coverage
  • circuit_breaker.py: 68% coverage
  • random_choice.py: 60% coverage
  • utils.py: 75% coverage

Test Structure

conftest.py

Contains pytest configuration, fixtures, and mocks for ComfyUI dependencies:

  • Mock ComfyUI modules (comfy, server, folder_paths, aiohttp)
  • Uses pytest_configure hook to install mocks before test collection
  • Provides format_string_class fixture using importlib to directly load module
  • Fixtures for test data and class instances
  • Pytest hooks for early mock installation

test_format_string.py

Comprehensive test suite for the FormatString node with 47 tests organized into classes:

  • TestVariableExtraction (12 tests): Variable extraction from templates
  • TestSimpleFormatting (4 tests): Python format string rendering
  • TestJinja2Formatting (5 tests): Jinja2 template rendering
  • TestDynamicOutputs (6 tests): Dynamic output configuration
  • TestOutputConsistency (3 tests): Outputs match RETURN_TYPES/RETURN_NAMES
  • TestInputTypes (4 tests): INPUT_TYPES method validation
  • TestIsChanged (5 tests): Cache invalidation logic
  • TestStatePersistence (2 tests): State saving/loading
  • TestEdgeCases (4 tests): Error handling and edge cases
  • TestTimeNowFunction (2 tests): time_now utility function

Mocking Strategy

The tests use importlib.util to directly load the format_string.py module, bypassing the package __init__.py which has ComfyUI dependencies. This allows testing without ComfyUI installation while maintaining the root __init__.py for ComfyUI extension discovery.

Writing Tests

Example test

def test_new_feature(self, format_string_class, sample_data):
    """Test that new feature works correctly."""
    result = format_string_class.some_method(sample_data["name"])
    assert result == expected_value

Available fixtures

  • format_string_class: Fresh FormatString class with reset state
  • sample_templates: Dictionary of sample template strings
  • sample_data: Dictionary of sample data for templates

Test naming convention

Use descriptive names: test_<what>_<condition>_<expected>

Troubleshooting

Debugging failed tests

# Run with verbose output
uv run pytest -vv --tb=long

# Run with pdb debugger
uv run pytest --pdb

Test isolation

Each test is independent. The format_string_class fixture provides a fresh instance with reset state.

Future Improvements

  • Add integration tests with actual ComfyUI installation
  • Add JavaScript tests for frontend functionality
  • Increase coverage for circuit_breaker and random_choice nodes
  • Add property-based testing with Hypothesis