skip to content

[ compare · web testing frameworks ]

e2e vs selenium

Selenium and e2e both drive real browsers from code. Selenium is the WebDriver standard in Java, Python, C#, Ruby, and JavaScript, with a test framework of your choice on top. e2e is a TypeScript and JavaScript test framework with the runner, retrying assertions, and agent goals built in, on web and native mobile.

[ at a glance ]

what each tool is.

  • made by, license

    [ e2e ]

    e2e, Apache-2.0

    [ selenium ]

    The Selenium project under the Software Freedom Conservancy; Apache-2.0

  • browsers

    [ e2e ]

    Chromium, Firefox, WebKit (Safari's engine) through Playwright; iOS and Android apps through agent-device

    [ selenium ]

    Chrome, Edge, Firefox, Safari through each vendor's driver; mobile browsers and native apps through Appium

  • languages

    [ e2e ]

    TypeScript, JavaScript

    [ selenium ]

    Java, Python, C#, Ruby, JavaScript

  • what it includes

    [ e2e ]

    Runner, locators, assertions, agent steps, reporters, trace pages, video, replay cache

    [ selenium ]

    WebDriver, Grid, IDE, Selenium Manager, BiDi; assertions and reports come from your test framework

  • waits

    [ e2e ]

    Actions wait for their target, assertions retry until they pass or time out, and agent.waitFor waits for a condition in plain language

    [ selenium ]

    Implicit and explicit waits you write, with WebDriverWait and expected conditions

  • when ai is used

    [ e2e ]

    At run time, when a step needs it. Verified goals replay without model calls.

    [ selenium ]

    Nowhere

  • parallel runs

    [ e2e ]

    Workers and shards; web({ connect }) to a remote Chromium; browser providers such as Kernel, smol, Lightpanda, TestMu AI

    [ selenium ]

    Selenium Grid and the device clouds that speak WebDriver

[ the same test ]

the same test,written both ways.

selenium
driver.get("http://localhost:3000/login");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(visibilityOfElementLocated(By.id("username"))).sendKeys("admin@example.test");
driver.findElement(By.id("password")).sendKeys(System.getenv("ADMIN_PASSWORD"));
driver.findElement(By.xpath("//button[contains(., 'Sign in')]")).click();
wait.until(urlContains("/dashboard"));
assertEquals("Welcome back, admin!",
    driver.findElement(By.cssSelector(".greeting")).getText());
e2e
import { test } from '@e2e-dev/web';
import { expect, credentials } from 'e2e';

test('signs in', async ({ app, agent, browser }) => {
  const admin = credentials.user('admin');
  await app.open('/login');
  await agent.act('sign in as {username}', { params: { username: admin.username, password: admin.password } });
  await expect(browser).toHaveURL('/dashboard');
  await agent.assert('the page greets admin by name');
});

The sign-in becomes one goal, with the password passed as a credential the model never sees. The URL check stays exact, and the agent judges the greeting. The migration guide shows the fully scripted version too, with one screen line for each findElement.

[ differences ]

the five main differences.

  • what you get in the package

    Selenium's documentation says it plainly: WebDriver does not know a thing about testing. It does not compare things, assert pass or fail, or report. You bring JUnit, pytest, or Mocha, a reporter, and a retry strategy.

    e2e is the whole stack in one package: runner, locators, assertions, fixtures, reporters for list, JSON, JUnit, and markdown output, a trace page per failed test, video, and a pull request comment reporter.

  • waits

    Selenium has implicit waits, off by default, explicit WebDriverWait with expected conditions, and fluent waits. Its docs warn not to mix the first two.

    In e2e, a locator action waits for its target, and expect retries until the assertion passes or assertionTimeout ends. Explicit sleeps are not needed, and agent.waitFor waits for a condition in plain language.

  • finding elements

    Selenium finds elements by id, name, CSS, XPath, and link text, and findElement acts on the first match.

    e2e queries by role, label, text, and test id. A string must match the whole name, and several matches fail the step. CSS and XPath still work through browser.locator when nothing else can name a node, which makes that test web only.

  • when ai is used

    Selenium has no agent layer. A test is the clicks you scripted.

    e2e adds agent.act goals. The first run of a goal uses the model, a later passing assertion saves the clicks as a recording, and every run after that replays it with no model call. If the UI changes, the agent takes over for that goal and saves a new recording. A test with no agent steps never calls a model.

  • languages, browsers, and scale

    Selenium runs in five languages, drives the browsers your users run through vendor drivers, and scales through Grid and the device clouds built on it.

    e2e tests are TypeScript or JavaScript and drive Chromium, Firefox, and WebKit, the engine behind Safari. Parallel runs use workers and shards, remote browsers come through CDP or a browser provider, and native iOS and Android run from the same test file instead of a second project on Appium.

01 / 05

[ side by side ]

feature by feature.

Selenium leads on reach: five languages, Grid, and twenty years of tooling built on WebDriver. e2e leads where one suite covers web and native mobile, where waits and selectors take the most time, and where a check is a question in plain language rather than a selector.

  • native mobile

    [ e2e ]

    [ e2e ]

    The same test file on iOS and Android

    [ selenium ]

    Appium, a separate project and suite

  • writing a test

    [ e2e ]

    [ e2e ]

    One agent.act goal in plain language, checked by an exact assertion, or one screen line per step

    [ selenium ]

    Each step is a findElement and an action in code

  • when the ui changes

    [ e2e ]

    [ e2e ]

    The agent finishes the goal from the changed screen; the runner saves a new recording

    [ selenium ]

    The test fails; fix the selectors

  • waits

    [ e2e ]

    [ e2e ]

    Actions wait, assertions retry

    [ selenium ]

    Implicit, explicit, and fluent waits you write

  • ai assertions

    [ e2e ]

    [ e2e ]

    agent.assert, agent.waitFor, and agent.extract with a schema; vision for drawn content

    [ selenium ]

    Value assertions from your test framework; no model-judged check

  • exploratory testing

    [ e2e ]

    [ e2e ]

    e2e explore runs from a goal and reports findings; a bug bash turns findings into failing repro tests

    [ selenium ]

    Selenium IDE records and plays back what you click

  • runner and reports

    [ e2e ]

    [ e2e ]

    Built in: JUnit, JSON, markdown, trace.md, video, pull request comment

    [ selenium ]

    Your test framework and reporter

  • finding elements

    [ even ]

    [ e2e ]

    Role, label, text, and test id queries, whole-string match; CSS and XPath through browser.locator

    [ selenium ]

    id, name, CSS, XPath, and link text; findElement takes the first match

  • browsers

    [ even ]

    [ e2e ]

    Chromium, Firefox, and WebKit builds through Playwright; WebKit is Safari's engine, not Safari itself

    [ selenium ]

    Chrome, Edge, Firefox, and Safari itself, each through its vendor's driver

  • languages

    [ selenium ]

    [ e2e ]

    TypeScript, JavaScript

    [ selenium ]

    Java, Python, C#, Ruby, JavaScript

  • parallel runs

    [ selenium ]

    [ e2e ]

    Workers, shards, CDP connect, browser providers

    [ selenium ]

    Grid with router, distributor, and nodes; device clouds

  • windows and popups

    [ selenium ]

    [ e2e ]

    Dialogs through browser.onDialog; windows the app opens are not driven yet

    [ selenium ]

    switchTo().window(), alert handling

  • automation outside tests

    [ selenium ]

    [ e2e ]

    A test runner; automation lives inside tests

    [ selenium ]

    A WebDriver client any program can call

[ which one ]

which one to pick.

pick by the job in front of you: first the jobs where e2e is the better choice, then the jobs where selenium is the better choice.

  • A new suite in TypeScript or JavaScript

    [ e2e ]

    The runner, assertions, traces, and reports come in one package.

  • A suite whose maintenance is mostly explicit waits and selector updates

    [ e2e ]

    The explicit waits go: actions wait for their target and assertions retry. A step rewritten as an agent.act goal follows UI changes; a locator step keeps its selector.

  • One suite for web and native mobile

    [ e2e ]

    The same test file runs on iOS and Android; Selenium needs a second project on Appium.

  • Goals an agent completes beside exact checks

    [ e2e ]

    Verified goals replay without model calls; Selenium has no agent layer.

  • A suite and a team in Java, Python, C#, or Ruby

    [ selenium ]

    e2e tests are TypeScript or JavaScript.

  • Browser builds only a vendor driver reaches

    [ selenium ]

    Selenium drives each vendor's browser through its own driver; e2e drives Chromium, Firefox, and WebKit (Safari's engine) builds.

  • Grid or a device cloud that speaks WebDriver

    [ selenium ]

    Infrastructure worth keeping; e2e uses workers, shards, CDP, and browser providers instead.

  • Browser automation that is not a test, such as a script or a bot

    [ selenium ]

    Selenium is a WebDriver client any program can call; e2e is a test runner.

[ switching ]

run both, move one flow at a time.

  1. [step 1]

    Run npx e2e init in the app, or in an e2e/ folder with its own package.json beside a Java or Python suite.

  2. [step 2]

    Set app.url to the url every driver.get used, and move passwords and tokens into credentials or secrets.

  3. [step 3]

    Rewrite one page object and the flows that use it. Prefer role and label queries, replace every wait with a locator assertion, and run npx e2e run. Keep the Selenium tests until the new ones pass. The agent prompt at the top of the guide does the rewrite, and the migrate-to-e2e skill tracks a migration across sessions.

The migration guide maps every API. Rolling e2e out across a larger team? Book a call and the e2e team sets it up with you.

[ faq ]

questions.

what people on selenium ask before they add e2e.

[001]can e2e run my java or python selenium tests?

No. e2e tests are TypeScript or JavaScript, so a Java or Python suite is rewritten one page object and its flows at a time, with both suites running in the meantime. The migration guide maps each WebDriver call.

[002]what's the difference between e2e and selenium?

Selenium is a browser automation standard in five languages; the test framework, waits, and reports are yours to choose. e2e is one framework with the runner, retrying assertions, traces, and agent goals built in, on web and native mobile.

[003]how does e2e replace explicit waits?

Locator actions wait for their target, and assertions retry until they pass or time out. Thread.sleep and WebDriverWait have no counterpart.

[004]does e2e need an ai model?

Only for agent steps. A test with only locator steps runs without one. Agent steps take a subscription you already pay for, an API key, or a local model.

[005]what about selenium grid?

e2e runs tests in parallel with workers and across machines with --shard. web({ connect }) attaches to a remote Chromium over CDP, and providers lease hosted browsers from Kernel, smol, Lightpanda, or TestMu AI.

[006]can i keep css and xpath selectors?

Yes, through browser.locator('css or xpath'), which makes that test web only. Role, label, and test id queries on screen run on every target, mobile included.

ask anything else

facts checked 30 october 2026 against selenium.dev (selenium 4.52) and the e2e docs. something out of date? open an issue on github.

[ get started ]

your verificationlayerstarts withjust one command

npx e2e@latest init