You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Selenium与pytest测试Streamlit应用:元素定位与等待

问题与解决方案

问题概述

我搭建了一个简单的Streamlit应用,想用Selenium和pytest框架测试其UI元素。已完成Chrome浏览器及ChromeDriver的安装、路径配置。待测试脚本app/Home.py代码如下:

import streamlit as st

st.set_page_config(page_title="Home")

st.title("Welcome to My Streamlit App")
st.write("This is the home page of the application.")

st.header("Instructions")
st.write("Navigate to the sidebar to explore different pages:")
st.write("- Home: This page.")
st.write("- About: Learn more about the app.")

st.subheader("Features")
st.write("- Interactive data visualization.")
st.write("- Easy navigation between pages.")

st.info("Enjoy exploring the app!")

现有pytest测试脚本可测试首页标题,但目前用time.sleep等待应用启动及元素加载,希望改用Selenium内置的隐式/显式等待;同时不清楚如何定位st.header、st.write、st.info对应的页面元素,需解决这两个问题。当前测试脚本:

import subprocess
import time

import pytest
from selenium import webdriver


@pytest.fixture(scope="session")
def driver():
    # Start the Streamlit application as a separate process
    app_process = subprocess.Popen(
        ["streamlit", "run", "app/Home.py"]
        )

    # Wait for the Streamlit app to start
    time.sleep(2)

    driver = webdriver.Chrome()
    yield driver
    driver.quit()

    # Stop the Streamlit application process after the test
    app_process.terminate()
    app_process.wait()

def test_home_title(driver):
    driver.get("http://localhost:8501")

    # How to find the streamlit element and then wait for them to being ready?
    time.sleep(1)

    assert driver.title == "Home"

解决方案

1. 替换time.sleep为Selenium等待机制

隐式等待

在初始化Driver后设置全局隐式等待,让Driver在查找元素时自动等待指定时长,无需重复编写等待逻辑:

driver = webdriver.Chrome()
driver.implicitly_wait(10)  # 最多等待10秒
yield driver

显式等待(推荐)

针对特定元素或条件做精准等待,比隐式等待更灵活,比如等待Streamlit应用启动完成:
先导入相关模块:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

然后在fixture中替换原time.sleep(2):

# 先打开页面,再等待标题加载完成
driver.get("http://localhost:8501")
WebDriverWait(driver, 15).until(EC.title_is("Home"))

2. Streamlit元素定位方法

Streamlit生成的HTML元素带有特定class属性,可结合文本内容或class进行定位:

  • st.title:对应<h1>标签,class为stTitle,定位示例:
    title_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//h1[text()='Welcome to My Streamlit App']"))
    )
    
  • st.header:对应<h2>标签,class为stHeader,定位示例:
    header_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//h2[text()='Instructions']"))
    )
    
  • st.write:内容通常在class为stMarkdown或stText的<div>中,定位示例:
    write_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//div[contains(text(),'This is the home page of the application.')]"))
    )
    
  • st.info:对应class为stAlert的<div>,定位示例:
    info_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//div[@class='stAlert' and contains(text(),'Enjoy exploring the app!')]"))
    )
    

修改后的完整测试脚本

import subprocess

import pytest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@pytest.fixture(scope="session")
def driver():
    # 启动Streamlit应用
    app_process = subprocess.Popen(["streamlit", "run", "app/Home.py"])

    # 初始化Driver并设置隐式等待
    driver = webdriver.Chrome()
    driver.implicitly_wait(10)
    
    # 显式等待应用启动完成
    driver.get("http://localhost:8501")
    WebDriverWait(driver, 15).until(EC.title_is("Home"))
    
    yield driver
    
    # 清理资源
    driver.quit()
    app_process.terminate()
    app_process.wait()

def test_home_page_elements(driver):
    # 验证页面标题
    assert driver.title == "Home"
    
    # 验证st.title元素
    title = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//h1[text()='Welcome to My Streamlit App']"))
    )
    assert title.is_displayed()
    
    # 验证st.header元素
    header = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//h2[text()='Instructions']"))
    )
    assert header.is_displayed()
    
    # 验证st.write文本
    write_text = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//div[contains(text(),'This is the home page of the application.')]"))
    )
    assert write_text.is_displayed()
    
    # 验证st.info元素
    info_box = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(("xpath", "//div[@class='stAlert' and contains(text(),'Enjoy exploring the app!')]"))
    )
    assert info_box.is_displayed()

内容的提问来源于stack exchange,提问作者Péter Szilvási

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:53:14