UI Unit Testing Streamlit Apps--best practices?


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


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):

    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()
    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:

  1. Installation | Playwright (I just ran the install via npm and ignored the rest of the instructions)
  2. Installation | Playwright Python (Installed the python packages and ran from command line)

The question

Does the above approach make sense or am I heading down some wrong rabbit hole?

The 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


Hi @breckbaldwin, curious how that turned out and if you had a good experience using Playwright with Streamlit.