Skip to content

Commit 43f8021

Browse files
committed
tests(engine): parameterize server fixtures by engine option/marker
1 parent b718be3 commit 43f8021

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

conftest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,36 @@ def setup_session(
7373
"""Session-level test configuration for pytest."""
7474
if USING_ZSH:
7575
request.getfixturevalue("zshrc")
76+
77+
78+
def pytest_addoption(parser: pytest.Parser) -> None:
79+
"""Add CLI options for selecting tmux engine."""
80+
parser.addoption(
81+
"--engine",
82+
action="store",
83+
default="subprocess",
84+
choices=["subprocess", "control"],
85+
help="Select tmux engine for fixtures (default: subprocess).",
86+
)
87+
88+
89+
def pytest_configure(config: pytest.Config) -> None:
90+
"""Register custom markers."""
91+
config.addinivalue_line(
92+
"markers",
93+
(
94+
"engines(names): run the test once for each engine in 'names' "
95+
"(e.g. ['control', 'subprocess'])."
96+
),
97+
)
98+
99+
100+
def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
101+
"""Parametrize engine_name when requested by tests."""
102+
if "engine_name" in metafunc.fixturenames:
103+
marker = metafunc.definition.get_closest_marker("engines")
104+
if marker:
105+
params = list(marker.args[0])
106+
else:
107+
params = [metafunc.config.getoption("--engine")]
108+
metafunc.parametrize("engine_name", params, indirect=True)

docs/pytest-plugin/index.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,31 @@ def set_home(
137137
monkeypatch.setenv("HOME", str(user_path))
138138
```
139139

140+
## Selecting tmux engines (experimental)
141+
142+
Fixtures can run against different execution engines. By default the
143+
`subprocess` engine is used. You can choose control mode globally:
144+
145+
```console
146+
$ pytest --engine=control
147+
```
148+
149+
Or per-test via the `engines` marker (uses parametrization) and the `engine_name`
150+
fixture:
151+
152+
```python
153+
import pytest
154+
155+
@pytest.mark.engines(["subprocess", "control"])
156+
def test_my_flow(server, engine_name):
157+
# server uses the selected engine, engine_name reflects the current one
158+
assert engine_name in {"subprocess", "control"}
159+
assert server.is_alive()
160+
```
161+
162+
`TestServer` also respects the selected engine. Control mode is experimental and
163+
its APIs may change between releases.
164+
140165
## Fixtures
141166

142167
```{eval-rst}

src/libtmux/pytest_plugin.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import pytest
1313

1414
from libtmux import exc
15+
from libtmux._internal.engines.base import Engine
16+
from libtmux._internal.engines.control_mode import ControlModeEngine
17+
from libtmux._internal.engines.subprocess_engine import SubprocessEngine
1518
from libtmux.server import Server
1619
from libtmux.test.constants import TEST_SESSION_PREFIX
1720
from libtmux.test.random import get_test_session_name, namer
@@ -115,6 +118,7 @@ def server(
115118
request: pytest.FixtureRequest,
116119
monkeypatch: pytest.MonkeyPatch,
117120
config_file: pathlib.Path,
121+
engine_name: str,
118122
) -> Server:
119123
"""Return new, temporary :class:`libtmux.Server`.
120124
@@ -141,7 +145,10 @@ def server(
141145
142146
>>> result.assert_outcomes(passed=1)
143147
"""
144-
server = Server(socket_name=f"libtmux_test{next(namer)}")
148+
server = Server(
149+
socket_name=f"libtmux_test{next(namer)}",
150+
engine=_build_engine(engine_name),
151+
)
145152

146153
def fin() -> None:
147154
server.kill()
@@ -311,5 +318,26 @@ def fin() -> None:
311318
Server,
312319
on_init=on_init,
313320
socket_name_factory=socket_name_factory,
321+
engine=_build_engine(request.getfixturevalue("engine_name")),
314322
),
315323
)
324+
325+
326+
@pytest.fixture
327+
def engine_name(request: pytest.FixtureRequest) -> str:
328+
"""Engine selector fixture, driven by CLI or parametrization."""
329+
if hasattr(request, "param"):
330+
return t.cast(str, request.param)
331+
try:
332+
return t.cast(str, request.config.getoption("--engine"))
333+
except ValueError:
334+
# Option may not be registered when libtmux is used purely as a plugin
335+
# dependency in downstream projects. Default to subprocess for safety.
336+
return "subprocess"
337+
338+
339+
def _build_engine(engine_name: str) -> Engine:
340+
"""Return engine instance by name."""
341+
if engine_name == "control":
342+
return ControlModeEngine()
343+
return SubprocessEngine()

0 commit comments

Comments
 (0)