From d24a52c54cdb3b7a49c5b4d339bb86059d6ef735 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Wed, 25 Mar 2026 15:16:17 +0100 Subject: [PATCH] Simplify tests --- tests/base/__init__.py | 1 - tests/base/graphical_test_base.py | 48 ------------- tests/test_graphical_camera_settings.py | 42 +---------- tests/test_graphical_custom_keyboard.py | 71 +------------------ tests/test_graphical_imu_calibration.py | 34 --------- .../test_graphical_imu_calibration_ui_bug.py | 7 -- tests/test_graphical_keyboard_styling.py | 29 +------- tests/test_graphical_osupdate.py | 68 +----------------- 8 files changed, 10 insertions(+), 290 deletions(-) diff --git a/tests/base/__init__.py b/tests/base/__init__.py index f83aed8e..0d7c5b19 100644 --- a/tests/base/__init__.py +++ b/tests/base/__init__.py @@ -11,7 +11,6 @@ Usage: class TestMyApp(GraphicalTestBase): def test_something(self): # self.screen is already set up - # self.screenshot_dir is configured pass """ diff --git a/tests/base/graphical_test_base.py b/tests/base/graphical_test_base.py index cac2993a..b2497060 100644 --- a/tests/base/graphical_test_base.py +++ b/tests/base/graphical_test_base.py @@ -4,7 +4,6 @@ Base class for graphical tests in MicroPythonOS. This class provides common setup/teardown patterns for tests that require LVGL/UI initialization. It handles: - Screen creation and cleanup -- Screenshot directory configuration - Common UI testing utilities Usage: @@ -13,17 +12,13 @@ Usage: class TestMyApp(GraphicalTestBase): def test_something(self): # self.screen is already set up (320x240) - # self.screenshot_dir is configured label = lv.label(self.screen) label.set_text("Hello") self.wait_for_render() - self.capture_screenshot("my_test") """ import unittest import lvgl as lv -import sys -import os class GraphicalTestBase(unittest.TestCase): @@ -42,33 +37,12 @@ class GraphicalTestBase(unittest.TestCase): Instance Attributes: screen: The LVGL screen object for the test - screenshot_dir: Path to the screenshots directory """ SCREEN_WIDTH = 320 SCREEN_HEIGHT = 240 DEFAULT_RENDER_ITERATIONS = 5 - @classmethod - def setUpClass(cls): - """ - Set up class-level fixtures. - - Configures the screenshot directory based on platform. - """ - # Determine screenshot directory based on platform - if sys.platform == "esp32": - cls.screenshot_dir = "tests/screenshots" - else: - # On desktop, tests directory is in parent - cls.screenshot_dir = "../tests/screenshots" - - # Ensure screenshots directory exists - try: - os.mkdir(cls.screenshot_dir) - except OSError: - pass # Directory already exists - def setUp(self): """ Set up test fixtures before each test method. @@ -103,28 +77,6 @@ class GraphicalTestBase(unittest.TestCase): iterations = self.DEFAULT_RENDER_ITERATIONS wait_for_render(iterations) - def capture_screenshot(self, name, width=None, height=None): - """ - Capture a screenshot with standardized naming. - - Args: - name: Name for the screenshot (without extension) - width: Screenshot width (default: SCREEN_WIDTH) - height: Screenshot height (default: SCREEN_HEIGHT) - - Returns: - bytes: The screenshot buffer - """ - from mpos import capture_screenshot - - if width is None: - width = self.SCREEN_WIDTH - if height is None: - height = self.SCREEN_HEIGHT - - path = f"{self.screenshot_dir}/{name}.raw" - return capture_screenshot(path, width=width, height=height) - def find_label_with_text(self, text, parent=None): """ Find a label containing the specified text. diff --git a/tests/test_graphical_camera_settings.py b/tests/test_graphical_camera_settings.py index 08c404f5..3f44e373 100644 --- a/tests/test_graphical_camera_settings.py +++ b/tests/test_graphical_camera_settings.py @@ -20,11 +20,9 @@ Usage: import unittest import lvgl as lv import mpos.ui -import os import sys from mpos import ( wait_for_render, - capture_screenshot, find_label_with_text, find_button_with_text, verify_text_present, @@ -51,19 +49,6 @@ class TestGraphicalCameraSettings(unittest.TestCase): except: self.skipTest("No camera module available (webcam or internal)") - # Get absolute path to screenshots directory - import sys - if sys.platform == "esp32": - self.screenshot_dir = "tests/screenshots" - else: - self.screenshot_dir = "../tests/screenshots" - - # Ensure screenshots directory exists - try: - os.mkdir(self.screenshot_dir) - except OSError: - pass # Directory already exists - def tearDown(self): """Clean up after each test method.""" # Navigate back to launcher (closes the camera app) @@ -109,10 +94,9 @@ class TestGraphicalCameraSettings(unittest.TestCase): Steps: 1. Start camera app 2. Wait for camera to initialize - 3. Capture initial screenshot - 4. Click settings button (found dynamically by lv.SYMBOL.SETTINGS) - 5. Verify settings dialog opened - 6. If we get here without crash, test passes + 3. Click settings button (found dynamically by lv.SYMBOL.SETTINGS) + 4. Verify settings dialog opened + 5. If we get here without crash, test passes """ print("\n=== Testing settings button click (no crash) ===") @@ -130,11 +114,6 @@ class TestGraphicalCameraSettings(unittest.TestCase): print("\nInitial screen labels:") print_screen_labels(screen) - # Capture screenshot before clicking settings - screenshot_path = f"{self.screenshot_dir}/camera_before_settings.raw" - print(f"\nCapturing initial screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - # Find and click settings button dynamically found = self._find_and_click_settings_button(screen) self.assertTrue(found, "Settings button with lv.SYMBOL.SETTINGS not found on screen") @@ -171,11 +150,6 @@ class TestGraphicalCameraSettings(unittest.TestCase): "Settings screen did not open (no Save/Cancel buttons or expected UI elements found)" ) - # Capture screenshot of settings dialog - screenshot_path = f"{self.screenshot_dir}/camera_settings_dialog.raw" - print(f"\nCapturing settings dialog screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - # If we got here without segfault, the test passes! print("\n✓ Settings button clicked successfully without crash!") @@ -296,11 +270,6 @@ class TestGraphicalCameraSettings(unittest.TestCase): wait_for_render(iterations=15) - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/camera_dropdown_open.raw" - print(f"Capturing dropdown screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - screen = lv.screen_active() print("\nScreen after dropdown interaction:") print_screen_labels(screen) @@ -319,11 +288,6 @@ class TestGraphicalCameraSettings(unittest.TestCase): print("\nWaiting for reconfiguration...") wait_for_render(iterations=30) - # Capture screenshot after reconfiguration - screenshot_path = f"{self.screenshot_dir}/camera_after_resolution_change.raw" - print(f"Capturing post-change screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - # If we got here without segfault, the test passes! print("\n✓ Resolution changed successfully without crash!") diff --git a/tests/test_graphical_custom_keyboard.py b/tests/test_graphical_custom_keyboard.py index 872d2439..3ccf329d 100644 --- a/tests/test_graphical_custom_keyboard.py +++ b/tests/test_graphical_custom_keyboard.py @@ -2,7 +2,7 @@ Graphical tests for MposKeyboard. Tests keyboard visual appearance, text input via simulated button presses, -and mode switching. Captures screenshots for regression testing. +and mode switching. Usage: Desktop: ./tests/unittest.sh tests/test_graphical_custom_keyboard.py @@ -11,9 +11,7 @@ Usage: import unittest import lvgl as lv -import sys -import os -from mpos import MposKeyboard, wait_for_render, capture_screenshot, AppearanceManager +from mpos import MposKeyboard, wait_for_render, AppearanceManager class TestGraphicalMposKeyboard(unittest.TestCase): @@ -21,20 +19,7 @@ class TestGraphicalMposKeyboard(unittest.TestCase): def setUp(self): """Set up test fixtures before each test method.""" - # Determine screenshot directory - if sys.platform == "esp32": - self.screenshot_dir = "tests/screenshots" - else: - self.screenshot_dir = "../tests/screenshots" - - # Ensure screenshots directory exists - try: - os.mkdir(self.screenshot_dir) - except OSError: - pass # Directory already exists - print(f"\n=== Graphical Keyboard Test Setup ===") - print(f"Platform: {sys.platform}") def tearDown(self): """Clean up after each test method.""" @@ -102,7 +87,7 @@ class TestGraphicalMposKeyboard(unittest.TestCase): """ Test keyboard appearance in lowercase mode. - Verifies that the keyboard renders correctly and captures screenshot. + Verifies that the keyboard renders correctly. """ print("\n=== Testing lowercase keyboard appearance ===") @@ -112,16 +97,6 @@ class TestGraphicalMposKeyboard(unittest.TestCase): keyboard.set_mode(MposKeyboard.MODE_LOWERCASE) wait_for_render(10) - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/custom_keyboard_lowercase.raw" - print(f"Capturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - - # Verify screenshot was created - stat = os.stat(screenshot_path) - self.assertTrue(stat[6] > 0, "Screenshot file is empty") - print(f"Screenshot captured: {stat[6]} bytes") - print("=== Lowercase appearance test PASSED ===") def test_keyboard_uppercase_appearance(self): @@ -134,16 +109,6 @@ class TestGraphicalMposKeyboard(unittest.TestCase): keyboard.set_mode(MposKeyboard.MODE_UPPERCASE) wait_for_render(10) - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/custom_keyboard_uppercase.raw" - print(f"Capturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - - # Verify screenshot was created - stat = os.stat(screenshot_path) - self.assertTrue(stat[6] > 0, "Screenshot file is empty") - print(f"Screenshot captured: {stat[6]} bytes") - print("=== Uppercase appearance test PASSED ===") def test_keyboard_numbers_appearance(self): @@ -156,16 +121,6 @@ class TestGraphicalMposKeyboard(unittest.TestCase): keyboard.set_mode(MposKeyboard.MODE_NUMBERS) wait_for_render(10) - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/custom_keyboard_numbers.raw" - print(f"Capturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - - # Verify screenshot was created - stat = os.stat(screenshot_path) - self.assertTrue(stat[6] > 0, "Screenshot file is empty") - print(f"Screenshot captured: {stat[6]} bytes") - print("=== Numbers appearance test PASSED ===") def test_keyboard_specials_appearance(self): @@ -178,16 +133,6 @@ class TestGraphicalMposKeyboard(unittest.TestCase): keyboard.set_mode(MposKeyboard.MODE_SPECIALS) wait_for_render(10) - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/custom_keyboard_specials.raw" - print(f"Capturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - - # Verify screenshot was created - stat = os.stat(screenshot_path) - self.assertTrue(stat[6] > 0, "Screenshot file is empty") - print(f"Screenshot captured: {stat[6]} bytes") - print("=== Specials appearance test PASSED ===") def test_keyboard_visibility_light_mode(self): @@ -275,11 +220,6 @@ class TestGraphicalMposKeyboard(unittest.TestCase): lv.screen_load(screen) wait_for_render(20) - # Capture standard keyboard - screenshot_path = f"{self.screenshot_dir}/keyboard_standard_comparison.raw" - print(f"Capturing standard keyboard: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - # Clean up lv.screen_load(lv.obj()) wait_for_render(5) @@ -301,11 +241,6 @@ class TestGraphicalMposKeyboard(unittest.TestCase): lv.screen_load(screen2) wait_for_render(20) - # Capture custom keyboard - screenshot_path = f"{self.screenshot_dir}/keyboard_custom_comparison.raw" - print(f"Capturing custom keyboard: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - print("=== Comparison test PASSED ===") diff --git a/tests/test_graphical_imu_calibration.py b/tests/test_graphical_imu_calibration.py index 4c20b1ae..204ddf63 100644 --- a/tests/test_graphical_imu_calibration.py +++ b/tests/test_graphical_imu_calibration.py @@ -12,12 +12,9 @@ Usage: import unittest import lvgl as lv import mpos.ui -import os -import sys import time from mpos import ( wait_for_render, - capture_screenshot, find_label_with_text, verify_text_present, print_screen_labels, @@ -34,20 +31,6 @@ from mpos import ( class TestIMUCalibration(unittest.TestCase): """Test suite for IMU calibration activities.""" - def setUp(self): - """Set up test fixtures.""" - # Get screenshot directory - if sys.platform == "esp32": - self.screenshot_dir = "tests/screenshots" - else: - self.screenshot_dir = "../tests/screenshots" # it runs from internal_filesystem/ - - # Ensure directory exists - try: - os.mkdir(self.screenshot_dir) - except OSError: - pass - def tearDown(self): """Clean up after test.""" # Navigate back to launcher @@ -82,15 +65,6 @@ class TestIMUCalibration(unittest.TestCase): self.assertTrue(verify_text_present(screen, "Accel."), "Accel. label not found") self.assertTrue(verify_text_present(screen, "Gyro"), "Gyro label not found") - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/check_imu_calibration.raw" - print(f"Capturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path) - - # Verify screenshot saved - stat = os.stat(screenshot_path) - self.assertTrue(stat[6] > 0, "Screenshot file is empty") - print("=== CheckIMUCalibrationActivity test complete ===") def test_calibrate_activity_flow(self): @@ -118,10 +92,6 @@ class TestIMUCalibration(unittest.TestCase): self.assertTrue(verify_text_present(screen, "Place device on flat"), "Instructions not shown") - # Capture initial state - screenshot_path = f"{self.screenshot_dir}/calibrate_imu_01_initial.raw" - capture_screenshot(screenshot_path) - # Click "Calibrate Now" button to start calibration calibrate_btn = find_button_with_text(screen, "Calibrate Now") self.assertIsNotNone(calibrate_btn, "Could not find 'Calibrate Now' button") @@ -144,10 +114,6 @@ class TestIMUCalibration(unittest.TestCase): verify_text_present(screen, "offsets"), "Calibration offsets not shown") - # Capture completion state - screenshot_path = f"{self.screenshot_dir}/calibrate_imu_02_complete.raw" - capture_screenshot(screenshot_path) - print("=== CalibrateIMUActivity flow test complete ===") def test_navigation_from_check_to_calibrate(self): diff --git a/tests/test_graphical_imu_calibration_ui_bug.py b/tests/test_graphical_imu_calibration_ui_bug.py index 88a90e42..ec44511f 100644 --- a/tests/test_graphical_imu_calibration_ui_bug.py +++ b/tests/test_graphical_imu_calibration_ui_bug.py @@ -23,7 +23,6 @@ from mpos import ( find_label_with_text, get_widget_coords, print_screen_labels, - capture_screenshot, click_label, click_button, find_text_on_screen, @@ -85,9 +84,6 @@ class TestIMUCalibrationUI(unittest.TestCase): print_screen_labels(lv.screen_active()) print() - # Capture screenshot before - capture_screenshot("../tests/screenshots/check_imu_before_calib.raw") - # Look for actual values (not "--") has_values_before = False widgets = [] @@ -154,9 +150,6 @@ class TestIMUCalibrationUI(unittest.TestCase): print_screen_labels(lv.screen_active()) print() - # Capture screenshot after - capture_screenshot("../tests/screenshots/check_imu_after_calib.raw") - # Look for actual values (not "--") has_values_after = False for widget in get_all_widgets_with_text(lv.screen_active()): diff --git a/tests/test_graphical_keyboard_styling.py b/tests/test_graphical_keyboard_styling.py index 54d8f0ed..a895eb1e 100644 --- a/tests/test_graphical_keyboard_styling.py +++ b/tests/test_graphical_keyboard_styling.py @@ -5,9 +5,8 @@ This test verifies that keyboard buttons have proper visible contrast in both light and dark modes. It checks for the bug where keyboard buttons appear white-on-white in light mode on ESP32. -The test uses two approaches: -1. Programmatic: Query LVGL style properties to verify button background colors -2. Visual: Capture screenshots for manual verification and regression testing +The test uses a programmatic approach: Query LVGL style properties to verify +button background colors. This test should INITIALLY FAIL, demonstrating the bug before the fix is applied. @@ -21,10 +20,8 @@ import lvgl as lv import mpos.ui import mpos.config import sys -import os from mpos import ( wait_for_render, - capture_screenshot, AppearanceManager, ) @@ -34,18 +31,6 @@ class TestKeyboardStyling(unittest.TestCase): def setUp(self): """Set up test fixtures before each test method.""" - # Determine screenshot directory - if sys.platform == "esp32": - self.screenshot_dir = "tests/screenshots" - else: - self.screenshot_dir = "../tests/screenshots" - - # Ensure screenshots directory exists - try: - os.mkdir(self.screenshot_dir) - except OSError: - pass # Directory already exists - # Save current theme setting prefs = mpos.config.SharedPreferences("theme_settings") self.original_theme = prefs.get_string("theme_light_dark", "light") @@ -243,11 +228,6 @@ class TestKeyboardStyling(unittest.TestCase): print(f" Screen background: {screen_bg}") print(f" Button background: {button_bg}") - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/keyboard_light_mode.raw" - print(f"\nCapturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - # Verify contrast print("\nChecking button/screen contrast...") has_contrast = self._color_contrast_sufficient(button_bg, screen_bg, min_difference=20) @@ -297,11 +277,6 @@ class TestKeyboardStyling(unittest.TestCase): print(f" Screen background: {screen_bg}") print(f" Button background: {button_bg}") - # Capture screenshot - screenshot_path = f"{self.screenshot_dir}/keyboard_dark_mode.raw" - print(f"\nCapturing screenshot: {screenshot_path}") - capture_screenshot(screenshot_path, width=320, height=240) - # Verify contrast print("\nChecking button/screen contrast...") has_contrast = self._color_contrast_sufficient(button_bg, screen_bg, min_difference=20) diff --git a/tests/test_graphical_osupdate.py b/tests/test_graphical_osupdate.py index 7011fd71..f489e1f1 100644 --- a/tests/test_graphical_osupdate.py +++ b/tests/test_graphical_osupdate.py @@ -1,18 +1,13 @@ import unittest import lvgl as lv import mpos -import time -import sys -import os # Import graphical test helper from mpos import ( wait_for_render, - capture_screenshot, find_label_with_text, verify_text_present, print_screen_labels, - DeviceInfo, BuildInfo, AppManager ) @@ -107,8 +102,8 @@ class TestOSUpdateGraphicalUI(unittest.TestCase): verify_text_present(screen, "WiFi") self.assertTrue(checking_found, "Should show some status message") - def test_screenshot_initial_state(self): - """Capture screenshot of initial app state.""" + def test_initial_state_labels(self): + """Print initial app labels for debugging.""" result = AppManager.start_app("com.micropythonos.osupdate") self.assertTrue(result) wait_for_render(20) @@ -122,19 +117,6 @@ class TestOSUpdateGraphicalUI(unittest.TestCase): class TestOSUpdateGraphicalStatusMessages(unittest.TestCase): """Graphical tests for OSUpdate status messages.""" - def setUp(self): - """Set up test fixtures.""" - self.hardware_id = DeviceInfo.hardware_id - self.screenshot_dir = "tests/screenshots" - - try: - os.stat(self.screenshot_dir) - except OSError: - try: - os.mkdir(self.screenshot_dir) - except OSError: - pass - def tearDown(self): """Clean up after test.""" mpos.ui.back_screen() @@ -176,49 +158,3 @@ class TestOSUpdateGraphicalStatusMessages(unittest.TestCase): self.assertTrue(version_found, "Version label should be present and readable") -class TestOSUpdateGraphicalScreenshots(unittest.TestCase): - """Screenshot tests for visual regression testing.""" - - def setUp(self): - """Set up test fixtures.""" - self.hardware_id = DeviceInfo.hardware_id - self.screenshot_dir = "tests/screenshots" - - try: - os.stat(self.screenshot_dir) - except OSError: - try: - os.mkdir(self.screenshot_dir) - except OSError: - pass - - def tearDown(self): - """Clean up after test.""" - mpos.ui.back_screen() - wait_for_render(5) - - def test_capture_main_screen(self): - """Capture screenshot of main OSUpdate screen.""" - result = AppManager.start_app("com.micropythonos.osupdate") - self.assertTrue(result) - wait_for_render(20) - - - def test_capture_with_labels_visible(self): - """Capture screenshot ensuring all text is visible.""" - result = AppManager.start_app("com.micropythonos.osupdate") - self.assertTrue(result) - wait_for_render(20) - - screen = lv.screen_active() - - # Verify key elements are visible before screenshot (case insensitive) - has_version = verify_text_present(screen, "Installed") or verify_text_present(screen, "version") - # Button text can be "Update OS", "Reinstall\nsame version", or "Install\nolder version" - has_button = verify_text_present(screen, "Update") or verify_text_present(screen, "update") or \ - verify_text_present(screen, "Reinstall") or verify_text_present(screen, "Install") - - self.assertTrue(has_version, "Version label should be visible") - self.assertTrue(has_button, "Update button should be visible") - -