Features
Everything the plumbing used to be
Add one dependency and get the lifecycle, waits, retries, reporting, and CI wiring that every Java team otherwise rebuilds — plus Playwright-inspired ergonomics, without hiding Selenium.
The essentials
Sold on outcomes, named for the API
Never write Thread.sleep() again
WaitEngine
Every action auto-waits on a centralised engine with 10+ built-in conditions, so fixed sleeps and most timing flakes go away.
Tests survive CSS & DOM refactors
Accessibility-first locators
getByRole, getByLabel, getByText, getByTestId — target the accessibility tree, not brittle selectors.
Assertions that don't flake on timing
Web-first assertThat()
assertThat(locator).isVisible() auto-retries until true or the timeout — no manual polling.
Known-flaky tests stop blocking your build
@Retryable + RetryListener
Global, per-method, or per-scenario retries absorb transient failures. Quarantine known-flaky tests without deleting them.
Hand stakeholders a report they'll read
HTML report + JUnit XML
Tabbed dashboard — overview, cases, failures, flakiness radar. JUnit XML parsed natively by any CI.
Safe parallel execution by default
ThreadLocal DriverManager
One driver per thread, isolated and thread-safe. Scale across methods or classes with a config flag.
CI that configures itself
CiEnvironmentDetector
Auto-detects GitHub Actions / Jenkins / GitLab. Headless forced, threads tuned, pass-rate gates enforced.
Extend it without forking it
SPI plugin toolkit
Registry-based plugins for custom drivers, hooks, and report adapters. The escape hatch most never need.
Out of the box
The complete list
Outcomes on the left, the API that delivers each one on the right.
| Never write driver setup or teardown again | One driver per thread, created before each test, quit after |
| Switch environments without touching code | YAML config — browser, parallel, timeouts, retry in one file |
| Never write Thread.sleep() again | Auto-waiting WaitEngine with 10+ built-in conditions |
| Known-flaky tests stop blocking your build | Global, per-method @Retryable, or per-scenario @retryable tag |
| See exactly why a test failed | Screenshot auto-captured on failure, embedded in the report |
| Read the test like a spec | StepLogger named steps with optional per-step screenshots |
| Hand stakeholders a report they'll read | Tabbed HTML dashboard — overview, cases, failures, flakiness radar |
| Plug into any CI without extra tooling | JUnit XML parsed natively by Jenkins, GitHub Actions, GitLab CI |
| CI that configures itself | Headless forced, threads auto-tuned, no config changes needed |
| Extend it without forking it | SPI-based plugins — custom drivers, hooks, report adapters |
| Bring your own test runner | Full JUnit 5 parity via @ExtendWith or BaseJUnit5Test |
| Write specs your product team can read | BDD / Cucumber — BaseCucumberSteps, per-scenario steps in report |
| Test UI and API in the same suite | BaseApiTest, fluent ApiClient, JSONPath, schema validation |
| Pin down the exact element, fluently | $("selector").filter().nth().withText() — chainable locators |
| Tests survive CSS and DOM refactors | getByRole / getByText / getByLabel / getByPlaceholder / getByTestId |
| Assertions that don't flake on timing | Web-first assertThat(...).isVisible() — auto-retrying |
| Test admin-and-user flows in one test | withSession("admin", () -> { ... }) — two browsers in one test |
| Verify what actually landed in the DB | db().assertRowExists() / db().query() — plain JDBC, no ORM |
| Assert on the email your app sent | mailbox().waitForEmail(...) — Mailhog, Mailtrap, Outlook, IMAP |
| Skip the browser for non-UI tests | @NoBrowser — DB assertions, API checks, file ops, no WebDriver |
| Run on real cloud browsers unchanged | execution.mode: browserstack / saucelabs — session URL in report |
| Locators that repair themselves | Self-healing fallback strategies when a locator fails |
| Know which tests will flake next | Flakiness prediction — risk scores from run history, radar chart |
| Drive tests from data you already have | @TestData("csv:…" / "excel:…" / "db:SELECT…") |
| Test time-dependent behaviour deterministically | Clock mocking — clock().set(...), JS Date override, auto-reset |
Full API docs and guides live atdocs.seleniumboot.com ↗.
Keep your test code. Delete the plumbing.
Add one dependency and focus on testing — not framework engineering.
<dependency>
<groupId>io.github.seleniumboot</groupId>
<artifactId>selenium-boot</artifactId>
<version>3.9.0</version>
</dependency>Or start from a working project:use the starter template ↗