🚧 WIP
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"""Tests for the frozen-exe build script + frozen-aware config default.
|
||||
|
||||
The PyInstaller run itself is Windows-only and slow; these tests cover the
|
||||
pure logic the build script and the CLI rely on. The build script is
|
||||
PowerShell (``scripts/build_exe.ps1``); the tests assert on its content and
|
||||
on the CLI behaviors the produced exe depends on.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from opcda_diagnozer.main import DEFAULT_CONFIG, _default_config_path
|
||||
|
||||
BUILD_SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "build_exe.ps1"
|
||||
|
||||
|
||||
def test_default_config_path_in_source_mode() -> None:
|
||||
"""Not frozen: the default stays the plain relative name (CWD lookup)."""
|
||||
with mock.patch.object(sys, "frozen", False, create=True):
|
||||
assert _default_config_path() == DEFAULT_CONFIG
|
||||
|
||||
|
||||
def test_default_config_path_when_frozen_resolves_next_to_exe(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Frozen: config.yaml lives next to the exe — never the service CWD (System32)."""
|
||||
exe_dir = tmp_path / "Program Files" / "OPCDA-Diagnozer"
|
||||
exe_dir.mkdir(parents=True)
|
||||
exe = exe_dir / "opcda-diagnozer.exe"
|
||||
exe.touch()
|
||||
monkeypatch.setattr(sys, "frozen", True, raising=False)
|
||||
monkeypatch.setattr(sys, "executable", str(exe))
|
||||
assert _default_config_path() == str(exe_dir / DEFAULT_CONFIG)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "win32", reason="the exe is Windows-only")
|
||||
class TestBuildScript:
|
||||
"""Static assertions on scripts/build_exe.ps1 (no PyInstaller invocation)."""
|
||||
|
||||
def test_hidden_imports_cover_lazy_modules(self) -> None:
|
||||
"""Every lazy import in the package must be declared to PyInstaller."""
|
||||
content = BUILD_SCRIPT.read_text(encoding="utf-8")
|
||||
# the deferred COM imports (opc/automation.py, opc/discovery.py)
|
||||
assert "'pythoncom'" in content
|
||||
assert "'win32com.client'" in content
|
||||
assert "'opcda_diagnozer.opc.automation'" in content
|
||||
# the lazily-imported browse module (main.py verbs)
|
||||
assert "'opcda_diagnozer.opc.browse'" in content
|
||||
# the Phase 3 service host stays in the bundle from day one
|
||||
assert "'opcda_diagnozer.service'" in content
|
||||
|
||||
def test_version_info_template_uses_pyi_keywords(self) -> None:
|
||||
"""The embedded version-info must use PyInstaller's exact keyword names.
|
||||
|
||||
FixedFileInfo.__init__ takes filevers/prodvers/mask/flags/OS/fileType/
|
||||
subtype/date — anything else (fileVers, fileDate, subType) raises a
|
||||
TypeError inside PyInstaller's eval at build time.
|
||||
"""
|
||||
content = BUILD_SCRIPT.read_text(encoding="utf-8")
|
||||
assert "filevers=(" in content
|
||||
assert "fileType=0x1" in content
|
||||
assert "subtype=0x0" in content
|
||||
assert "date=(0, 0)" in content
|
||||
# the rejected spellings must NOT appear
|
||||
assert "fileVers=" not in content
|
||||
assert "fileDate=" not in content
|
||||
assert "subType=" not in content
|
||||
|
||||
def test_bitness_guards_present(self) -> None:
|
||||
"""The script must refuse a 64-bit interpreter and verify the PE."""
|
||||
content = BUILD_SCRIPT.read_text(encoding="utf-8")
|
||||
assert "struct.calcsize('P') * 8" in content # interpreter bitness check
|
||||
assert "0x14C" in content # PE machine = IMAGE_FILE_MACHINE_I386 check
|
||||
Reference in New Issue
Block a user