diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..f9953a2 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,7 @@ +import sys +from pathlib import Path + +# Ensure repo root is on sys.path so that protocol/ and ocf/ can be imported +repo_root = Path(__file__).resolve().parent.parent +if str(repo_root) not in sys.path: + sys.path.insert(0, str(repo_root)) diff --git a/tests/test_import_isolation.py b/tests/test_import_isolation.py new file mode 100644 index 0000000..735ed95 --- /dev/null +++ b/tests/test_import_isolation.py @@ -0,0 +1,37 @@ +"""protocol/ and ocf/ must be vendorable on their own — no dependency +on mqtt_demo/. This copies just those two directories into an empty +temp dir and imports every module in them there, so a stray +`from mqtt_demo... import ...` fails loudly instead of silently +passing because mqtt_demo/ happens to also be on sys.path in-repo.""" +import shutil +import subprocess +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parent.parent + + +def test_protocol_and_ocf_import_without_mqtt_demo_present(tmp_path): + for pkg in ('protocol', 'ocf'): + shutil.copytree(REPO_ROOT / pkg, tmp_path / pkg) + + import_lines = [ + "import protocol.coap", + "import protocol.dtls_session", + "import ocf.state_cache", + "import ocf.poll_scheduler", + "import ocf.keepalive", + "import ocf.observe_refresh", + ] + script = "\n".join(import_lines) + "\nprint('OK')\n" + + result = subprocess.run( + [sys.executable, "-c", script], + cwd=str(tmp_path), + capture_output=True, text=True, + ) + assert result.returncode == 0, ( + f"protocol/ocf failed to import without mqtt_demo/ present:\n" + f"stdout: {result.stdout}\nstderr: {result.stderr}" + ) + assert "OK" in result.stdout