What are best practices for testing Streamlit apps at the UI level?
I am authoring fairly complex Streamlit apps and really should be testing the behavior. I don’t have any experience working with UI unit testing frameworks. Below is a small check box app that has a bit of logic that I’d like to make sure is correct:
import streamlit as st st.title("Test") def select_all(arg): st.session_state.a = st.session_state[arg] st.session_state.b = st.session_state[arg] def update_star(): all_true = True for selection in ['a', 'b']: if not st.session_state[selection]: all_true = False st.session_state['star_sel'] = all_true st.write('### Control') st.checkbox('\*', key='star_sel', args=['star_sel'], on_change=select_all) st.write('### main') st.checkbox('a', key='a', on_change=update_star) st.checkbox('b', key='b', on_change=update_star)
In testing this I finally settled on trying Playwright, Installation | Playwright Python, for my testing. I looked at the blog post at How to Create Automated Visual Tests [SeleniumBase Tutorial] but couldn’t get it to work.
My testing code is:
from playwright.sync_api import Page, expect def test_tmp(page: Page): page.goto("http://localhost:8501") star_cb = page.locator("label").filter(has_text="*").locator("span") a_cb = page.locator("label").filter(has_text="a").locator("span") b_cb = page.locator("label").filter(has_text="b").locator("span") assert not star_cb.is_checked() assert not a_cb.is_checked() assert not b_cb.is_checked() star_cb.click() assert star_cb.is_checked() page.wait_for_timeout(50) #annoying assert page.locator("label").filter(has_text="a").locator("span").is_checked() assert b_cb.is_checked()
So I run the streamlit app as usual and then run the above using
pytest test.py after installing the relevant packages for Playwright for anyone replicating what I am doing:
- Installation | Playwright (I just ran the install via npm and ignored the rest of the instructions)
- Installation | Playwright Python (Installed the python packages and ran from command line)
Does the above approach make sense or am I heading down some wrong rabbit hole?
page.wait_for_timeout(50) with an
#annoying comment is indeed annoying, but since the backend has to compute the values of the checkboxes it makes some sense. The auto-wait feature of Playwright does not handle it correctly–perhaps I am using it improperly?
thanks for any feedback