Java Testing Guide

This guide helps contributors write tests in the Selenium Java codebase.

Test Framework

  • Browser tests use JUnit 5 (Jupiter) and extend JupiterTestBase.
  • Test HTML pages live in common/src/web/.
  • pages field gets URLs from java/test/org/openqa/selenium/testing/Pages.java.
  • There are 2 pre-configured wait methods for 5 seconds and 10 seconds.
  • Assertions use the AssertJ library.
class MyFeatureTest extends JupiterTestBase {
    @Test
    void testBasicFunctionality() {
        driver.get(pages.xhtmlTestPage);

        wait.until(ExpectedConditions.titleIs("XHTML Test Page"));  // 10s timeout
        shortWait.until(ExpectedConditions.elementToBeClickable(element));  // 5s timeout

        assertThat(driver.getTitle()).isEqualTo("XHTML Test Page");
    }

    @Test
    void testWithLocalDriver() {
        localDriver = new ChromeDriver();
        localDriver.get(pages.xhtmlTestPage);
        wait(localDriver).until(ExpectedConditions.titleIs("XHTML Test Page"));  // creates 10s wait
    }
}

Running Tests

Bazel creates separate test targets for browsers and remote grid depending on what is supported in the BUILD.bazel file in that test's directory. Tests run in parallel by default.

bazel test //java/...  # Run all Java tests
bazel test //java/test/org/openqa/selenium/bidi/... # Run all tests in bidi directory
bazel test //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest # Run a specific test

# Test Filters
bazel test //java/... --test_size_filters=small   # unit tests only (no browser)
bazel test //java/... --test_size_filters=large   # all browser tests
bazel test //java/... --test_tag_filters=chrome   # chrome tests only
bazel test //java/... --test_tag_filters=remote-browser  # all browser tests that run on grid
bazel test //java/... --test_tag_filters=-safari  # no safari tests (use `-` to exclude a tag)

# Additional Arguments
bazel test //java/... --pin_browsers  # Use pinned browser versions (recommended)
bazel test //java/... --flaky_test_attempts=3 # Rerun failed tests up to 3 times
bazel test //java/... --test_output=all # displays all test output at end of run
bazel test //java/... --test_output=streamed # displays test output in real time (disables parallel execution)

Annotations

Valid Browser values: CHROME, EDGE, FIREFOX, SAFARI, IE, ALL. (Default is ALL)

Skipping and Expected Failures

These accept parameters for value (browser name) and reason. Each browser on a separate line.

AnnotationWhen to Use
@IgnoreTest doesn't work for a browser. Also accepts issue (GitHub issue, e.g. "#1234") and gitHubActions (only skip on CI).
@NotYetImplementedFeature isn't implemented yet. Test always runs and passes if it fails, and fails if it unexpectedly passes so the annotation can be removed.

Driver Lifecycle

The shared driver is reused across tests for efficiency. These annotations control that behavior. They accept value (browser) and reason.

AnnotationWhen to Use
@NeedsFreshDriverTest needs clean browser state with default capabilities. Driver is restarted before the test.
@NoDriverBeforeTestTest needs custom capabilities or tests driver creation itself. Driver is destroyed, must use createNewDriver(capabilities) in the test to create one.
@NoDriverAfterTestTest leaves browser in a bad state. Driver is restarted after the test. Also accepts failedOnly.

For tests needing two browsers simultaneously (e.g., multi-user scenarios), create a second instance with localDriver = new ChromeDriver(). This driver is automatically quit after the test.

If createNewDriver(capabilities) is called without an annotation, it closes the current driver and creates a new one.

Be careful with hard-coding the creation of new drivers since it may conflict with the current Bazel target.

Other

AnnotationWhen to Use
@SwitchToTopAfterTestTest navigates into frames. Automatically switches to default content after.
@NeedsSecureServerClass-level. All tests in the class need HTTPS.

Build files

  • Adding tests shouldn't require changes in Bazel files since most are picked up automatically.
  • Make sure the *Test.java file is in a directory that has a BUILD.bazel file with a java_selenium_test_suite declaration.