Structure of test files and folders when using AppTest

Python version: 3.11
Streamlit Version: 1.30.0

Running it locally

Hi,

We have started covering our application with tests and we have a problem. We would like our tests to be structured as follows.

β”œβ”€β”€ tests
β”‚   β”œβ”€β”€ unit
β”‚   β”‚   │── test_interface.py
β”‚   β”œβ”€β”€ integration

#test_interface.py
from streamlit.testing.v1 import AppTest


def prepare_view():
    import streamlit as st

    st.multiselect(label='test', options=['foo', 'bar'], key='key', default='foo')


class TestView:
    def test_change_value(self):
        app_test = AppTest.from_function(prepare_view)
        app_test.run()

        assert app_test.session_state['key'] == ['foo']

        app_test.multiselect[0].set_value(['bar']).run()
        assert app_test.session_state['key'] == ['bar']

With this structure, running a test with the command pytest tests/unit/test_interface.py works correctly
An error occurs when running all the tests of the project with the command pytest tests

Exception:

self = SessionState(_new_session_state={'$$STREAMLIT_INTERNAL_KEY_SCRIPT_RUN_WITHOUT_ERRORS': True}, _new_widget_state=WStates()), key = 'key'
...
E           KeyError: 'st.session_state has no key "key". Did you forget to initialize it? More info: https://docs.streamlit.io/library/advanced-features/session-state#initialization'

key        = 'key'
self       = SessionState(_new_session_state={'$$STREAMLIT_INTERNAL_KEY_SCRIPT_RUN_WITHOUT_ERRORS': True}, _new_widget_state=WStates())
wid_key_map = {}
widget_id  = 'key'

If we move the file with this test to the tests/ folder and run it with the pytest tests command, everything will work correctly

Can you please help how to make the tests work correctly in the unit subfolder when running all tests?

Hi Ilzirauraz,

you have tried to initialize the session state at the start of the test?

def prepare_view():
    st.session_state['key'] = None  # Initialize session state 
    st.multiselect(label='test', options=['foo', 'bar'], key='key', default='foo')

Hello @ilzirauraz,

Can you please try this:

  1. Ensure your pytest is configured correctly to discover and run tests in subdirectories.
  2. Make sure each of your test directories (tests/, tests/unit/, tests/integration/) contains an __init__.py file.
  3. Consider using a pytest fixture to initialize Streamlit’s session state before tests run, ensuring consistent setup across tests.
# In a conftest.py file within your tests directory

import pytest
from streamlit.testing.v1 import AppTest

@pytest.fixture(scope="function")
def app_test():
    # Setup code here, if needed
    
    yield AppTest.from_function(prepare_view)
  1. Modify your test to use the fixture for consistent session state handling.
# In your test_interface.py

def test_change_value(app_test):  # app_test is automatically injected by pytest
    app_test.run()
    assert app_test.session_state['key'] == ['foo']
    app_test.multiselect[0].set_value(['bar']).run()
    assert app_test.session_state['key'] == ['bar']

Hope this helps!

Kind Regards,
Sahir Maharaj
Data Scientist | AI Engineer

P.S. Lets connect on LinkedIn!

➀ Want me to build your solution? Lets chat about how I can assist!
➀ Join my Medium community of 30k readers! Sharing my knowledge about data science and AI
➀ Website: https://sahirmaharaj.com
➀ Email: sahir@sahirmaharaj.com
➀ 100+ FREE Power BI Themes: Download Now

3 Likes