Installation testing infrastructure for ComfyUI custom nodes
Project description
comfy-test
Installation testing infrastructure for ComfyUI custom nodes.
Test your nodes install and work correctly across Linux, Windows, and Windows Portable - with just config files, no pytest code needed.
Quick Start
Add these files to your custom node repository:
1. comfy-test.toml
[test]
name = "ComfyUI-MyNode"
[test.verification]
expected_nodes = ["MyNode1", "MyNode2"]
[test.workflow]
file = "tests/workflows/smoke_test.json"
timeout = 120
2. .github/workflows/test-install.yml
name: Test Installation
on: [push, pull_request]
jobs:
test:
uses: PozzettiAndrea/comfy-test/.github/workflows/test-matrix.yml@main
3. tests/workflows/smoke_test.json
A minimal ComfyUI workflow that uses your nodes. Export from ComfyUI.
Done! Push to GitHub and your tests will run automatically on all platforms.
What It Tests
- Setup - Clones ComfyUI, creates environment, installs dependencies
- Install - Copies your node, runs
install.py, installsrequirements.txt - Verify - Starts ComfyUI, checks your nodes appear in
/object_info - Validate - Runs 4-level workflow validation (see below)
- Execute - Runs your test workflow, verifies it completes without errors
Workflow Validation (4 Levels)
When a workflow file is configured, comfy-test runs comprehensive validation before execution:
| Level | Name | What It Checks |
|---|---|---|
| 1 | Schema | Widget values match allowed enums, types, and ranges |
| 2 | Graph | Connections are valid, all referenced nodes exist |
| 3 | Introspection | Node definitions are well-formed (INPUT_TYPES, RETURN_TYPES, FUNCTION) |
| 4 | Partial Execution | Runs non-CUDA nodes to verify they work |
Level 1: Schema Validation
Validates widget values in your workflow against node schemas from /object_info:
- Enum values - Checks dropdown selections are in the allowed list
- INT/FLOAT ranges - Validates numbers are within min/max bounds
- Type checking - Ensures STRING, BOOLEAN, INT, FLOAT values have correct types
[schema] Node 5 (LoadTrellis2Models): 'attn_backend': 'auto' not in allowed values ['flash_attn', 'xformers', 'sdpa', 'sageattn']
Level 2: Graph Validation
Validates the workflow graph structure:
- Node existence - All linked nodes actually exist
- Connection types - Output types match input types (IMAGE -> IMAGE)
- Slot validity - Input/output slot indices are valid
[graph] Node 12 (SaveImage): Type mismatch: KSampler outputs LATENT, but SaveImage expects IMAGE
Level 3: Node Introspection
Validates node definitions from the ComfyUI API:
- INPUT_TYPES - Returns valid dict with required/optional structure
- RETURN_TYPES - Is a list matching RETURN_NAMES length
- FUNCTION - Method name is defined
[introspection] Node 3 (BrokenNode): Node has no FUNCTION defined
Level 4: Partial Execution
Executes the "prefix" of your workflow - nodes that don't require CUDA:
- Identifies nodes that don't depend on CUDA packages
- Converts workflow to ComfyUI prompt format
- Submits partial workflow to the API
- Reports which nodes executed successfully
This catches runtime errors in non-GPU code paths (file loading, preprocessing, etc.) even on CPU-only CI.
[Step 3c/4] Partial execution (3 non-CUDA nodes)...
Executed 3 nodes successfully
Detecting CUDA Nodes
To mark nodes as requiring CUDA (so they're excluded from partial execution), list them in your comfy-test.toml:
[test.validation]
cuda_node_types = ["KSampler", "VAEDecode", "MyGPUNode"]
Or use comfy-env.toml to specify CUDA packages - any node importing those packages will be detected automatically.
Configuration Reference
[test]
name = "ComfyUI-MyNode" # Test suite name
comfyui_version = "latest" # ComfyUI version (tag, commit, or "latest")
python_version = "3.10" # Python version
timeout = 300 # Setup timeout in seconds
[test.platforms]
linux = true # Test on Linux
windows = true # Test on Windows
windows_portable = true # Test on Windows Portable
[test.verification]
expected_nodes = [ # Nodes that must exist after install
"MyNode1",
"MyNode2",
]
[test.workflow]
file = "tests/workflows/smoke.json" # Workflow to run
timeout = 120 # Workflow timeout
[test.windows_portable]
comfyui_portable_version = "latest" # Portable version to download
CUDA Packages on CPU-only CI
comfy-test runs on CPU-only GitHub Actions runners. For nodes that use CUDA packages (nvdiffrast, flash-attn, etc.):
- Installation works - comfy-test sets
COMFY_ENV_CUDA_VERSION=12.8so comfy-env can resolve wheel URLs even without a GPU - Import may fail - CUDA packages typically fail to import without a GPU
Best practice for CUDA nodes:
- Use lazy imports in production (better UX, graceful errors)
- Consider strict imports mode for testing to catch missing deps
# In your node's __init__.py
import os
if os.environ.get('COMFY_TEST_STRICT_IMPORTS'):
# Test mode: import everything now to catch missing deps
import nvdiffrast # Will fail on CPU, but that's expected
else:
# Production: lazy import when needed
nvdiffrast = None
For full CUDA testing, use a self-hosted runner with a GPU.
CLI
# Install
pip install comfy-test
# Show config
comfy-test info
# Run tests locally
comfy-test run --platform linux
# Dry run (show what would happen)
comfy-test run --dry-run
# Generate GitHub workflow
comfy-test init-ci
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file comfy_test-0.0.71.tar.gz.
File metadata
- Download URL: comfy_test-0.0.71.tar.gz
- Upload date:
- Size: 98.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9321ff15d880fd210d34bccb648a261eb1571d7b82e5656713a41e30b7536c2
|
|
| MD5 |
c8824d9276b116726c15747df3508753
|
|
| BLAKE2b-256 |
cbb43c27376ad7cc1666c34ba96b01f8138c854d81855c7a679225180c1d967d
|
Provenance
The following attestation bundles were made for comfy_test-0.0.71.tar.gz:
Publisher:
publish.yml on PozzettiAndrea/comfy-test
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
comfy_test-0.0.71.tar.gz -
Subject digest:
a9321ff15d880fd210d34bccb648a261eb1571d7b82e5656713a41e30b7536c2 - Sigstore transparency entry: 864106550
- Sigstore integration time:
-
Permalink:
PozzettiAndrea/comfy-test@d3fea5f8573a475ee64d4a08574ed44125bd7cab -
Branch / Tag:
refs/heads/main - Owner: https://github.com/PozzettiAndrea
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d3fea5f8573a475ee64d4a08574ed44125bd7cab -
Trigger Event:
push
-
Statement type:
File details
Details for the file comfy_test-0.0.71-py3-none-any.whl.
File metadata
- Download URL: comfy_test-0.0.71-py3-none-any.whl
- Upload date:
- Size: 117.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38d32b897f1ea8c5b329acdad61ca2db1171cecea0c8506b627552ddebc113b9
|
|
| MD5 |
e4549773eef92e5d7b1461c0f7b014f7
|
|
| BLAKE2b-256 |
1848a60a9dcf1bfdebb7334030301e9eb85cc6d8eee46a45dcc83c7434139ef7
|
Provenance
The following attestation bundles were made for comfy_test-0.0.71-py3-none-any.whl:
Publisher:
publish.yml on PozzettiAndrea/comfy-test
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
comfy_test-0.0.71-py3-none-any.whl -
Subject digest:
38d32b897f1ea8c5b329acdad61ca2db1171cecea0c8506b627552ddebc113b9 - Sigstore transparency entry: 864106553
- Sigstore integration time:
-
Permalink:
PozzettiAndrea/comfy-test@d3fea5f8573a475ee64d4a08574ed44125bd7cab -
Branch / Tag:
refs/heads/main - Owner: https://github.com/PozzettiAndrea
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d3fea5f8573a475ee64d4a08574ed44125bd7cab -
Trigger Event:
push
-
Statement type: