Add more tests

This commit is contained in:
Thomas Farstrike
2025-11-18 15:09:12 +01:00
parent 5827d40091
commit b6869d592a
4 changed files with 268 additions and 1 deletions
@@ -0,0 +1,24 @@
{
"name": "ErrorTest",
"publisher": "MicroPythonOS",
"short_description": "Test app with intentional error",
"long_description": "This app has an intentional import error for testing.",
"icon_url": "https://apps.micropythonos.com/apps/com.micropythonos.errortest/icons/com.micropythonos.errortest_0.0.1_64x64.png",
"download_url": "https://apps.micropythonos.com/apps/com.micropythonos.errortest/mpks/com.micropythonos.errortest_0.0.1.mpk",
"fullname": "com.micropythonos.errortest",
"version": "0.0.1",
"category": "development",
"activities": [
{
"entrypoint": "assets/error.py",
"classname": "Error",
"intent_filters": [
{
"action": "main",
"category": "launcher"
}
]
}
]
}
@@ -0,0 +1,10 @@
from mpos.apps import ActivityDoesntExist # should fail here
class Error(Activity):
def onCreate(self):
screen = lv.obj()
label = lv.label(screen)
label.set_text('Hello World!')
label.center()
self.setContentView(screen)
+2 -1
View File
@@ -20,7 +20,8 @@ rm "$outputjson"
# com.micropythonos.confetti crashes when closing
# com.micropythonos.showfonts is slow to open
# com.micropythonos.draw isnt very useful
blacklist="com.micropythonos.filemanager com.quasikili.quasidoodle com.micropythonos.confetti com.micropythonos.showfonts com.micropythonos.draw"
# com.micropythonos.errortest is an intentional bad app for testing (caught by tests/test_graphical_launch_all_apps.py)
blacklist="com.micropythonos.filemanager com.quasikili.quasidoodle com.micropythonos.confetti com.micropythonos.showfonts com.micropythonos.draw com.micropythonos.errortest"
echo "[" | tee -a "$outputjson"
+232
View File
@@ -0,0 +1,232 @@
"""
Test that launches all installed apps to check for startup errors.
This test discovers all apps in apps/ and builtin/apps/ directories,
launches each one, and checks for exceptions during startup.
"""
import unittest
import os
import sys
import time
# This is a graphical test - needs boot and main to run first
# Add tests directory to path for helpers
if '../tests' not in sys.path:
sys.path.insert(0, '../tests')
from graphical_test_helper import wait_for_render
import mpos.apps
import mpos.ui
from mpos.content.package_manager import PackageManager
class TestLaunchAllApps(unittest.TestCase):
"""Test launching all installed apps."""
def setUp(self):
"""Set up test fixtures."""
self.apps_to_test = []
self.app_errors = {}
# Discover all apps
self._discover_apps()
def _discover_apps(self):
"""Discover all installed apps."""
# Use PackageManager to get all apps
all_packages = PackageManager.get_app_list()
for package in all_packages:
# Get the main activity for each app
if package.activities:
# Use first activity as the main one (activities are dicts)
main_activity = package.activities[0]
self.apps_to_test.append({
'package_name': package.fullname,
'activity_name': main_activity.get('classname', 'MainActivity'),
'label': package.name
})
def test_launch_all_apps(self):
"""Launch each app and check for errors."""
print(f"\n{'='*60}")
print(f"Testing {len(self.apps_to_test)} apps for startup errors")
print(f"{'='*60}\n")
failed_apps = []
passed_apps = []
for i, app_info in enumerate(self.apps_to_test, 1):
package_name = app_info['package_name']
activity_name = app_info['activity_name']
label = app_info['label']
print(f"\n[{i}/{len(self.apps_to_test)}] Testing: {label} ({package_name})")
error_found = False
error_message = ""
try:
# Launch the app by package name
result = mpos.apps.start_app(package_name)
# Wait for UI to render
wait_for_render(iterations=5)
# Check if start_app returned False (indicates error during execution)
if result is False:
error_found = True
error_message = "App failed to start (execute_script returned False)"
print(f" ❌ FAILED - App failed to start")
print(f" {error_message}")
failed_apps.append({
'info': app_info,
'error': error_message
})
else:
# If we got here without error, the app loaded successfully
print(f" ✓ PASSED - App loaded successfully")
passed_apps.append(app_info)
# Navigate back to exit the app
mpos.ui.back_screen()
wait_for_render(iterations=3)
except Exception as e:
error_found = True
error_message = f"{type(e).__name__}: {str(e)}"
print(f" ❌ FAILED - Exception during launch")
print(f" {error_message}")
failed_apps.append({
'info': app_info,
'error': error_message
})
# Print summary
print(f"\n{'='*60}")
print(f"Test Summary")
print(f"{'='*60}")
print(f"Total apps tested: {len(self.apps_to_test)}")
print(f"Passed: {len(passed_apps)}")
print(f"Failed: {len(failed_apps)}")
print(f"{'='*60}\n")
if failed_apps:
print("Failed apps:")
for fail in failed_apps:
print(f" - {fail['info']['label']} ({fail['info']['package_name']})")
print(f" Error: {fail['error']}")
print()
# Test should detect at least one error (the intentional errortest app)
if len(failed_apps) > 0:
print(f"✓ Test successfully detected {len(failed_apps)} app(s) with errors")
# Check if we found the errortest app
errortest_found = any(
'errortest' in fail['info']['package_name'].lower()
for fail in failed_apps
)
if errortest_found:
print("✓ Successfully detected the intentional error in errortest app")
# Verify errortest was found
all_app_names = [app['package_name'] for app in self.apps_to_test]
has_errortest = any('errortest' in name.lower() for name in all_app_names)
if has_errortest:
self.assertTrue(errortest_found,
"Failed to detect error in com.micropythonos.errortest app")
else:
print("⚠ Warning: No errors detected. All apps launched successfully.")
class TestLaunchSpecificApps(unittest.TestCase):
"""Test specific apps individually for more detailed error reporting."""
def _launch_and_check_app(self, package_name, expected_error=False):
"""
Launch an app and check for errors.
Args:
package_name: Full package name (e.g., 'com.micropythonos.camera')
expected_error: Whether this app is expected to have errors
Returns:
tuple: (success, error_message)
"""
error_found = False
error_message = ""
try:
# Launch the app by package name
result = mpos.apps.start_app(package_name)
wait_for_render(iterations=5)
# Check if start_app returned False (indicates error)
if result is False:
error_found = True
error_message = "App failed to start (execute_script returned False)"
# Navigate back
mpos.ui.back_screen()
wait_for_render(iterations=3)
except Exception as e:
error_found = True
error_message = f"{type(e).__name__}: {str(e)}"
if expected_error:
# For apps expected to have errors
return (error_found, error_message)
else:
# For apps that should work
return (not error_found, error_message)
def test_errortest_app_has_error(self):
"""Test that the errortest app properly reports an error."""
success, error_msg = self._launch_and_check_app(
'com.micropythonos.errortest',
expected_error=True
)
if success:
print(f"\n✓ Successfully detected error in errortest app:")
print(f" {error_msg}")
else:
print(f"\n❌ Failed to detect error in errortest app")
self.assertTrue(success,
"The errortest app should have an error but none was detected")
def test_launcher_app_loads(self):
"""Test that the launcher app loads without errors."""
success, error_msg = self._launch_and_check_app(
'com.micropythonos.launcher',
expected_error=False
)
if not success:
print(f"\n❌ Launcher app has errors: {error_msg}")
self.assertTrue(success,
f"Launcher app should load without errors: {error_msg}")
def test_about_app_loads(self):
"""Test that the About app loads without errors."""
success, error_msg = self._launch_and_check_app(
'com.micropythonos.about',
expected_error=False
)
if not success:
print(f"\n❌ About app has errors: {error_msg}")
self.assertTrue(success,
f"About app should load without errors: {error_msg}")
if __name__ == '__main__':
unittest.main()