Skip to main content

Testing Streaming Chatbots with Selenium: Completion, Meaning, and Latency

Use the current Selenium Chatbot Test APIs while distinguishing DOM quiet periods, semantic scores, and actual model completion.

3 min read
Testing Streaming Chatbots with Selenium: Completion, Meaning, and Latency
On this page

Selenium can test dynamic interfaces, but the wait condition has to match the application. The presence of a response element or the first visible word does not mean a chatbot has finished answering. Streaming makes that distinction especially easy to miss.

Prefer an explicit completion signal

If the application exposes a completed state, response identifier, or disabled streaming indicator, wait for it and assert the intended response. A DOM quiet period is a useful fallback when that signal is unavailable, but a pause between chunks can look like completion.

The current selenium-chatbot-test README documents StreamWaiter().wait_for_stream_end(driver, locator, silence_timeout=0.5, timeout=30.0). Timeouts are in seconds and the result is a WebElement. The earlier constructor and wait_for_stable_text examples have been replaced here.

python
from selenium.webdriver.common.by import By
from selenium_chatbot_test import StreamWaiter

# driver is an active session with the target response element present.
response_element = StreamWaiter().wait_for_stream_end(
    driver, (By.ID, "response"), silence_timeout=0.5, timeout=30.0
)
response_text = response_element.text
Quiet is not a completion guarantee
MutationObserver reports changes in the observed DOM. It cannot know whether the server will send another chunk later. Calibrate the quiet window and combine it with a response-specific application signal wherever possible.

Treat semantic similarity as one signal

python
from selenium_chatbot_test import SemanticAssert

SemanticAssert().assert_similarity(
    actual="Hi, how can I assist?",
    expected="Hello, how can I help?",
    min_score=0.7,
)

This is an illustrative threshold, not a promised passing result or 70% semantic accuracy. Similarity can miss a changed number, negation, unsafe instruction, or unsupported factual claim. Calibrate with labeled examples and keep exact checks for required structured fields and prohibited outcomes. The embedding dependency can download a model on first use, so prepare and cache it deliberately in CI.

Measure the visible response lifecycle

LatencyMonitor observes the page around the trigger action. Its first-change timing is a browser-visible proxy for response latency, not a direct measure of the model server’s first token. DOM mutation counts are not tokenizer token counts.

python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium_chatbot_test import StreamWaiter, LatencyMonitor

def test_chatbot_response():
    driver = webdriver.Chrome()
    try:
        # Replace with an authorized test app whose response node exists
        # before sending and is cleared for each new response.
        driver.get("https://example.com/chat")
        driver.find_element(By.ID, "chat-input").send_keys("Hello")
        with LatencyMonitor(driver, (By.ID, "response")) as monitor:
            driver.find_element(By.ID, "send-btn").click()
            element = StreamWaiter().wait_for_stream_end(
                driver, (By.ID, "response"),
                silence_timeout=0.5, timeout=30.0,
            )
        assert element.text.strip(), "Expected a visible response"
        # Add the application's completion and content assertions here.
        print({"first_change_ms": monitor.metrics.ttft_ms,
               "observed_total_ms": monitor.metrics.total_ms})
    finally:
        driver.quit()

Build the failure set before tuning

  • A response that starts late or pauses between chunks.
  • A new response that replaces an old DOM node.
  • A failed or cancelled request.
  • A semantically similar answer containing the wrong value.
  • A retry that accidentally appends to a previous response.

Retain response identifiers and sanitized browser evidence so timing failures can be distinguished from content failures. These helpers make checks easier to express; they do not make model output deterministic.

Selenium Chatbot Test current API guide, reviewed September 5, 2026.

Dhiraj Das

About the Author

Dhiraj Das is an Automation Consultant with over a decade of experience building systems that expose failures, reduce flakiness, and make complex workflows repeatable. He applies that discipline to AI-agent validation, LLM testing, and postmortems.

He shares small open source utilities from real automation work, including: waitless (flaky tests), sb-stealth-wrapper (bot detection), selenium-teleport (state persistence), selenium-chatbot-test (AI chatbot testing), lumos-shadowdom (Shadow DOM), and visual-guard (visual regression).

Share this article: