Hi all
I have a multipage app with the following layout. I have a sidebar and navigation managed by st-pages (streamlit==1.42.2, python 3.12, st-pages==1.0.1)
myproject/
├── .streamlit
│ ├── pages.toml
├── pages/
│ ├── home.py
│ ├── page_section
│ │ └── page1.py
├── app.py
└── tests/
└── test_app.py
I am trying to write a test that goes to each page and just tests that it loads without exception.
- The docs here say that we need to test each page individually but the app.py page uses a nav and that breaks this method:
ElementList(_list=[Exception(message='Unable to create Page. The file home.py
could not be found.'`
- Alternatively this issue recommends using the swtich_page ()method. This does not raise errors but the appTest object does not actually update after this is run (I tried using
at.run()
in multiple places, to no effect) and so I cannot actually navigate to that new page to check for errors (tests pass even when I raise an exception on target page)
I am testing with unittest and here is an excerpt of how I’m running the test:
def test_all_pages_load(self):
for filename in ['pages/page_section/page1.py']:
with self.subTest(filename=filename):
at = AppTest.from_file("../app.py").run()
at.switch_page(filename)
at.run()
assert not at.exception
Can someone help me understand how to test these pages?
Here’s the exact test code I used, and it seemed to work fine:
import os
import sys
import unittest
from pathlib import Path
from streamlit.testing.v1.app_test import AppTest
# Add the parent directory to sys.path to make imports work
sys.path.insert(0, str(Path(__file__).parent.parent))
class TestMultiPageApp(unittest.TestCase):
def setUp(self):
# Change to the directory containing app.py for proper path resolution
self.original_dir = os.getcwd()
os.chdir(str(Path(__file__).parent.parent))
def tearDown(self):
# Restore the original directory
os.chdir(self.original_dir)
def test_all_pages_load(self):
# List of pages to test
pages = ["pages/page_section/page1.py"]
for filename in pages:
with self.subTest(filename=filename):
# Initialize the app test with the main app
at = AppTest.from_file("app.py").run()
# Try to switch to the page
at.switch_page(filename)
at.run()
# Check if there were any exceptions
self.assertFalse(
at.exception,
f"Exception occurred while loading {filename}: {at.exception}",
)
if __name__ == "__main__":
unittest.main()
I tested it by adding a ValueError to page1.py, and it correctly showed it as a test error.
Hi, thanks for that snippet. I have it running now. but I still have issues with page switching.
I can catch errors on the home.py
page but not on other pages. I don’t get errors from switch_page()
but when I print the at
object, it doesn’t change before and after the command (eg: page hash, session state stays the same). What should I expect to see changing when I switch a page?
I’m not sure, sorry. I added print(at._page_hash)
and ran pytest -s
(to show all the outputs), and got different page hashes for each page:
tests/test_app.py 2025-04-08 10:08:57.041 WARNING streamlit.runtime.scriptrunner_utils.script_run_context: Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.
106a6c241b8797f52e1e77317b96a201 # page_hash for home.py
2025-04-08 10:08:57.118 Thread 'MainThread': missing ScriptRunContext! This warning can be ignored when running in bare mode.
acd150a6885f609532931d89844070b1 # page_hash for page1.py
Note that (just in case) I also updated the list of pages
to
pages = ["pages/home.py", "pages/page_section/page1.py"]