Open rjmautvix opened 2 months ago
If this issue affects you, please react with a 👍 (thumbs up emoji) to the initial post.
Your feedback helps us prioritize which bugs to investigate and address first.
The test code looks good, so I tested it for a while. There were several minor issues I found.
multiselect.set_value
is a list.E: TypeError: string indices must be integers, not 'str'
According to error message message, v
under the codeblock should be subscriptable. Thus, dictionary like {"id_inventory": 1, "description": "Inventory 1"} should be passed. similar to what you wrote at type hint of items variable.
/streamlit/testing/v1/element_tree.py:824: in <listcomp>
return [self.options.index(self.format_func(v)) for v in self.value]
# To use the format_func below,
items: list[dict] = st.multiselect(
"Estoques", inventories, format_func=lambda x: x["description"]
)
# The test function should modified like this
multiselect.set_value([{"id_inventory": 1, "description": "Inventory 1"}])
if st.button(~)
statement delete testing_tab1
, main function always sets the variable testing_tab1
False
. How about modifying code like below?:
def render_tab1(inventories):
...
if not items:
button_disabled = True
st.session_state["testing_tab1"] = False
else:
button_disabled = False
st.session_state["testing_tab1"] = True
In my opinion, button_disabled
and st.session_state["testing_tab1"]
should be considered at once. Because those status changes from same trigger. Also, the variables like st.session_state["testing_tab1"]
are only used in testing code, not affect rendered view. That's the reason why your screen looks ok.
Couldn't test screen view, so not sure if my suggestion was correct. However a slight logic change seems to improve the result better, so leave my comment. Have a good day!
The test code looks good, so I tested it for a while. There were several minor issues I found.
- I have just started learning Streamlit, so I might be pointing out non-issues. I apologize in advance for any inconvenience.
- The argument type of
multiselect.set_value
is a list.E: TypeError: string indices must be integers, not 'str' According to error message message,
v
under the codeblock should be subscriptable. Thus, dictionary like {"id_inventory": 1, "description": "Inventory 1"} should be passed. similar to what you wrote at type hint of items variable./streamlit/testing/v1/element_tree.py:824: in <listcomp> return [self.options.index(self.format_func(v)) for v in self.value]
# To use the format_func below, items: list[dict] = st.multiselect( "Estoques", inventories, format_func=lambda x: x["description"] ) # The test function should modified like this multiselect.set_value([{"id_inventory": 1, "description": "Inventory 1"}])
As
if st.button(~)
statement deletetesting_tab1
, main function always sets the variabletesting_tab1
False
. How about modifying code like below?:def render_tab1(inventories): ... if not items: button_disabled = True st.session_state["testing_tab1"] = False else: button_disabled = False st.session_state["testing_tab1"] = True
In my opinion,
button_disabled
andst.session_state["testing_tab1"]
should be considered at once. Because those status changes from same trigger. Also, the variables likest.session_state["testing_tab1"]
are only used in testing code, not affect rendered view. That's the reason why your screen looks ok.Couldn't test screen view, so not sure if my suggestion was correct. However a slight logic change seems to improve the result better, so leave my comment. Have a good day!
Hi, thanks for the digestion! Really if I replace this piece of code:
def test_screen_tab1():
app = AppTest.from_string(screen_code)
app.run()
tabs = app.tabs[0]
multiselect = tabs.multiselect[0]
button = tabs.button[0]
multiselect.set_value("Inventory 1")
button.click().run()
assert app.session_state.testing_tab1 == True
For this:
def test_screen_tab1():
app = AppTest.from_string(screen_code)
app.run()
tabs = app.tabs[0]
multiselect = tabs.multiselect[0]
button = tabs.button[0]
multiselect.set_value([{"id_inventory": 1, "description": "Inventory 1"}])
button.click().run()
assert app.session_state.testing_tab1 == True
The issue "TypeError: string indices must be integers, not 'str'" is resolved. However, the test still does not occur as expected. While on the screen when something is selected in multiselect the button is unlocked, in the test this does not happen. Even though I select something in multiselect and the _value attribute exists and has a value, the button remains disabled.
To prove the case mentioned above, just add this test case:
def test_screen_tab1():
app = AppTest.from_string(screen_code)
app.run()
tabs = app.tabs[0]
multiselect = tabs.multiselect[0]
button = tabs.button[0]
multiselect.set_value([{"id_inventory": 1, "description": "Inventory 1"}])
assert button.disabled == False
Hi @rjmautvix, appreciate your submission! There is certainly a gap with our AppTest capabilities right now, and unfortunately we don't know when we will be able to resolve them. We'll keep this issue open so that others can 👍 - we use that information to prioritize fixes. Thanks for your patience 🙏
Checklist
Summary
I wrote code for a streamlit page with 2 tabs: the first with a multiselect and the second with a selectbox.
In the first with a multiselect, I chose to lock the button if there is no option selected and, when options are selected, the button is unlocked.
In the second tab, I have a selectbox that, when an inventory with a following condition is selected (in the real app the condition is different), the button is blocked.
Operating the screen works as expected, but I can't execute the same behavior in tests. Testing the first tab, the button is not unlocked when selecting a multiselect option and, testing the second tab, the button is not blocked when the condition is met.
Reproducible Code Example
Steps To Reproduce
create a venv
install streamlit
install pytest
run the tests
create an app.py file with the contents of the
screen_code
variable and run the commandExpected Behavior
In the first test, after selecting an option in multiselect, it should be possible to click the button.
In the second test, the initial value of the selectbox is the inventory that will meet the condition to block the button and when selecting another inventory that does not meet the condition, it is to unlock the button.
Current Behavior
In the first test, the button is not unlocking when selecting a multiselect option and it is not possible to click on the button and the error occurs:
TypeError: string indices must be integers, not 'str'
.In the second test, the button is not unlocking when selecting an inventory that does not meet the condition.
Full test log:
Is this a regression?
Debug info
Additional Information
No response