Unexpected "nested form" error appears when testing app with AppTest

Hi everyone,

it’s fantastic that one can test streamlit apps! Unfortunately, I’m currently facing a problem: I’m trying to setup tests of my streamlit app (at the moment locally), and I encounter an unexpected / false-positive “streamlit.errors.StreamlitAPIException: Forms cannot be nested in other forms.” error upon this small example:

from streamlit.testing.v1 import AppTest

def test_runner() -> None:
    def minimal_example() -> None:
        import streamlit as st
        with st.form("some_form"):
            ok = st.checkbox("OK")
    minimal_example()

def test_dashboard_default_behavior() -> None:
    at = AppTest.from_function(test_runner, default_timeout=10)
    at.run()
    assert at.session_state["$$STREAMLIT_INTERNAL_KEY_SCRIPT_RUN_WITHOUT_ERRORS"]

the full error message is

test_main_dashboard.py::test_dashboard_default_behavior 2024-02-13 17:00:52.919 Uncaught app exception
Traceback (most recent call last):
  File ".../python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 535, in _run_script
    exec(code, module.__dict__)
  File "...", line 5, in <module>
    minimal_example()
  File "...", line 3, in minimal_example
    with st.form("some_form"):
         ^^^^^^^^^^^^^^^^^^^^
  File ".../python3.11/site-packages/streamlit/runtime/metrics_util.py", line 396, in wrapped_func
    result = non_optional_func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.11/site-packages/streamlit/elements/form.py", line 200, in form
    raise StreamlitAPIException("Forms cannot be nested in other forms.")
streamlit.errors.StreamlitAPIException: Forms cannot be nested in other forms.
FAILED

The original error appeared in a more complex setting, I’m reproducing it by having that test_runner factory (when reducing one level of indirection, i.e. directly calling minimal_example, the error does not appear). I’m using python 3.11.6, streamlit 1.30.

Your code worked for me just adding a call to test_dashboard_default_behavior at the end of the script and also using unittest, making test_dashboard_default_behavior a method of a TestCase, but I got the same error as you with pytest.

So is must be something pytest is doing, but I don’t know what it can be. I am not a pytest user.

I think the problem arises from pytest running test_runner twice. Try renaming it to just runner.

1 Like

Hi @Goyo , indeed, it was the naming of the test_runner that made pytest run it twice. Thanks a lot for your help - now it’s also working in the original, more complex setting.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.