Selenium

repository·trunk·Indexed 12 days ago

https://github.com/SeleniumHQ/selenium

An umbrella project providing infrastructure for the W3C WebDriver specification, enabling web browser automation across all major browsers via a language-neutral interface. It provides language bindings for .NET (Selenium.WebDriver), Java (selenium-java), and JavaScript (selenium-webdriver).

Tokens
49.2K
Snippets
169
Records
233
Agent score
98%

What's inside Selenium

  1. Explore the Selenium .NET API Modules

    trunk

    The Selenium .NET API is divided into two primary modules that provide different levels of functionality for browser automation:

    1. Selenium.WebDriver: The core module containing the primary WebDriver interfaces and classes used to control web browsers.
    2. Selenium.Support: A module providing additional helper classes, extensions, and support structures to simplify common automation tasks and enhance the core WebDriver functionality.
  2. Understand the Selenium 5 Release Goals

    trunk
    Selenium 5 is a focused alignment release designed to ensure that all language bindings (Java, JavaScript, Python, Ruby, and .NET) converge on consistent behavior. The primary goal is cross-binding consistency rather than introducing gratuitous breaking changes. The release follows the standard deprecation policy: a replacement is provided, the old path is marked as deprecated, and it is removed only after two subsequent releases.
  3. Access low-level BiDi features via composition

    trunk

    To prevent confusion between supported Selenium APIs and unsupported BiDi implementation details, low-level access is provided via composition rather than as a member of the driver object.

    Accessing a feature directly from the driver (e.g., driver.bidi) is considered an internal exposure and is not the intended way to interact with the protocol. Instead, you should compose the protocol module with the driver instance.

    Example (Ruby):

    • Supported (Neutral API): driver.network.add_request_handler(...) — This is the correct way to use high-level, protocol-neutral features.
    • Internal (Unsupported): BiDi::Protocol::Network.new(driver).add_intercept(...) — This is how you access the raw BiDi implementation via composition.
    • Forbidden Pattern: driver.bidi.network.add_intercept(...) — This pattern is rejected because anything reachable directly off the driver is implicitly treated as a supported Selenium API.
    # supported — neutral, returns no BiDi type
    driver.network.add_request_handler(...)                
    
    # internal — composed with the driver, unsupported
    BiDi::Protocol::Network.new(driver).add_intercept(...) 
    
    # not allowed — internal exposed as a driver member
    driver.bidi.network.add_intercept(...)                 
  4. Use built-in pytest fixtures for Selenium testing

    trunk

    The Python test suite provides several fixtures to simplify setup and teardown. Shared fixtures are located in conftest.py, while module-specific fixtures are defined within the test files themselves.

    FixtureDescription
    driverWebDriver instance, auto-parametrized by browser
    pagesLoad test pages: pages.load("page.html") or pages.url("page.html")
    webserverTest HTTP server reference
    clean_driverFresh driver without parametrization
    clean_optionsFresh browser options instance
  5. Manage Driver Lifecycle with annotations

    trunk

    The shared driver is reused across tests for efficiency. Use these annotations to control when the driver is restarted or destroyed. Annotations accept value (browser) and reason.

    AnnotationBehavior
    @NeedsFreshDriverRestarts the driver before the test to ensure a clean browser state with default capabilities.
    @NoDriverBeforeTestDriver is destroyed before the test. Use createNewDriver(capabilities) inside the test to create one with custom capabilities.
    @NoDriverAfterTestRestarts the driver after the test because the test leaves the browser in a bad state. Supports failedOnly.

    Important Implementation Rules:

    • Avoid direct instantiation: Never use new ChromeDriver(). Always use WebDriverBuilder or createNewDriver(capabilities). The builder respects the browser target defined by Bazel.
    • Manual Creation: If createNewDriver(capabilities) is called without an annotation, it closes the current driver and creates a new one.
  6. Understand Ruby test organization and naming

    trunk

    Tests are organized into unit and integration suites. All test files must follow the naming convention of ending in _spec.rb (e.g., driver_spec.rb).

    Directory Structure:

    • rb/spec/unit/: Unit tests that do not require a browser.
    • rb/spec/integration/: Integration tests involving browsers (Chrome, Firefox, Safari, Bidi) and spec_support helpers.
  7. Manage Browser Drivers with Selenium Manager

    trunk

    Selenium requires a driver (e.g., chromedriver, edgedriver, geckodriver) to interface with the chosen browser.

    Modern versions of Selenium automatically handle browser and driver installation using Selenium Manager. You generally do not need to manually download drivers or add them to your system PATH; Selenium Manager handles this when you instantiate a WebDriver.

    If Selenium Manager does not meet your specific needs, you can still manually install and specify browsers and drivers.

  8. How Kubernetes browser Jobs work

    trunk

    When a WebDriver session is requested in a Kubernetes-enabled Grid:

    1. Matching: The Node matches requested capabilities to a configured image or ConfigMap template.
    2. Job Creation: A Kubernetes Job is created with a unique name (browser name + timestamp).
    3. Monitoring: The Node watches the Pod for a Running state and detects early errors like ImagePullBackOff.
    4. Connectivity: If a remote cluster URL was provided, the Node establishes a local port-forward to the browser Pod.
    5. Readiness: The Node polls the browser server's /status endpoint until it returns HTTP 200.
    6. Session Start: The session is created against the browser and the ID is returned to the client.
    7. Cleanup: When the session ends, the Node saves Pod logs, relocates video files to the session directory, and deletes the Job.
  9. Optimize Bazel with Worktrees and Caches

    trunk

    To avoid re-downloading dependencies and rebuilding artifacts when using multiple Git worktrees, configure shared Bazel caches in your global ~/.bazelrc:

    • --disk_cache: Stores compiled action outputs.
    • --repository_cache: Stores downloaded external dependencies.

    Note: These directories grow unbounded and should be pruned periodically. Keep them on the same filesystem as your checkouts to allow Bazel to use hardlinks.

    Self-cleaning Worktrees (macOS/Linux)

    To prevent the Bazel output base from leaking disk space when deleting worktrees, point the output base inside the worktree by adding this to the worktree's .bazelrc.local: startup --output_base=.local/output-base.

    Windows Note

    Do not nest the output base inside the repo on Windows due to path-length limits. Instead, use startup --output_user_root=C:/tmp in selenium/.bazelrc.windows.local.

    # Add to ~/.bazelrc
    common --disk_cache=/path/to/your/home/.cache/bazel-disk
    common --repository_cache=/path/to/your/home/.cache/bazel-repo
    
    # Add to worktree/.bazelrc.local (macOS/Linux)
    startup --output_base=.local/output-base