Beyond the basics of app testing
现在你已经熟悉了如何为Streamlit应用程序执行基本测试,让我们来介绍AppTest
的可变属性:
AppTest.secrets
AppTest.session_state
AppTest.query_params
你可以使用类似字典的语法来读取和更新所有三个属性的值。对于.secrets
和.query_params
,你可以使用键表示法但不能使用属性表示法。例如,AppTest
的.secrets
属性接受at.secrets["my_key"]
但不接受at.secrets.my_key
。这与你在主库中使用相关命令的方式不同。另一方面,.session_state
允许键表示法和属性表示法。
对于这些属性,典型的模式是在执行应用程序的第一次运行之前声明任何值。可以在测试中随时检查这些值。对于秘密和会话状态,还有一些额外的考虑,我们现在将介绍这些内容。
Using secrets with app testing
注意不要在测试中直接包含秘密。考虑这个简单的项目,在项目的根目录下执行pytest
:
myproject/
├── .streamlit/
│ ├── config.toml
│ └── secrets.toml
├── app.py
└── tests/
└── test_app.py
cd myproject
pytest tests/
在上述场景中,您的模拟应用程序将可以访问您的secrets.toml
文件。然而,由于您不希望将您的秘密提交到您的存储库中,您可能需要编写测试,以安全地将您的秘密拉入内存或使用虚拟秘密。
Example: declaring secrets in a test
在测试中,初始化AppTest
实例后但在第一次运行之前声明每个秘密。(缺少秘密可能导致应用程序无法运行!)例如,考虑以下秘密文件和相应的测试初始化,以手动分配相同的秘密:
密钥文件:
db_username = "Jane"
db_password = "mypassword"
[my_other_secrets]
things_i_like = ["Streamlit", "Python"]
测试具有等效密钥的文件:
# Initialize an AppTest instance.
at = AppTest.from_file("app.py")
# Declare the secrets.
at.secrets["db_username"] = "Jane"
at.secrets["db_password"] = "mypassword"
at.secrets["my_other_secrets.things_i_like"] = ["Streamlit", "Python"]
# Run the app.
at.run()
通常,您希望避免在测试中直接输入您的秘密信息。如果您的测试不需要真实的秘密信息,您可以像上面的示例中那样声明虚拟的秘密信息。如果您的应用程序使用秘密信息来连接到外部服务,如数据库或API,请考虑在应用程序测试中模拟该服务。如果您需要使用真实的秘密信息并实际连接,您应该使用API来安全且匿名地传递它们。如果您使用GitHub操作自动化测试,请查看他们的安全指南。
at.secrets["my_key"] = <value provided through API>
Working with Session State in app testing
AppTest
的 .session_state
属性允许你使用键表示法(at.session_state["my_key"]
)和属性表示法(at.session_state.my_key
)来读取和更新会话状态值。通过在会话状态中手动声明值,你可以直接跳转到特定状态,而不需要模拟多个步骤来达到该状态。此外,测试框架不提供对多页面应用的原生支持。AppTest
的实例只能测试一个页面。你必须手动声明会话状态值来模拟用户从另一个页面携带数据。
Example: testing a multipage app
考虑一个简单的多页面应用程序,其中第一页可以修改会话状态中的值。要测试第二页,请手动设置会话状态并在测试中运行模拟应用程序:
项目结构:
myproject/
├── pages/
│ └── second.py
├── first.py
└── tests/
└── test_second.py
第一个应用页面:
"""first.py"""
import streamlit as st
st.session_state.magic_word = st.session_state.get("magic_word", "Streamlit")
new_word = st.text_input("Magic word:")
if st.button("Set the magic word"):
st.session_state.magic_word = new_word
第二个应用页面:
"""second.py"""
import streamlit as st
st.session_state.magic_word = st.session_state.get("magic_word", "Streamlit")
if st.session_state.magic_word == "Balloons":
st.markdown(":balloon:")
测试文件:
"""test_second.py"""
from streamlit.testing.v1 import AppTest
def test_balloons():
at = AppTest.from_file("pages/second.py")
at.session_state["magic_word"] = "Balloons"
at.run()
assert at.markdown[0].value == ":balloon:"
通过在测试中设置值 at.session_state["magic_word"] = "Balloons"
,您可以模拟用户在 first.py
上输入并保存“Balloons”后导航到 second.py
的情况。
还有问题吗?
我们的 论坛 充满了有用的信息和Streamlit专家。