-
Notifications
You must be signed in to change notification settings - Fork 0
Testing PyTest Bridge
Run pytest tests inside live Revit, AutoCAD, or Civil 3D instances via Named Pipe.
Source code:
RevitDevTool.PyTest(separate repo) | PyPI:revitdevtool_pytest| Architecture: docs/PyTest/README.md
Host API code cannot be fully tested from a normal external Python process because API calls need host context (active document, transactions, Revit/AutoCAD runtime). The bridge lets pytest collect tests locally, then execute them remotely inside the running host.
Local pytest (collect) → Named Pipe → Host (PytestRunner.py) → Results → Local pytest (report)
- pytest discovers and collects tests locally
- Plugin connects to the host via Named Pipe (
{Host}_{Version}_{PID}) - Test nodeids are sent to the host's
PytestRunner.py - Tests execute inside the host's Python.NET environment with full API access
- Results (pass/fail/skip, stdout, tracebacks) return via pipe
- Plugin maps results back to standard pytest reports
pip install revitdevtool_pytestAdd to pyproject.toml:
[tool.pytest.ini_options]
host_name = "revit" # revit, autocad, civil3d, plant3d, etc.
host_version = "2025" # version string (2025, 8.0, etc.)
host_launch = false # true = always launch new instance
host_timeout = "60" # per-test timeout (seconds)
host_launch_timeout = "180" # startup wait (seconds)| Host Name | Application | Pipe Prefix |
|---|---|---|
revit |
Autodesk Revit | Revit |
autocad |
AutoCAD | AutoCad |
civil3d |
Civil 3D | Civil3D |
plant3d |
Plant 3D | Plant3D |
| Any name | Any DevToolsPipeServer host | Uses name as prefix |
# Default (uses pyproject.toml config):
pytest -v
# Override host and version:
pytest --host autocad --host-version=2026 -v
# Civil 3D:
pytest --host civil3d --host-version=2026 -v
# Force-launch a new instance:
pytest --host-launch --host-version=2025 -v
# Connect to a specific pipe:
pytest --host-pipe=Revit_2025_12345 -v# conftest.py
import pytest
@pytest.fixture(scope="session")
def revit_uiapp():
return __revit__ # noqa: F821
@pytest.fixture(scope="session")
def revit_doc(revit_uiapp):
return revit_uiapp.ActiveUIDocument.Document# test_walls.py
def test_wall_count(revit_doc):
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory
walls = list(
FilteredElementCollector(revit_doc)
.OfCategory(BuiltInCategory.OST_Walls)
.WhereElementIsNotElementType()
)
print(f"Found {len(walls)} walls")
assert len(walls) > 0# conftest.py
import pytest
@pytest.fixture(scope="session")
def acad_app():
from Autodesk.AutoCAD.ApplicationServices.Core import Application
return Application
@pytest.fixture(scope="session")
def acad_doc(acad_app):
return acad_app.DocumentManager.MdiActiveDocument
@pytest.fixture(scope="session")
def acad_db(acad_doc):
return acad_doc.Database# test_layers.py
def test_layer_count(acad_db, acad_transaction):
from Autodesk.AutoCAD.DatabaseServices import LayerTable, OpenMode
lt = acad_transaction.GetObject(acad_db.LayerTableId, OpenMode.ForRead)
count = sum(1 for _ in lt)
print(f"Found {count} layers")
assert count > 0- All host/.NET imports must be inside function bodies (lazy imports)
- Revit:
__revit__builtin is injected by RevitDevTool — access via fixtures - AutoCAD: no builtin injection — use static
Applicationclass directly - Tests run on the host's main thread sequentially
Declare dependencies in conftest.py — RevitDevTool auto-installs them:
# /// script
# dependencies = ["numpy>=2.0", "polars>=1.0"]
# ///print() inside tests is automatically captured and displayed for both passing and failing tests. No extra flags needed.
{
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": ["tests"]
}Enable pytest as the test runner. The plugin auto-detects IDE adapters and adjusts streaming to avoid duplicate results.
- Verify the host is running with RevitDevTool installed
- Check pipe exists:
ls //./pipe/ | findstr Revit(orAutoCad,Civil3D) - Try explicit pipe:
pytest --host-pipe=Revit_2025_<pid> - Check
--host-versionmatches running instance
Another pytest session holds the suite mutex. Kill the other process or wait.
Increase timeout: pytest --host-timeout=120
- Run Code Overview
- Modern Python Scripting
- Python Debugging
- Python Ecosystems
- RevitDevTool And pyRevit
- Python Stub Generation
- Run .NET Add-ins
- Scripting Runtimes