Selenium performance testing in MaxoPerf
The Taurus selenium executor drives real Chrome or Firefox instances as virtual users. Where a JMeter or k6 VU sends raw HTTP requests, a Selenium VU loads the full page — HTML, CSS, JavaScript, web fonts, images — and executes your Python WebDriver script as a real browser would. This is how you measure what users actually see in MaxoPerf.
Before you start
Section titled “Before you start”- Read Browser vs protocol load to confirm browser testing is the right approach for your goal.
- Read By engine: Selenium browser tests for executor configuration reference.
- Have a target URL accessible from the MaxoPerf runner locations you intend to use.
What the selenium executor gives you
Section titled “What the selenium executor gives you”When MaxoPerf runs a selenium executor job:
- Each VU is a fully isolated Chrome (or Firefox) process.
- The browser navigates to your target, executes your script, and reports every WebDriver interaction as a labeled timing measurement.
- Errors include HTTP failures, assertion failures, and uncaught JavaScript exceptions.
- Results appear in the standard MaxoPerf run-detail view alongside any other metrics from the same run.
You do not get raw Core Web Vitals (LCP, CLS, INP) automatically from the selenium executor — you get interaction timings. To capture web vitals, inject the web-vitals JavaScript library in your script and report the values via a custom label. See Frontend web vitals under load for the pattern.
Taurus YAML with the selenium executor
Section titled “Taurus YAML with the selenium executor”execution: - executor: selenium concurrency: 5 # one Chrome process per VU — keep low ramp-up: 2m hold-for: 10m scenario: checkout-journey
scenarios: checkout-journey: script: scripts/checkout.py # Python WebDriver script, uploaded as test asset browser: chrome # chrome (default) or firefox headless: true # always true on MaxoPerf runners
modules: selenium: chromedriver: version: latestPython WebDriver script
Section titled “Python WebDriver script”Create scripts/checkout.py and upload it as a Test asset alongside the Taurus YAML:
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC
def test_checkout_journey(driver): """ Full checkout journey: home → product → cart → order summary. Each step is a separate Selenium label in MaxoPerf results. """ # Step 1: Load homepage driver.get("https://app.example.com/") WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".product-grid")) )
# Step 2: Open a product driver.find_element(By.CSS_SELECTOR, ".product-grid .product-card:first-child").click() WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "add-to-cart")) )
# Step 3: Add to cart driver.find_element(By.ID, "add-to-cart").click() WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".cart-count[data-count='1']")) )
# Step 4: Open cart and proceed to checkout driver.find_element(By.CSS_SELECTOR, ".cart-icon").click() WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.LINK_TEXT, "Proceed to checkout")) ).click()
# Step 5: Assert order summary page loaded WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".order-summary")) )Upload and run
Section titled “Upload and run”-
In the MaxoPerf console, open the test → Files tab.
-
Upload your Taurus YAML (
checkout.yaml) as the Entrypoint. -
Upload
scripts/checkout.pyas a Test asset. The YAML pathscripts/checkout.pymust match the relative path you set when uploading. -
Save. MaxoPerf validates that the YAML references the uploaded script.
-
In the Load profile tab, confirm concurrency (e.g.
5), ramp-up (2m), and hold duration (10m). -
Click Run. The runner starts Chrome instances equal to the
concurrencyvalue. Browser VUs are slower to cold-start — expect the first metrics to appear 20–60 s into the run.
Using a Selenium IDE .side file
Section titled “Using a Selenium IDE .side file”If your team recorded flows with Selenium IDE, you can upload the .side file directly as the entrypoint — MaxoPerf infers the selenium executor from the file extension:
my-flow.side → Entrypoint → engine: selenium (auto-detected)To control concurrency and duration, wrap the .side file in a Taurus YAML:
execution: - executor: selenium concurrency: 3 hold-for: 5m scenario: recorded-flow
scenarios: recorded-flow: script: my-flow.sideScaling browser VUs — cost and resource guidance
Section titled “Scaling browser VUs — cost and resource guidance”| VU count | Use case | Runner resource estimate |
|---|---|---|
| 1–3 | Smoke / sanity check — verify the journey runs | ~1–3 GB RAM per runner |
| 5–10 | Journey performance measurement | ~5–10 GB RAM per runner |
| 10–20 | Multi-user browser stress (edge case) | Requires dedicated runner sizing |
| 20+ | Avoid — use protocol VUs for scale | Cost is prohibitive; results become unreliable |
Each Chrome VU consumes roughly 500 MB–1 GB of RAM and 1–2 CPU cores under load. MaxoPerf runners are sized for protocol VUs; browser tests at high concurrency may exhaust runner resources and produce flaky results rather than load data.
Reading browser test results
Section titled “Reading browser test results”After the run finishes:
- Throughput — shown as iterations per second (completed browser flows), not HTTP RPS. A single flow may include 5 WebDriver interactions — each is also reported as a separate label.
- Latency — the time for each WebDriver
get(),click(), orwait_for_element()step. Focus on thenavigationlabel for page-load time and the finalwait_forlabel for the full journey duration. - Error rate — WebDriver assertion failures and uncaught exceptions. A high error rate usually means an element was not found — often caused by a layout change or a slow render that exceeded the
WebDriverWaittimeout. - Runner health — check the Runners tab. Browser VUs are more likely to saturate runners. A runner in
degradedstate indicates resource exhaustion; reduce concurrency.
Do / don’t
Section titled “Do / don’t”Do:
- Keep concurrency low (2–10) — browser tests measure UX, not throughput.
- Use
headless: true— headed Chrome is not supported on MaxoPerf runners. - Test your script locally with
python scripts/checkout.pybefore uploading. - Use
WebDriverWaitwith meaningful timeouts that reflect real user expectations.
Don’t:
- Use browser tests to generate high load — use protocol VUs for that.
- Put real credentials in the script — use Manage test secrets and inject them via environment variables.
- Compare Selenium iteration-rate numbers to JMeter RPS numbers — they measure different things.
Where to go next
Section titled “Where to go next”- Frontend web vitals under load — how to capture LCP/CLS/INP in a browser test.
- Hybrid load architecture — combine browser VUs with protocol load in one run.
- By engine: Selenium browser tests — executor reference,
.sidefiles, and thewdioalternative. - Browser vs protocol load — tradeoff analysis to confirm you chose the right approach.