Automated tests catch broken widgets and logic before users do, without clicking through the app by hand.
streamlit.testing.v1.AppTest runs an app script without a browser and lets you inspect and interact with its elements:
from streamlit.testing.v1 import AppTest
at = AppTest.from_file("app.py").run()from_string and from_function create apps from code directly, handy for small tests. After .run():
- Elements are accessed by type, as lists in order of appearance:
at.title[0].value,at.markdown,at.metric,at.dataframe,at.error,at.exception. - Widgets are accessed the same way or by key:
at.slider[0],at.text_input(key="name"). - Interact, then run again:
at.slider[0].set_value(5).run(),at.button[0].click().run(),at.text_input[0].input("Ada").run(),at.selectbox[0].select("pro").run(). at.session_state["count"]reads or presets state;at.secrets["api_key"] = "test"provides secrets.at.switch_page("pages/admin.py")tests multipage apps.
Assert that no exception occurred with assert not at.exception. Tests run in a fresh session each time, so they are isolated and fast enough for CI with pytest.
AppTest does not render HTML or JavaScript, so it cannot test visual layout or custom components; for that, use browser tests (Playwright). Keep business logic in plain functions with their own unit tests and use AppTest for the wiring.
Example
from streamlit.testing.v1 import AppTest
def app(): # the app under test
import streamlit as st
price = st.number_input("Price", value=10.0, key="price")
qty = st.slider("Qty", 1, 10, 1)
if qty > 5:
st.warning("Bulk order")
st.metric("Total", f"{price * qty:.2f}")
def test_total_and_warning():
at = AppTest.from_function(app).run()
assert at.metric[0].value == "10.00"
assert len(at.warning) == 0
at.slider[0].set_value(6).run()
at.number_input(key="price").set_value(2.5).run()
assert at.metric[0].value == "15.00"
assert at.warning[0].value == "Bulk order"
assert not at.exception
test_total_and_warning()
print("passed") # run with pytest in a real projectRemember
- AppTest runs apps headless:
AppTest.from_file('app.py').run() - Inspect elements by type or key and interact with set_value, click, input, then
.run() - Preset
session_stateandsecrets; assertnot at.exception
Watch out for
- Forgetting to call
.run()after interacting, so assertions see the previous state.