Open-Source Wikis

/

Elasticsearch

/

How to contribute

/

Testing

elastic/elasticsearch

Testing

Elasticsearch has one of the most elaborate testing infrastructures of any open-source Java project. There are several layers; pick the lightest one that exercises the change.

The full reference is TESTING.asciidoc. This page is a high-density tour.

Test types

Type Base class When to use
Unit ESTestCase (test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java) Almost always. Fastest, deterministic, no node started.
Single node ESSingleNodeTestCase Need a real Node (e.g. testing real IndexShard behavior) without the cost of multi-node.
Integration cluster ESIntegTestCase Need real cross-node communication.
REST (Java) ESRestTestCase Black-box against a running cluster.
REST (YAML) ESClientYamlSuiteTestCase Preferred for new REST surface; also runs against the BWC matrix.

The project guidance is: YAML REST tests are preferred for integration/API testing. Use real classes over mocks unless the real class is too heavy (in which case extend with a simplified subclass; mocks/stubs are a last resort and require a comment explaining why).

Unit tests

Unit tests live next to the production code under src/test/java. Naming: *Tests.java (note the trailing 's'). All unit tests extend ESTestCase, which:

  • Seeds a deterministic Random per test from the tests.seed system property.
  • Resets static state and detects thread leaks.
  • Provides helpers like randomAlphaOfLength(), randomFrom(), randomInstantBetween(), mockTransport().

Example:

public class MyServiceTests extends ESTestCase {
    public void testThing() {
        var subject = new MyService(...);
        assertThat(subject.compute(...), equalTo(...));
    }
}

Integration tests

Integration tests use the suffix *IT.java and run via per-module Gradle tasks: internalClusterTest, javaRestTest, yamlRestTest. They start a small in-process cluster (InternalTestCluster) and exercise the full transport + cluster state stack.

./gradlew :server:internalClusterTest --tests org.elasticsearch.cluster.SomeIT
./gradlew :x-pack:plugin:esql:internalClusterTest --tests "org.elasticsearch.xpack.esql.CsvIT.*stats_first_last*"

YAML REST tests

YAML REST tests are the project's preferred form for any change visible at the REST surface. They live under rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/ (default-distribution endpoints) and per-module src/yamlRestTest/resources/.

Each .yml file is a list of named test cases. Skipping based on cluster version uses requires/skip:

'my new endpoint':
  - requires:
      capabilities:
        - method: PUT
          path: /_my/{name}
          capabilities: [my_new_capability]
  - do:
      my.endpoint:
        name: foo
        body: { ... }
  - match: { acknowledged: true }

Run a single YAML case:

./gradlew ":rest-api-spec:yamlRestTest" \
  --tests "org.elasticsearch.test.rest.ClientYamlTestSuiteIT.test {yaml=indices.create/10_basic/Create index}"

ES|QL CSV tests

ES|QL has its own CSV-driven test framework. Each *.csv-spec file under x-pack/plugin/esql/qa/testFixtures/src/main/resources/ is a sequence of <name> blocks each containing an ES|QL query and the expected tabular result. They run via CsvIT:

./gradlew ":x-pack:plugin:esql:internalClusterTest" \
  --tests "org.elasticsearch.xpack.esql.CsvIT.*stats_first_last*"

Append *<test-name>* to target a single test within a file.

BWC and multi-version testing

Elasticsearch ships rolling upgrades and full-cluster restarts. The qa/full-cluster-restart and qa/rolling-upgrade projects start two clusters at different versions and exercise upgrade paths. The :bwc Gradle subprojects build prior majors from source and run the matrix.

Determinism, seeds, and iteration

# Reproduce
-Dtests.seed=DEADBEEF

# Re-run N times (use to flush out flaky tests)
-Dtests.iters=20

# Bypass test cache when re-running with the same seed
-Dtests.timestamp=$(date +%s)

# Tune test JVMs
-Dtests.jvms=8
-Dtests.heap.size=4G
-Dtests.jvm.argline="-verbose:gc"
-Dtests.output=always

Mocking and assertion idioms

  • MockLog (test/framework/src/main/java/org/elasticsearch/test/MockLog.java) — assert that specific log messages were or were not emitted.
  • DeterministicTaskQueue — drive virtual time forward in coordination/scheduling tests.
  • TransportInterceptor and MockTransportService — wrap the transport for failure-injection tests.
  • assertBusy(Runnable) — poll a condition with a timeout for flake-resistant assertions on async behavior.
  • assertAcked, assertHitCount, assertSearchHits — high-level cluster assertions.

Where to put new tests

  • A unit test next to the production class is mandatory for almost every change.
  • If the change is observable through REST, add a YAML REST test (preferred) or a Java REST test.
  • If the change is cross-node, add an integration test in the same module under internalClusterTest.
  • Add to qa/ only when the test crosses module boundaries, exercises packaging, or needs a special fixture (Docker, Kerberos, etc.).

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Testing – Elasticsearch wiki | Factory