"""Integration tests for Streamlit app. These tests actually run the Streamlit app to catch API errors that unit tests miss (like wrong parameter names). """ import pytest import subprocess import sys import time import os import signal class TestStreamlitAppRuns: """Test that the Streamlit app actually runs without errors.""" def test_app_python_syntax_valid(self): """App has valid Python syntax.""" app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) app_path = os.path.join(app_dir, "app.py") # Compile the file to check for syntax errors with open(app_path, "r") as f: source = f.read() try: compile(source, app_path, "exec") except SyntaxError as e: pytest.fail(f"Syntax error in app.py: {e}") class TestStreamlitAPIUsage: """Check for common Streamlit API mistakes by parsing the code.""" def test_no_invalid_dataframe_width(self): """st.dataframe should use use_container_width, not width="stretch".""" app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) app_path = os.path.join(app_dir, "app.py") with open(app_path, "r") as f: content = f.read() # Find all st.dataframe calls with wrong width parameter import re # Look for st.dataframe with width="stretch" (wrong) # But NOT use_container_width (correct) pattern = r'st\.dataframe\([^)]*[^_]width\s*=\s*["\']stretch["\']' matches = re.findall(pattern, content) if matches: pytest.fail( f"Found st.dataframe with 'width=\"stretch\"' parameter. " f"Use 'use_container_width=True' instead.\n" f"Matches: {matches}" ) def test_no_undefined_variables_in_fstrings(self): """Check for common f-string variable errors.""" app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) app_path = os.path.join(app_dir, "app.py") with open(app_path, "r") as f: lines = f.readlines() # Check each f-string for obvious issues import re for i, line in enumerate(lines, 1): # Find f-strings if 'f"' in line or "f'" in line: # Check for empty braces (common mistake) if "{}" in line: pytest.fail(f"Line {i}: Empty braces in f-string: {line.strip()}") class TestAppWithStreamlitTesting: """Use Streamlit's built-in testing framework if available.""" @pytest.fixture def app(self): """Create AppTest instance.""" try: from streamlit.testing.v1 import AppTest except ImportError: pytest.skip("streamlit.testing not available (requires streamlit>=1.28)") app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) app_path = os.path.join(app_dir, "app.py") # Run the app at = AppTest.from_file(app_path) at.run(timeout=30) return at def test_app_runs_without_exception(self, app): """App renders without raising exceptions.""" assert not app.exception, f"App raised exception: {app.exception}" def test_app_has_header(self, app): """App has a header element.""" # The app should have rendered some content assert len(app.markdown) > 0 or len(app.header) > 0, "App has no content" def test_app_has_sidebar(self, app): """App has sidebar elements.""" assert len(app.sidebar) > 0, "App has no sidebar"