revitdevtool-pytest 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/.gitignore +1 -0
- revitdevtool_pytest-0.4.0/.run/Attach.run.xml +8 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/.vscode/settings.json +1 -1
- revitdevtool_pytest-0.4.0/AGENTS.md +202 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/CHANGELOG.md +18 -0
- revitdevtool_pytest-0.4.0/PKG-INFO +220 -0
- revitdevtool_pytest-0.4.0/README.md +193 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/pyproject.toml +14 -10
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/__init__.py +1 -1
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/bridge.py +26 -1
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/connection.py +11 -16
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/constants.py +14 -5
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/discovery.py +7 -17
- revitdevtool_pytest-0.4.0/src/revitdevtool_pytest/ipy_collect.py +91 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/models.py +3 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/plugin.py +92 -54
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/reporting.py +105 -19
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/suite_leasing.py +30 -28
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/suite_lock.py +21 -13
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Civil3d/test_active_state.py +2 -2
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/conftest.py +2 -2
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/contracts.py +1 -1
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/custom_workflow.py +3 -3
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/field_mapping.py +1 -1
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/header_workflow.py +3 -3
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/serializer.py +3 -3
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/template_workflow.py +6 -6
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_schedule_custom_copy_revit.py +9 -9
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_schedule_field_mapping_revit.py +3 -3
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_schedule_header_capture_revit.py +7 -7
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_schedule_header_copy_revit.py +6 -6
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_scheduleformatting_revit.py +16 -16
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/conftest.py +5 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/ipylib/__init__.py +16 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/ipylib/geom.py +14 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/nested/__init__.py +1 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/nested/test_nested_import_ipy.py +11 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/pyproject.toml +5 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/test_document_ipy.py +41 -0
- revitdevtool_pytest-0.4.0/tests/Revit_Ipy/test_ipylib_ipy.py +22 -0
- revitdevtool_pytest-0.4.0/tests/plugin/conftest.py +9 -0
- revitdevtool_pytest-0.4.0/tests/plugin/test_fan_suite_results.py +50 -0
- revitdevtool_pytest-0.4.0/tests/plugin/test_ipy_collect.py +122 -0
- revitdevtool_pytest-0.4.0/tests/plugin/test_plugin_runtestloop.py +23 -0
- revitdevtool_pytest-0.4.0/tests/plugin/test_reporting.py +212 -0
- revitdevtool_pytest-0.4.0/tests/plugin/test_suite_leasing.py +25 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/uv.lock +2 -2
- revitdevtool_pytest-0.3.0/AGENTS.md +0 -164
- revitdevtool_pytest-0.3.0/PKG-INFO +0 -234
- revitdevtool_pytest-0.3.0/README.md +0 -207
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/.github/workflows/publish.yml +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/CLAUDE.md +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/LICENSE +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/src/revitdevtool_pytest/dialog_resolver.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Civil3d/conftest.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Civil3d/test_civil3d_api.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Civil3d/test_document.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Civil3d/test_geometry.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Civil3d/test_smoke.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/_session_probe.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/__init__.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/constants.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/model.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/table_cell.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/schedule/test.json +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_active_state.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_dependencies.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_image_export.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_revit_basic.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_revit_document.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_revit_transactions.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_session_cleanliness.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_smoke.py +0 -0
- {revitdevtool_pytest-0.3.0 → revitdevtool_pytest-0.4.0}/tests/Revit/test_streaming.py +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<component name="ProjectRunConfigurationManager">
|
|
2
|
+
<configuration default="false" name="Attach Host: Python" type="PythonDapAttachConfiguration">
|
|
3
|
+
<option name="localRoot" value="$PROJECT_DIR$" />
|
|
4
|
+
<option name="remoteAddress" value="localhost:5678" />
|
|
5
|
+
<option name="remoteRoot" value="$PROJECT_DIR$" />
|
|
6
|
+
<method v="2" />
|
|
7
|
+
</configuration>
|
|
8
|
+
</component>
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# AGENTS
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
pytest client plugin for [RevitDevTool](https://github.com/trgiangv/RevitDevTool). Collects tests locally, executes them inside a live host via Named Pipe JSON-RPC (`BridgeMessage` framing).
|
|
6
|
+
|
|
7
|
+
**Supported today:** **Revit** and **AutoCAD family** (AutoCAD, Civil 3D, Plant 3D, Architecture / Mechanical / MEP / Electrical / Map 3D). Other hosts may appear in the registry but are **in progress** — not validated end-to-end yet.
|
|
8
|
+
|
|
9
|
+
**Package:** `revitdevtool_pytest` (PyPI) · **Entry point:** `revitdevtool` · **Version:** see `pyproject.toml`
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
flowchart LR
|
|
15
|
+
Collect[Local collect] --> Pipe["DevTools_*"]
|
|
16
|
+
Pipe --> CPython[PytestRunner.py]
|
|
17
|
+
Pipe --> IPy[IpyTestDriver.py]
|
|
18
|
+
CPython --> Report[Local report]
|
|
19
|
+
IPy --> Report
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Do **not** connect to `DevToolsMcp_*` (MCP SDK). Pytest uses `DevTools_{Host}_{Version}_{PID}` on `DevToolsPipeServer`.
|
|
23
|
+
|
|
24
|
+
### Client modules (`src/revitdevtool_pytest/`)
|
|
25
|
+
|
|
26
|
+
| Module | Role |
|
|
27
|
+
|--------|------|
|
|
28
|
+
| `plugin.py` | Hook orchestrator — lifecycle, options, bridge setup |
|
|
29
|
+
| `ipy_collect.py` | Pytest collect convention `test_*_ipy.py` → `ipytests/run` (no CPython import) |
|
|
30
|
+
| `connection.py` | Discover, connect, lease, launch, retry |
|
|
31
|
+
| `bridge.py` | Named Pipe framing, `tests/run` / `ipytests/run` RPC |
|
|
32
|
+
| `discovery.py` | Pipe scan, host registry, process launch |
|
|
33
|
+
| `reporting.py` | Remote `CaseResult` → pytest `TestReport` |
|
|
34
|
+
| `suite_leasing.py` | File-based suite → host PID allocation |
|
|
35
|
+
| `suite_lock.py` | Windows mutex — same suite, one pytest process |
|
|
36
|
+
| `dialog_resolver.py` | Auto-dismiss host startup dialogs (Win32) |
|
|
37
|
+
| `models.py` | Wire models (mirror C# `PytestContracts`) |
|
|
38
|
+
| `constants.py` | Options, host registry, pipe pattern |
|
|
39
|
+
|
|
40
|
+
### Host-side (RevitDevTool repo)
|
|
41
|
+
|
|
42
|
+
| Location | Role |
|
|
43
|
+
|----------|------|
|
|
44
|
+
| `DevTools.Execution/External/DevToolsPipeServer.cs` | Pytest/control pipe server |
|
|
45
|
+
| `DevTools.Execution/External/Handlers/PytestRequestHandler.cs` | Routes `tests/run` |
|
|
46
|
+
| `DevTools.Execution/External/Handlers/IpyTestRequestHandler.cs` | Routes `ipytests/run` |
|
|
47
|
+
| `DevTools.Execution/External/Testing/` | `PytestExecutionService`, `IpyTestExecutionService`, `PytestContracts` |
|
|
48
|
+
| `DevTools.Execution/Resources/scripts/PytestRunner.py` | In-host `pytest.main()` runner |
|
|
49
|
+
| `DevTools.Execution/Resources/scripts/IpyTestDriver.py` | In-host IronPython test driver (2.7 / 3.4) |
|
|
50
|
+
|
|
51
|
+
Wire methods: `tests/run` (CPython pytest), `ipytests/run` (IronPython unittest, pyRevit-first). Progress notifications: `notifications/tests/progress`.
|
|
52
|
+
|
|
53
|
+
**IPy collect convention is `test_*_ipy.py`** (pytest `test_` + `_ipy` marker). That name is only how the plugin routes onto `ipytests/run`; the host runs unittest on the requested paths and does not require it. Dialect: 2.7 / 3.4, `unittest.TestCase`, no pytest fixtures / PEP 723 (CPython `tests/run` still installs `# /// script` via pixi). `*_ipy_script.py` is execution-tree script, not a test file. Library modules use normal names (`ipylib/geom.py`).
|
|
54
|
+
|
|
55
|
+
## This repo layout
|
|
56
|
+
|
|
57
|
+
Integration tests for the plugin — not shipped in the wheel.
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
tests/
|
|
61
|
+
plugin/ # local plugin unit tests (no host); sets REVITDEVTOOL_PYTEST_DISABLE
|
|
62
|
+
Revit/ # default testpaths in pyproject.toml
|
|
63
|
+
conftest.py # PEP 723 deps (CPython tests/run only), revit_doc, rollback fixtures
|
|
64
|
+
schedule/ # shared schedule helpers (import as schedule.*)
|
|
65
|
+
test_*.py # CPython pytest → tests/run
|
|
66
|
+
test_*_ipy.py # mixed-tree IronPython unittest → ipytests/run
|
|
67
|
+
Revit_Ipy/ # IPy libs + more test_*_ipy.py (folder is not identity)
|
|
68
|
+
ipylib/ # 2.7/3.4 helpers imported by tests
|
|
69
|
+
test_*_ipy.py
|
|
70
|
+
Civil3d/
|
|
71
|
+
conftest.py # acad_app, acad_doc, transaction fixtures
|
|
72
|
+
test_*.py
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Switch suites via `pyproject.toml`:
|
|
76
|
+
|
|
77
|
+
```toml
|
|
78
|
+
testpaths = ["tests/Revit"] # or tests/Civil3d
|
|
79
|
+
host_name = "revit" # or civil3d, autocad, …
|
|
80
|
+
host_version = "2025"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Schedule helpers live under `tests/Revit/schedule/`. Imports use the `schedule` package name (e.g. `from schedule.constants import …`), with `pythonpath = ["tests/Revit"]` in `pyproject.toml`.
|
|
84
|
+
|
|
85
|
+
`revit_doc` opens `REVIT_TEST_MODEL_PATH` (default `F:\Project1.rvt`) when set.
|
|
86
|
+
|
|
87
|
+
## Host support
|
|
88
|
+
|
|
89
|
+
### Supported (tested)
|
|
90
|
+
|
|
91
|
+
| Host Name | Pipe Prefix | Executable | Product ID |
|
|
92
|
+
|-----------|------------|------------|------------|
|
|
93
|
+
| `revit` | `Revit` | `Revit.exe` | — |
|
|
94
|
+
| `autocad` | `AutoCad` | `acad.exe` | `01` |
|
|
95
|
+
| `civil3d` | `Civil3D` | `acad.exe` | `00` |
|
|
96
|
+
| `plant3d` | `Plant3D` | `acad.exe` | `17` |
|
|
97
|
+
| `acadarch` | `AcadArch` | `acad.exe` | `04` |
|
|
98
|
+
| `acadmech` | `AcadMech` | `acad.exe` | `05` |
|
|
99
|
+
| `acadmep` | `AcadMep` | `acad.exe` | `06` |
|
|
100
|
+
| `acadelec` | `AcadElec` | `acad.exe` | `07` |
|
|
101
|
+
| `acadmap3d` | `AcadMap3D` | `acad.exe` | `02` |
|
|
102
|
+
|
|
103
|
+
### In progress (not supported yet)
|
|
104
|
+
|
|
105
|
+
| Host Name | Pipe Prefix | Notes |
|
|
106
|
+
|-----------|------------|--------|
|
|
107
|
+
| `navisworks` | `Navisworks` | Registry stub only |
|
|
108
|
+
| `rhino` | `Rhino` | Registry stub only |
|
|
109
|
+
| `tekla` | `Tekla` | Registry stub only |
|
|
110
|
+
|
|
111
|
+
Unknown host names still get a fallback `HostConfig(pipe_prefix=host_name)` for experimentation, but are not supported. Do not document or rely on them until promoted to **Supported**.
|
|
112
|
+
|
|
113
|
+
### Pipe format
|
|
114
|
+
|
|
115
|
+
`DevTools_{Host}_{Version}_{PID}` — regex `^DevTools_\w+_[^_]+_\d+$`
|
|
116
|
+
|
|
117
|
+
Examples: `DevTools_Revit_2025_12345`, `DevTools_AutoCad_2026_7890`
|
|
118
|
+
|
|
119
|
+
## Key design decisions
|
|
120
|
+
|
|
121
|
+
- **Dual pytest model:** collect locally, execute in-host (IDE tree + host thread).
|
|
122
|
+
- **`--capture=sys`:** required in embedded Python.NET (no fd-level `dup2`).
|
|
123
|
+
- **`sys.__pytest_running__`:** set by `PytestRunner.py`; setup scripts skip I/O hijack during runs.
|
|
124
|
+
- **Streaming vs batch:** CLI streams progress; IDE adapters (`vscode_pytest`, `TEST_RUN_PIPE`) get one batch.
|
|
125
|
+
- **Suite leasing + mutex:** one pytest process per host+version+workspace; CPython and IronPython tests in that workspace reuse the same host PID. One invocation still cannot mix two `conftest.py` trees — run `tests/Revit` then `tests/Revit_Ipy` separately (same Revit). Mixed `test_*.py` + `test_*_ipy.py` under one conftest is fine (`tests/run` then `ipytests/run` on the same pipe).
|
|
126
|
+
- **`force_launch`:** force new host + wait for that PID's pipe; skip reuse.
|
|
127
|
+
- **No matching instance:** after discovery fails, plugin auto-launches when `host_version` is set.
|
|
128
|
+
|
|
129
|
+
## Running tests
|
|
130
|
+
|
|
131
|
+
Always **`uv run pytest`** from this repo root — do not use system Python or bare `pytest`.
|
|
132
|
+
|
|
133
|
+
```powershell
|
|
134
|
+
cd c:\Users\truon\source\repos\RevitDevTool.PyTest
|
|
135
|
+
uv run pytest -v
|
|
136
|
+
uv run pytest tests/Revit/test_active_state.py::test_active_view_info -v
|
|
137
|
+
uv run pytest --host-version=2025 -v
|
|
138
|
+
uv run pytest --host autocad --host-version 2026 -v
|
|
139
|
+
uv run pytest --force-launch --host-version=2025 -v
|
|
140
|
+
uv run pytest tests/Revit_Ipy -v --host-version=2025
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Plugin auto-enables `-rP` (stdout for passing tests).
|
|
144
|
+
|
|
145
|
+
## Configuration
|
|
146
|
+
|
|
147
|
+
`[tool.pytest.ini_options]` in `pyproject.toml`:
|
|
148
|
+
|
|
149
|
+
```toml
|
|
150
|
+
testpaths = ["tests/Revit"]
|
|
151
|
+
pythonpath = ["tests/Revit"]
|
|
152
|
+
host_name = "revit"
|
|
153
|
+
host_version = "2025"
|
|
154
|
+
force_launch = false
|
|
155
|
+
per_test_timeout = "60"
|
|
156
|
+
launch_timeout = "180"
|
|
157
|
+
host_pipe = ""
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
CLI: `--host`, `--host-version`, `--per-test-timeout`, `--host-pipe`, `--force-launch`, `--launch-timeout`.
|
|
161
|
+
|
|
162
|
+
## Fixtures pattern
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# conftest.py (Revit)
|
|
166
|
+
@pytest.fixture(scope="session")
|
|
167
|
+
def revit_uiapp():
|
|
168
|
+
return __revit__ # noqa: F821
|
|
169
|
+
|
|
170
|
+
@pytest.fixture(scope="session")
|
|
171
|
+
def revit_doc(revit_uiapp):
|
|
172
|
+
return revit_uiapp.ActiveUIDocument.Document
|
|
173
|
+
|
|
174
|
+
@pytest.fixture
|
|
175
|
+
def revit_auto_rollback(revit_transaction_service):
|
|
176
|
+
revit_transaction_service.StartChanges()
|
|
177
|
+
try:
|
|
178
|
+
yield revit_transaction_service
|
|
179
|
+
finally:
|
|
180
|
+
revit_transaction_service.RevertChanges()
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Host API imports belong **inside test bodies** (or fixture bodies), not at module top level.
|
|
184
|
+
|
|
185
|
+
## Common traps
|
|
186
|
+
|
|
187
|
+
- Tests run **inside the host**, not locally.
|
|
188
|
+
- `__revit__` only exists at runtime — use fixtures.
|
|
189
|
+
- Host APIs need the main thread; execution is sequential via `IHostContextExecutor`.
|
|
190
|
+
- Pytest pipe ≠ MCP pipe (`DevTools_*` vs `DevToolsMcp_*`).
|
|
191
|
+
- PEP 723 deps in CPython `conftest.py` / `test_*.py` are installed by `PytestDependencyService` before `tests/run`. **IronPython `test_*_ipy.py` does not use PEP 723** — `ipytests/run` never calls that service; IPy 2.7/3.4 cannot import CPython wheels.
|
|
192
|
+
- `--force-launch` requires `--host-version`.
|
|
193
|
+
- `print()` captured via `--capture=sys` → `CaseResult.stdout`.
|
|
194
|
+
- IronPython tests: no pytest fixtures; **no PEP 723**; host APIs inside methods; `test_*_ipy.py` is pytest routing only, not a host filename contract.
|
|
195
|
+
|
|
196
|
+
## Change rules
|
|
197
|
+
|
|
198
|
+
- Wire protocol: sync `models.py` ↔ `PytestContracts.cs` / `PytestBridgeMethods.cs`.
|
|
199
|
+
- New CLI options: `pytest_addoption` + `parser.addini`.
|
|
200
|
+
- `connection.py` stays stateless; only `plugin.py` holds session globals.
|
|
201
|
+
- After connection/discovery changes: test `force_launch = true` and `false`.
|
|
202
|
+
- `HOST_REGISTRY` ↔ C# `HostApp` enum + `AcadPathResolver.ProductIdMap`.
|
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.4.0] - 2026-08-31
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- IronPython tests: files named `test_*_ipy.py` run on the host via `ipytests/run`
|
|
10
|
+
(`unittest`). CPython `test_*.py` still uses `tests/run`.
|
|
11
|
+
- CPython and IronPython suites in the same workspace reuse one host instance.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Pipe name is `DevTools_{Host}_{Version}_{PID}` (was `{Host}_{Version}_{PID}`).
|
|
16
|
+
Pytest does not use the MCP pipe `DevToolsMcp_*`.
|
|
17
|
+
- CLI/INI names match RevitDevTool.TestAdapter (breaking vs 0.3.0):
|
|
18
|
+
`--host-launch` → `--force-launch`, `--host-timeout` → `--per-test-timeout`,
|
|
19
|
+
`--host-launch-timeout` → `--launch-timeout`. `--host` / `--host-version` unchanged.
|
|
20
|
+
- PEP 723 `# /// script` is installed only for CPython `tests/run`. IronPython
|
|
21
|
+
tests cannot use CPython wheels.
|
|
22
|
+
|
|
5
23
|
## [0.3.0] - 2026-05-31
|
|
6
24
|
|
|
7
25
|
### Added
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: revitdevtool_pytest
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: pytest plugin for testing CAD/BIM API code inside host applications via RevitDevTool Named Pipe bridge
|
|
5
|
+
Project-URL: Homepage, https://github.com/trgiangv/RevitDevTool.PyTest
|
|
6
|
+
Project-URL: Repository, https://github.com/trgiangv/RevitDevTool.PyTest
|
|
7
|
+
Project-URL: Issues, https://github.com/trgiangv/RevitDevTool.PyTest/issues
|
|
8
|
+
Author: Truong Giang Vu
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: autocad,bim,civil3d,multi-host,pytest,revit,revit-api,revitdevtool,testing
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Framework :: Pytest
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: pytest>=9.0
|
|
25
|
+
Requires-Dist: pywin32>=311
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# RevitDevTool.PyTest
|
|
29
|
+
|
|
30
|
+
[](https://pypi.org/project/revitdevtool-pytest/)
|
|
31
|
+
[](https://pypi.org/project/revitdevtool-pytest/)
|
|
32
|
+
[](LICENSE)
|
|
33
|
+
|
|
34
|
+
pytest plugin for testing CAD/BIM API code inside live host applications via the RevitDevTool Named Pipe bridge.
|
|
35
|
+
|
|
36
|
+
Write tests locally with pytest; execution happens inside the host process. **Currently supported:** **Revit** and **AutoCAD family** only. Navisworks, Rhino, Tekla, and other hosts are **in progress**.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install revitdevtool_pytest
|
|
42
|
+
# or
|
|
43
|
+
uv add revitdevtool_pytest
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| Requirement | Version |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Python | >= 3.10 |
|
|
49
|
+
| pytest | >= 9.0 |
|
|
50
|
+
| pywin32 | >= 311 |
|
|
51
|
+
| OS | Windows (Named Pipes) |
|
|
52
|
+
| Host | [RevitDevTool](https://github.com/trgiangv/RevitDevTool) add-in loaded |
|
|
53
|
+
|
|
54
|
+
## Supported hosts
|
|
55
|
+
|
|
56
|
+
### Supported today
|
|
57
|
+
|
|
58
|
+
| `host_name` | Application | Pipe prefix |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `revit` | Autodesk Revit | `Revit` |
|
|
61
|
+
| `autocad` | AutoCAD | `AutoCad` |
|
|
62
|
+
| `civil3d` | Civil 3D | `Civil3D` |
|
|
63
|
+
| `plant3d` | Plant 3D | `Plant3D` |
|
|
64
|
+
| `acadarch` | AutoCAD Architecture | `AcadArch` |
|
|
65
|
+
| `acadmech` | AutoCAD Mechanical | `AcadMech` |
|
|
66
|
+
| `acadmep` | AutoCAD MEP | `AcadMep` |
|
|
67
|
+
| `acadelec` | AutoCAD Electrical | `AcadElec` |
|
|
68
|
+
| `acadmap3d` | AutoCAD Map 3D | `AcadMap3D` |
|
|
69
|
+
|
|
70
|
+
### In progress
|
|
71
|
+
|
|
72
|
+
| `host_name` | Application | Status |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `navisworks` | Navisworks | Not validated |
|
|
75
|
+
| `rhino` | Rhino | Not validated |
|
|
76
|
+
| `tekla` | Tekla Structures | Not validated |
|
|
77
|
+
|
|
78
|
+
The plugin registry may list additional names for future work. Treat them as experimental until documented here as **Supported today**.
|
|
79
|
+
|
|
80
|
+
### Pipe names (pytest only)
|
|
81
|
+
|
|
82
|
+
The plugin connects to the **pytest/control** pipe:
|
|
83
|
+
|
|
84
|
+
`DevTools_{Host}_{Version}_{PID}`
|
|
85
|
+
|
|
86
|
+
Examples: `DevTools_Revit_2025_12345`, `DevTools_AutoCad_2026_7890`
|
|
87
|
+
|
|
88
|
+
MCP clients use a separate pipe: `DevToolsMcp_{Host}_{Version}_{PID}`. Do not point pytest at an MCP pipe.
|
|
89
|
+
|
|
90
|
+
## Quick start (consumer project)
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
uv init my-host-tests && cd my-host-tests
|
|
94
|
+
uv add revitdevtool_pytest pytest
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`pyproject.toml`:
|
|
98
|
+
|
|
99
|
+
```toml
|
|
100
|
+
[tool.pytest.ini_options]
|
|
101
|
+
host_name = "revit"
|
|
102
|
+
host_version = "2025"
|
|
103
|
+
force_launch = false
|
|
104
|
+
per_test_timeout = "60"
|
|
105
|
+
launch_timeout = "180"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`tests/conftest.py`:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import pytest
|
|
112
|
+
|
|
113
|
+
@pytest.fixture(scope="session")
|
|
114
|
+
def revit_uiapp():
|
|
115
|
+
return __revit__
|
|
116
|
+
|
|
117
|
+
@pytest.fixture(scope="session")
|
|
118
|
+
def revit_doc(revit_uiapp):
|
|
119
|
+
return revit_uiapp.ActiveUIDocument.Document
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`tests/test_smoke.py`:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
def test_active_view(revit_doc):
|
|
126
|
+
assert revit_doc.ActiveView is not None
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv run pytest -v
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Configuration
|
|
134
|
+
|
|
135
|
+
| Option | Default | Description |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| `host_name` | `"revit"` | Target host — use **Supported today** names only. |
|
|
138
|
+
| `host_version` | — | Version string (`"2025"`, `"8.0"`, …). Required for launch. |
|
|
139
|
+
| `force_launch` | `false` | Force a **new** host instance (skip reuse). Requires `host_version`. |
|
|
140
|
+
| `per_test_timeout` | `"60"` | Per-test budget (seconds). The `tests/run` pipe wait is this × collected tests. |
|
|
141
|
+
| `launch_timeout` | `"180"` | Wait for host pipe after launch (seconds). |
|
|
142
|
+
| `host_pipe` | — | Explicit pipe name (skip discovery). |
|
|
143
|
+
|
|
144
|
+
CLI flags override INI: `--host`, `--host-version`, `--force-launch`, `--per-test-timeout`, `--launch-timeout`, `--host-pipe`.
|
|
145
|
+
|
|
146
|
+
### Connection behavior
|
|
147
|
+
|
|
148
|
+
1. **`force_launch = false` (default):** scan for `DevTools_*` pipes matching `host_name` / `host_version`, reuse a free instance (suite leasing), or reconnect to a leased PID.
|
|
149
|
+
2. **No matching instance:** auto-launch host when `host_version` is set (unless `--host-pipe` pins an existing pipe).
|
|
150
|
+
3. **`force_launch = true`:** always spawn a new process and wait for its pipe.
|
|
151
|
+
|
|
152
|
+
### Print output
|
|
153
|
+
|
|
154
|
+
Captured `print()` from in-host tests is shown for passing tests (same as `-rP`). No extra flags needed.
|
|
155
|
+
|
|
156
|
+
## Writing tests
|
|
157
|
+
|
|
158
|
+
- Put **host API imports inside functions** — collection runs on your machine, execution in the host.
|
|
159
|
+
- Use fixtures for `__revit__`, documents, and rollback helpers.
|
|
160
|
+
- Declare suite dependencies with **PEP 723** in CPython `conftest.py` (or `test_*.py`); RevitDevTool installs them before `tests/run`. IronPython `test_*_ipy.py` **does not** use PEP 723 — `ipytests/run` never installs packages.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# /// script
|
|
164
|
+
# dependencies = ["numpy>=2.0", "polars>=1.0"]
|
|
165
|
+
# ///
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Revit rollback fixture
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
@pytest.fixture
|
|
172
|
+
def revit_auto_rollback(revit_transaction_service):
|
|
173
|
+
revit_transaction_service.StartChanges()
|
|
174
|
+
try:
|
|
175
|
+
yield revit_transaction_service
|
|
176
|
+
finally:
|
|
177
|
+
revit_transaction_service.RevertChanges()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## How it works
|
|
181
|
+
|
|
182
|
+
1. Local pytest collects tests.
|
|
183
|
+
2. Plugin connects to `DevTools_{Host}_{Version}_{PID}`.
|
|
184
|
+
3. Node IDs sent via JSON-RPC method `tests/run` (`BridgeMessage` length-prefixed frames).
|
|
185
|
+
4. Host runs `PytestRunner.py` embedded in RevitDevTool (`PytestExecutionService` on main thread).
|
|
186
|
+
5. Results and optional progress notifications return to the client.
|
|
187
|
+
6. Plugin maps `CaseResult` → standard pytest reports.
|
|
188
|
+
|
|
189
|
+
## Developing this repository
|
|
190
|
+
|
|
191
|
+
Clone and run integration tests against a live host:
|
|
192
|
+
|
|
193
|
+
```powershell
|
|
194
|
+
cd RevitDevTool.PyTest
|
|
195
|
+
uv run pytest -v # Revit suite (default)
|
|
196
|
+
uv run pytest tests/Revit/test_smoke.py -v
|
|
197
|
+
uv run pytest --host civil3d --host-version 2026 # after switching testpaths/host in pyproject.toml
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Layout
|
|
201
|
+
|
|
202
|
+
| Path | Purpose |
|
|
203
|
+
|---|---|
|
|
204
|
+
| `src/revitdevtool_pytest/` | Plugin source (published wheel) |
|
|
205
|
+
| `tests/Revit/` | Revit integration tests + `schedule/` helpers |
|
|
206
|
+
| `tests/Civil3d/` | Civil 3D / AutoCAD API tests |
|
|
207
|
+
|
|
208
|
+
Revit suite settings in `pyproject.toml`: `testpaths = ["tests/Revit"]`, `pythonpath = ["tests/Revit"]` for local `schedule` imports.
|
|
209
|
+
|
|
210
|
+
Optional env: `REVIT_TEST_MODEL_PATH` — path to `.rvt` for `revit_doc` fixture (default `F:\Project1.rvt`).
|
|
211
|
+
|
|
212
|
+
## IDE integration
|
|
213
|
+
|
|
214
|
+
**VS Code / Cursor** — `python.testing.pytestEnabled: true`. Plugin detects `vscode_pytest` / `TEST_RUN_PIPE` and disables CLI streaming to avoid duplicate tree entries.
|
|
215
|
+
|
|
216
|
+
**PyCharm** — enable pytest as test runner.
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# RevitDevTool.PyTest
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/revitdevtool-pytest/)
|
|
4
|
+
[](https://pypi.org/project/revitdevtool-pytest/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
pytest plugin for testing CAD/BIM API code inside live host applications via the RevitDevTool Named Pipe bridge.
|
|
8
|
+
|
|
9
|
+
Write tests locally with pytest; execution happens inside the host process. **Currently supported:** **Revit** and **AutoCAD family** only. Navisworks, Rhino, Tekla, and other hosts are **in progress**.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install revitdevtool_pytest
|
|
15
|
+
# or
|
|
16
|
+
uv add revitdevtool_pytest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Requirement | Version |
|
|
20
|
+
|---|---|
|
|
21
|
+
| Python | >= 3.10 |
|
|
22
|
+
| pytest | >= 9.0 |
|
|
23
|
+
| pywin32 | >= 311 |
|
|
24
|
+
| OS | Windows (Named Pipes) |
|
|
25
|
+
| Host | [RevitDevTool](https://github.com/trgiangv/RevitDevTool) add-in loaded |
|
|
26
|
+
|
|
27
|
+
## Supported hosts
|
|
28
|
+
|
|
29
|
+
### Supported today
|
|
30
|
+
|
|
31
|
+
| `host_name` | Application | Pipe prefix |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `revit` | Autodesk Revit | `Revit` |
|
|
34
|
+
| `autocad` | AutoCAD | `AutoCad` |
|
|
35
|
+
| `civil3d` | Civil 3D | `Civil3D` |
|
|
36
|
+
| `plant3d` | Plant 3D | `Plant3D` |
|
|
37
|
+
| `acadarch` | AutoCAD Architecture | `AcadArch` |
|
|
38
|
+
| `acadmech` | AutoCAD Mechanical | `AcadMech` |
|
|
39
|
+
| `acadmep` | AutoCAD MEP | `AcadMep` |
|
|
40
|
+
| `acadelec` | AutoCAD Electrical | `AcadElec` |
|
|
41
|
+
| `acadmap3d` | AutoCAD Map 3D | `AcadMap3D` |
|
|
42
|
+
|
|
43
|
+
### In progress
|
|
44
|
+
|
|
45
|
+
| `host_name` | Application | Status |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `navisworks` | Navisworks | Not validated |
|
|
48
|
+
| `rhino` | Rhino | Not validated |
|
|
49
|
+
| `tekla` | Tekla Structures | Not validated |
|
|
50
|
+
|
|
51
|
+
The plugin registry may list additional names for future work. Treat them as experimental until documented here as **Supported today**.
|
|
52
|
+
|
|
53
|
+
### Pipe names (pytest only)
|
|
54
|
+
|
|
55
|
+
The plugin connects to the **pytest/control** pipe:
|
|
56
|
+
|
|
57
|
+
`DevTools_{Host}_{Version}_{PID}`
|
|
58
|
+
|
|
59
|
+
Examples: `DevTools_Revit_2025_12345`, `DevTools_AutoCad_2026_7890`
|
|
60
|
+
|
|
61
|
+
MCP clients use a separate pipe: `DevToolsMcp_{Host}_{Version}_{PID}`. Do not point pytest at an MCP pipe.
|
|
62
|
+
|
|
63
|
+
## Quick start (consumer project)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv init my-host-tests && cd my-host-tests
|
|
67
|
+
uv add revitdevtool_pytest pytest
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`pyproject.toml`:
|
|
71
|
+
|
|
72
|
+
```toml
|
|
73
|
+
[tool.pytest.ini_options]
|
|
74
|
+
host_name = "revit"
|
|
75
|
+
host_version = "2025"
|
|
76
|
+
force_launch = false
|
|
77
|
+
per_test_timeout = "60"
|
|
78
|
+
launch_timeout = "180"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`tests/conftest.py`:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
import pytest
|
|
85
|
+
|
|
86
|
+
@pytest.fixture(scope="session")
|
|
87
|
+
def revit_uiapp():
|
|
88
|
+
return __revit__
|
|
89
|
+
|
|
90
|
+
@pytest.fixture(scope="session")
|
|
91
|
+
def revit_doc(revit_uiapp):
|
|
92
|
+
return revit_uiapp.ActiveUIDocument.Document
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`tests/test_smoke.py`:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
def test_active_view(revit_doc):
|
|
99
|
+
assert revit_doc.ActiveView is not None
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv run pytest -v
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Configuration
|
|
107
|
+
|
|
108
|
+
| Option | Default | Description |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `host_name` | `"revit"` | Target host — use **Supported today** names only. |
|
|
111
|
+
| `host_version` | — | Version string (`"2025"`, `"8.0"`, …). Required for launch. |
|
|
112
|
+
| `force_launch` | `false` | Force a **new** host instance (skip reuse). Requires `host_version`. |
|
|
113
|
+
| `per_test_timeout` | `"60"` | Per-test budget (seconds). The `tests/run` pipe wait is this × collected tests. |
|
|
114
|
+
| `launch_timeout` | `"180"` | Wait for host pipe after launch (seconds). |
|
|
115
|
+
| `host_pipe` | — | Explicit pipe name (skip discovery). |
|
|
116
|
+
|
|
117
|
+
CLI flags override INI: `--host`, `--host-version`, `--force-launch`, `--per-test-timeout`, `--launch-timeout`, `--host-pipe`.
|
|
118
|
+
|
|
119
|
+
### Connection behavior
|
|
120
|
+
|
|
121
|
+
1. **`force_launch = false` (default):** scan for `DevTools_*` pipes matching `host_name` / `host_version`, reuse a free instance (suite leasing), or reconnect to a leased PID.
|
|
122
|
+
2. **No matching instance:** auto-launch host when `host_version` is set (unless `--host-pipe` pins an existing pipe).
|
|
123
|
+
3. **`force_launch = true`:** always spawn a new process and wait for its pipe.
|
|
124
|
+
|
|
125
|
+
### Print output
|
|
126
|
+
|
|
127
|
+
Captured `print()` from in-host tests is shown for passing tests (same as `-rP`). No extra flags needed.
|
|
128
|
+
|
|
129
|
+
## Writing tests
|
|
130
|
+
|
|
131
|
+
- Put **host API imports inside functions** — collection runs on your machine, execution in the host.
|
|
132
|
+
- Use fixtures for `__revit__`, documents, and rollback helpers.
|
|
133
|
+
- Declare suite dependencies with **PEP 723** in CPython `conftest.py` (or `test_*.py`); RevitDevTool installs them before `tests/run`. IronPython `test_*_ipy.py` **does not** use PEP 723 — `ipytests/run` never installs packages.
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
# /// script
|
|
137
|
+
# dependencies = ["numpy>=2.0", "polars>=1.0"]
|
|
138
|
+
# ///
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Revit rollback fixture
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
@pytest.fixture
|
|
145
|
+
def revit_auto_rollback(revit_transaction_service):
|
|
146
|
+
revit_transaction_service.StartChanges()
|
|
147
|
+
try:
|
|
148
|
+
yield revit_transaction_service
|
|
149
|
+
finally:
|
|
150
|
+
revit_transaction_service.RevertChanges()
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## How it works
|
|
154
|
+
|
|
155
|
+
1. Local pytest collects tests.
|
|
156
|
+
2. Plugin connects to `DevTools_{Host}_{Version}_{PID}`.
|
|
157
|
+
3. Node IDs sent via JSON-RPC method `tests/run` (`BridgeMessage` length-prefixed frames).
|
|
158
|
+
4. Host runs `PytestRunner.py` embedded in RevitDevTool (`PytestExecutionService` on main thread).
|
|
159
|
+
5. Results and optional progress notifications return to the client.
|
|
160
|
+
6. Plugin maps `CaseResult` → standard pytest reports.
|
|
161
|
+
|
|
162
|
+
## Developing this repository
|
|
163
|
+
|
|
164
|
+
Clone and run integration tests against a live host:
|
|
165
|
+
|
|
166
|
+
```powershell
|
|
167
|
+
cd RevitDevTool.PyTest
|
|
168
|
+
uv run pytest -v # Revit suite (default)
|
|
169
|
+
uv run pytest tests/Revit/test_smoke.py -v
|
|
170
|
+
uv run pytest --host civil3d --host-version 2026 # after switching testpaths/host in pyproject.toml
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Layout
|
|
174
|
+
|
|
175
|
+
| Path | Purpose |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `src/revitdevtool_pytest/` | Plugin source (published wheel) |
|
|
178
|
+
| `tests/Revit/` | Revit integration tests + `schedule/` helpers |
|
|
179
|
+
| `tests/Civil3d/` | Civil 3D / AutoCAD API tests |
|
|
180
|
+
|
|
181
|
+
Revit suite settings in `pyproject.toml`: `testpaths = ["tests/Revit"]`, `pythonpath = ["tests/Revit"]` for local `schedule` imports.
|
|
182
|
+
|
|
183
|
+
Optional env: `REVIT_TEST_MODEL_PATH` — path to `.rvt` for `revit_doc` fixture (default `F:\Project1.rvt`).
|
|
184
|
+
|
|
185
|
+
## IDE integration
|
|
186
|
+
|
|
187
|
+
**VS Code / Cursor** — `python.testing.pytestEnabled: true`. Plugin detects `vscode_pytest` / `TEST_RUN_PIPE` and disables CLI streaming to avoid duplicate tree entries.
|
|
188
|
+
|
|
189
|
+
**PyCharm** — enable pytest as test runner.
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
[MIT](LICENSE)
|