Skip to content

Commit 0a2596b

Browse files
zedfmarioamotl
authored andcommitted
✨ Allowing pytest cli arguments for host and port
1 parent d49b766 commit 0a2596b

File tree

8 files changed

+48
-18
lines changed

8 files changed

+48
-18
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
/.ruff_cache
55
/.vagrant
66
/.venv*
7+
/.github
8+
/build
79

810
/dist
911

1012
.coverage*
1113
coverage.xml
1214
*.egg-info
1315
*.pyc
14-
__pycache__
16+
__pycache__

README.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ fixtures for ``pytest``. It has been conceived for the fine
4747
Capture MQTT messages, using the `Paho MQTT Python Client`_, in the spirit of
4848
``caplog`` and ``capsys``. It can also be used to publish MQTT messages.
4949

50+
MQTT server host and port are configurable via pytest cli arguments:
51+
``mqtt_host`` and ``mqtt_port`` (defaults to ``localhost`` and ``1883``)
52+
5053
``mosquitto`` fixture
5154
=====================
5255

@@ -105,9 +108,6 @@ The ``capmqtt_decode_utf8`` setting can be enabled in three ways.
105108
Issues
106109
******
107110

108-
- Both fixtures currently do not support changing the MQTT broker hostname and
109-
port number differently than ``localhost:1883``.
110-
111111
- The ``mosquitto`` fixture currently does not support either authentication or
112112
encryption.
113113

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ dependencies = [
6161
]
6262

6363
[project.entry-points.pytest11]
64+
mqttcliargs = "pytest_mqtt.mqttcliargs"
6465
capmqtt = "pytest_mqtt.capmqtt"
6566
mosquitto = "pytest_mqtt.mosquitto"
6667

pytest_mqtt/capmqtt.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727

2828

2929
class MqttClientAdapter(threading.Thread):
30-
def __init__(self, on_message_callback: t.Optional[t.Callable] = None):
30+
def __init__(self, on_message_callback: t.Optional[t.Callable] = None, host: str = "localhost", port: int = 1883):
3131
super().__init__()
3232
self.client: mqtt.Client = mqtt.Client()
3333
self.on_message_callback = on_message_callback
34+
self.host = host
35+
self.port = int(port)
3436
self.setup()
3537

3638
def setup(self):
@@ -43,7 +45,7 @@ def setup(self):
4345
client.on_message = self.on_message_callback
4446

4547
logger.debug("[PYTEST] Connecting to MQTT broker")
46-
client.connect("localhost", port=1883)
48+
client.connect(host=self.host, port=self.port)
4749
client.subscribe("#")
4850

4951
def run(self):
@@ -75,12 +77,12 @@ def publish(self, topic: str, payload: str, **kwargs) -> mqtt.MQTTMessageInfo:
7577
class MqttCaptureFixture:
7678
"""Provides access and control of log capturing."""
7779

78-
def __init__(self, decode_utf8: t.Optional[bool]) -> None:
80+
def __init__(self, decode_utf8: t.Optional[bool], host: str = "localhost", port: int = 1883) -> None:
7981
"""Creates a new funcarg."""
8082
self._buffer: t.List[MqttMessage] = []
8183
self._decode_utf8: bool = decode_utf8
8284

83-
self.mqtt_client = MqttClientAdapter(on_message_callback=self.on_message)
85+
self.mqtt_client = MqttClientAdapter(on_message_callback=self.on_message, host=host, port=port)
8486
self.mqtt_client.start()
8587
# time.sleep(0.1)
8688

@@ -119,20 +121,22 @@ def publish(self, topic: str, payload: str, **kwargs) -> mqtt.MQTTMessageInfo:
119121

120122

121123
@pytest.fixture(scope="function")
122-
def capmqtt(request):
124+
def capmqtt(request, mqttcliargs):
123125
"""Access and control MQTT messages."""
124126

125127
# Configure `capmqtt` fixture, obtaining the `capmqtt_decode_utf8` setting from
126128
# either a global or module-wide setting, or from a test case marker.
127129
# https://docs.pytest.org/en/7.1.x/how-to/fixtures.html#fixtures-can-introspect-the-requesting-test-context
128130
# https://docs.pytest.org/en/7.1.x/how-to/fixtures.html#using-markers-to-pass-data-to-fixtures
131+
132+
host, port = mqttcliargs
133+
129134
capmqtt_decode_utf8 = (
130135
getattr(request.config.option, "capmqtt_decode_utf8", False)
131136
or getattr(request.module, "capmqtt_decode_utf8", False)
132137
or request.node.get_closest_marker("capmqtt_decode_utf8") is not None
133138
)
134-
135-
result = MqttCaptureFixture(decode_utf8=capmqtt_decode_utf8)
139+
result = MqttCaptureFixture(decode_utf8=capmqtt_decode_utf8, host=host, port=port)
136140
delay()
137141
yield result
138142
result.finalize()

pytest_mqtt/mosquitto.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
23
# Copyright (c) 2020-2022 Andreas Motl <andreas.motl@panodata.org>
34
# Copyright (c) 2020-2022 Richard Pobering <richard.pobering@panodata.org>
45
#
@@ -36,7 +37,10 @@
3637
class Mosquitto(BaseImage):
3738

3839
name = "mosquitto"
39-
port = 1883
40+
41+
def __init__(self, host: str = "localhost", port: int = 1883) -> None:
42+
self.host = host
43+
self.port = port
4044

4145
def check(self):
4246
# TODO: Add real implementation.
@@ -71,16 +75,18 @@ def run(self):
7175
mosquitto_image = Mosquitto()
7276

7377

74-
def is_mosquitto_running() -> bool:
75-
return probe_tcp_connect("localhost", 1883)
78+
def is_mosquitto_running(host: str, port: int) -> bool:
79+
return probe_tcp_connect(host, port)
7680

7781

7882
@pytest.fixture(scope="session")
79-
def mosquitto():
83+
def mosquitto(request, mqttcliargs):
84+
85+
host, port = mqttcliargs
8086

8187
# Gracefully skip spinning up the Docker container if Mosquitto is already running.
82-
if is_mosquitto_running():
83-
yield "localhost", 1883
88+
if is_mosquitto_running(host, port):
89+
yield host, port
8490
return
8591

8692
# Spin up Mosquitto container.

pytest_mqtt/mqttcliargs.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import typing as t
2+
3+
import pytest
4+
5+
6+
@pytest.fixture(scope="session")
7+
def mqttcliargs(request) -> t.Tuple[str, int]:
8+
host = request.config.getoption("--mqtt_host", "localhost")
9+
port = int(request.config.getoption("--mqtt_port", 1883))
10+
yield host, port

testing/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def pytest_addoption(parser) -> None:
2+
parser.addoption("--mqtt_host", action="store", default="localhost", help="mqtt host to be connected through")
3+
parser.addoption("--mqtt_port", action="store", default=1883, help="mqtt port to be connected through")

testing/test_capmqtt.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33

44

55
def test_mqtt_client_adapter(mosquitto):
6-
mqtt_client = MqttClientAdapter()
6+
host, port = mosquitto
7+
mqtt_client = MqttClientAdapter(host=host, port=port)
78
mqtt_client.start()
89

10+
assert mqtt_client.client._host == host
11+
assert mqtt_client.client._port == int(port)
12+
913
# Submit MQTT message.
1014
message_info = mqtt_client.publish("foo", "bar")
1115
message_info.wait_for_publish(timeout=0.5)

0 commit comments

Comments
 (0)