Skip to content

Commit b3068d6

Browse files
Merge pull request #19 from prathameshnium/prathameshnium-patch-1
Create test_auto_discovery.py
2 parents d182c71 + 28b2ecc commit b3068d6

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

tests/test_auto_discovery.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import unittest
2+
import sys
3+
import os
4+
import importlib.util
5+
from unittest.mock import MagicMock, patch
6+
7+
# -------------------------------------------------------------------------
8+
# GLOBAL HEADLESS MOCKS
9+
# We mock everything before we even look for files.
10+
# -------------------------------------------------------------------------
11+
MOCK_MODULES = [
12+
'tkinter', 'tkinter.ttk', 'tkinter.messagebox', 'tkinter.filedialog',
13+
'tkinter.scrolledtext', 'tkinter.font', 'tkinter.Canvas',
14+
'pyvisa', 'pyvisa.errors', 'pyvisa.resources',
15+
'pymeasure', 'pymeasure.instruments', 'pymeasure.instruments.keithley',
16+
'matplotlib', 'matplotlib.pyplot', 'matplotlib.backends',
17+
'matplotlib.backends.backend_tkagg', 'matplotlib.figure',
18+
'PIL', 'PIL.Image', 'PIL.ImageTk',
19+
'pandas', 'numpy', 'gpib_ctypes'
20+
]
21+
22+
for mod in MOCK_MODULES:
23+
sys.modules[mod] = MagicMock()
24+
25+
class TestDynamicDiscovery(unittest.TestCase):
26+
27+
def setUp(self):
28+
# Point to the root directory of the repo
29+
self.root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
30+
31+
def load_module_from_path(self, file_path):
32+
"""
33+
Dynamically loads a Python file as a module given its path.
34+
This effectively 'runs' the top-level code (imports, class definitions).
35+
"""
36+
spec = importlib.util.spec_from_file_location("dynamic_module", file_path)
37+
if spec and spec.loader:
38+
module = importlib.util.module_from_spec(spec)
39+
sys.modules["dynamic_module"] = module
40+
spec.loader.exec_module(module)
41+
return module
42+
return None
43+
44+
def test_all_frontends_and_launchers(self):
45+
"""
46+
Walks through the entire repository.
47+
If a file looks like a GUI script, try to import it.
48+
"""
49+
print("\n[AUTO-DISCOVERY] Scanning repository for GUI modules...")
50+
51+
found_count = 0
52+
failure_count = 0
53+
54+
# Walk through all folders starting from root
55+
for root, dirs, files in os.walk(self.root_dir):
56+
57+
# Skip the 'tests', 'Setup', and hidden folders
58+
if "tests" in root or "Setup" in root or ".__" in root:
59+
continue
60+
61+
for file in files:
62+
# DEFINITION OF A GUI MODULE:
63+
# 1. Ends with .py
64+
# 2. Contains 'Frontend' OR starts with 'PICA_v' (your launcher)
65+
if file.endswith(".py") and ("Frontend" in file or file.startswith("PICA_v")):
66+
67+
full_path = os.path.join(root, file)
68+
rel_path = os.path.relpath(full_path, self.root_dir)
69+
70+
print(f" -> Testing: {rel_path}", end=" ... ")
71+
72+
try:
73+
# Try to load it
74+
self.load_module_from_path(full_path)
75+
print("OK")
76+
found_count += 1
77+
except Exception as e:
78+
print(f"FAIL\n Error: {e}")
79+
failure_count += 1
80+
# We don't fail immediately so we can see all errors
81+
# But we record it to fail the test at the end
82+
83+
print(f"\n[SUMMARY] Tested {found_count} modules. Failed {failure_count}.")
84+
85+
# Fail the test if anything broke
86+
self.assertEqual(failure_count, 0, f"{failure_count} modules failed to load.")
87+
88+
if __name__ == '__main__':
89+
unittest.main()

0 commit comments

Comments
 (0)