or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions-matchers.mdcluster-management.mdcore-testing.mddata-generation.mdindex.mdmock-implementations.mdspecialized-testing.md

core-testing.mddocs/

0

# Core Testing Classes

1

2

The core testing classes in `org.elasticsearch.test` provide the foundation for all Elasticsearch testing. These base classes extend Apache Lucene's testing infrastructure with Elasticsearch-specific functionality, random data generation, and cluster management capabilities.

3

4

## ESTestCase

5

6

The primary base class for all Elasticsearch unit tests, extending Lucene's `LuceneTestCase` with Elasticsearch-specific utilities.

7

8

```{ .api }

9

package org.elasticsearch.test;

10

11

import com.carrotsearch.randomizedtesting.RandomizedTest;

12

import org.apache.lucene.tests.util.LuceneTestCase;

13

import org.elasticsearch.common.settings.Settings;

14

import org.elasticsearch.common.util.concurrent.ThreadContext;

15

import org.elasticsearch.core.TimeValue;

16

17

/**

18

* Base class for all Elasticsearch unit tests providing randomized testing utilities,

19

* proper setup/teardown lifecycle, and Elasticsearch-specific test infrastructure.

20

*/

21

@ThreadLeakScope(Scope.NONE)

22

@ThreadLeakFilters(filters = {ESTestCase.ElasticsearchThreadFilter.class})

23

@TimeoutSuite(millis = TimeUnits.HOUR)

24

@LuceneTestCase.SuppressReproduceLine

25

public abstract class ESTestCase extends LuceneTestCase {

26

27

/**

28

* Sets up test environment before each test method.

29

* Initializes logging, thread context, and randomization seeds.

30

*/

31

@Before

32

public void setUp() throws Exception;

33

34

/**

35

* Cleans up test environment after each test method.

36

* Ensures proper resource cleanup and thread termination.

37

*/

38

@After

39

public void tearDown() throws Exception;

40

41

/**

42

* Generates a random string of the specified length using alphanumeric characters.

43

*

44

* @param length the length of the string to generate

45

* @return a random alphanumeric string

46

*/

47

public static String randomAlphaOfLength(int length);

48

49

/**

50

* Generates a random string between the specified minimum and maximum length.

51

*

52

* @param minLength minimum length (inclusive)

53

* @param maxLength maximum length (inclusive)

54

* @return a random alphanumeric string

55

*/

56

public static String randomAlphaOfLengthBetween(int minLength, int maxLength);

57

58

/**

59

* Returns a random integer between min and max (both inclusive).

60

*

61

* @param min minimum value (inclusive)

62

* @param max maximum value (inclusive)

63

* @return random integer in the specified range

64

*/

65

public static int randomIntBetween(int min, int max);

66

67

/**

68

* Returns a random integer scaled by the test multiplier for performance testing.

69

*

70

* @param min minimum value (inclusive)

71

* @param max maximum value (inclusive)

72

* @return scaled random integer

73

*/

74

public static int scaledRandomIntBetween(int min, int max);

75

76

/**

77

* Picks a random element from the provided array.

78

*

79

* @param array array to pick from

80

* @param <T> type of array elements

81

* @return randomly selected element

82

*/

83

public static <T> T randomFrom(T... array);

84

85

/**

86

* Picks a random element from the provided list.

87

*

88

* @param list list to pick from

89

* @param <T> type of list elements

90

* @return randomly selected element

91

*/

92

public static <T> T randomFrom(List<T> list);

93

94

/**

95

* Returns a random boolean value.

96

*

97

* @return true or false with equal probability

98

*/

99

public static boolean randomBoolean();

100

101

/**

102

* Returns a random TimeValue for duration testing.

103

*

104

* @return random TimeValue between 0 and 1 hour

105

*/

106

public static TimeValue randomTimeValue();

107

108

/**

109

* Returns a random long value.

110

*

111

* @return random long value

112

*/

113

public static long randomLong();

114

115

/**

116

* Returns a random non-negative long value.

117

*

118

* @return random non-negative long value

119

*/

120

public static long randomNonNegativeLong();

121

122

/**

123

* Returns a random double value.

124

*

125

* @return random double value

126

*/

127

public static double randomDouble();

128

129

/**

130

* Returns a random float value.

131

*

132

* @return random float value

133

*/

134

public static float randomFloat();

135

136

/**

137

* Returns a random byte value.

138

*

139

* @return random byte value

140

*/

141

public static byte randomByte();

142

143

/**

144

* Returns a random UUID string.

145

*

146

* @return random UUID string

147

*/

148

public static String randomUUID();

149

150

/**

151

* Returns a random identifier string suitable for names/IDs.

152

*

153

* @return random identifier string (8-12 lowercase chars)

154

*/

155

public static String randomIdentifier();

156

157

/**

158

* Returns a random alphanumeric string of the specified length.

159

*

160

* @param length the length of the string to generate

161

* @return random alphanumeric string

162

*/

163

public static String randomAlphanumericOfLength(int length);

164

165

/**

166

* Returns a random unicode string of the specified length.

167

*

168

* @param codeUnits the length in code units

169

* @return random unicode string

170

*/

171

public static String randomUnicodeOfLength(int codeUnits);

172

173

/**

174

* Returns a random value other than the specified input.

175

*

176

* @param input value to exclude

177

* @param randomSupplier supplier for generating random values

178

* @param <T> type of the value

179

* @return random value different from input

180

*/

181

public static <T> T randomValueOtherThan(T input, Supplier<T> randomSupplier);

182

183

/**

184

* Returns a random subset of the provided collection.

185

*

186

* @param collection collection to select from

187

* @param <T> type of collection elements

188

* @return random subset as a list

189

*/

190

public static <T> List<T> randomSubsetOf(Collection<T> collection);

191

192

/**

193

* Waits until the specified condition becomes true or timeout is reached.

194

*

195

* @param breakSupplier condition to wait for

196

* @param maxWaitTime maximum time to wait

197

* @param unit time unit for maxWaitTime

198

* @return true if condition was met, false if timeout

199

*/

200

public static boolean waitUntil(BooleanSupplier breakSupplier, long maxWaitTime, TimeUnit unit);

201

202

/**

203

* Waits until the specified condition becomes true (10 second default timeout).

204

*

205

* @param breakSupplier condition to wait for

206

* @return true if condition was met, false if timeout

207

*/

208

public static boolean waitUntil(BooleanSupplier breakSupplier);

209

}

210

```

211

212

### ESTestCase Usage Examples

213

214

```java

215

import org.elasticsearch.test.ESTestCase;

216

import org.elasticsearch.common.settings.Settings;

217

218

public class MyUnitTest extends ESTestCase {

219

220

public void testRandomDataGeneration() {

221

// Generate random test data

222

String randomName = randomAlphaOfLength(10);

223

int randomPort = randomIntBetween(9200, 9300);

224

boolean randomFlag = randomBoolean();

225

226

// Test with random values

227

MyService service = new MyService(randomName, randomPort, randomFlag);

228

assertThat(service.getName(), equalTo(randomName));

229

assertThat(service.getPort(), allOf(greaterThanOrEqualTo(9200), lessThanOrEqualTo(9300)));

230

}

231

232

public void testSettingsGeneration() {

233

Settings settings = Settings.builder()

234

.put("node.name", randomAlphaOfLength(8))

235

.put("http.port", randomIntBetween(9200, 9299))

236

.put("path.home", createTempDir())

237

.build();

238

239

assertThat(settings.get("node.name"), notNullValue());

240

assertThat(settings.getAsInt("http.port", 0), greaterThan(9199));

241

}

242

243

public void testRandomValueGeneration() {

244

// Generate various random values

245

String uuid = randomUUID();

246

String identifier = randomIdentifier();

247

long randomLong = randomLong();

248

double randomDouble = randomDouble();

249

byte randomByte = randomByte();

250

251

assertThat(uuid, notNullValue());

252

assertThat(identifier.length(), allOf(greaterThanOrEqualTo(8), lessThanOrEqualTo(12)));

253

}

254

255

public void testAsyncOperation() {

256

AtomicBoolean completed = new AtomicBoolean(false);

257

258

// Start async operation

259

myAsyncMethod(() -> completed.set(true));

260

261

// Wait for completion (30 second timeout)

262

boolean success = waitUntil(() -> completed.get(), 30, TimeUnit.SECONDS);

263

264

assertTrue("Operation should complete", success && completed.get());

265

}

266

}

267

```

268

269

## ESIntegTestCase

270

271

Base class for integration tests that require a full Elasticsearch cluster. Manages cluster lifecycle and provides integration testing utilities.

272

273

```{ .api }

274

package org.elasticsearch.test;

275

276

import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;

277

import org.elasticsearch.client.internal.Client;

278

import org.elasticsearch.cluster.health.ClusterHealthStatus;

279

import org.elasticsearch.common.settings.Settings;

280

281

/**

282

* Base class for integration tests providing full Elasticsearch cluster management.

283

* Supports single-node and multi-node cluster configurations with automatic lifecycle management.

284

*/

285

@ClusterScope(scope = Scope.SUITE, numDataNodes = 1)

286

public abstract class ESIntegTestCase extends ESTestCase {

287

288

/**

289

* Defines the scope and configuration for test clusters.

290

*/

291

public static @interface ClusterScope {

292

Scope scope() default Scope.SUITE;

293

int numDataNodes() default -1;

294

int numClientNodes() default 0;

295

boolean autoManageMasterNodes() default true;

296

String[] supportedFeatures() default {};

297

}

298

299

/**

300

* Enumeration of cluster scope options.

301

*/

302

public enum Scope {

303

/** Cluster shared across entire test suite */

304

SUITE,

305

/** New cluster for each test method */

306

TEST

307

}

308

309

/**

310

* Returns the client for interacting with the test cluster.

311

*

312

* @return client instance connected to the test cluster

313

*/

314

public static Client client();

315

316

/**

317

* Returns a client connected to a specific node.

318

*

319

* @param node node name or pattern

320

* @return client for the specified node

321

*/

322

public static Client client(String node);

323

324

/**

325

* Returns the internal test cluster for direct cluster management.

326

*

327

* @return InternalTestCluster instance

328

*/

329

public static InternalTestCluster internalCluster();

330

331

/**

332

* Creates an index with the specified name and default settings.

333

*

334

* @param indices index names to create

335

*/

336

public static void createIndex(String... indices);

337

338

/**

339

* Creates an index with custom settings.

340

*

341

* @param index index name

342

* @param settings index settings

343

*/

344

public static void createIndex(String index, Settings settings);

345

346

/**

347

* Creates an index using a builder for complex configuration.

348

*

349

* @param name index name

350

* @return CreateIndexRequestBuilder for fluent configuration

351

*/

352

public static CreateIndexRequestBuilder prepareCreate(String name);

353

354

/**

355

* Waits for the cluster to reach green health status for the specified indices.

356

*

357

* @param indices indices to wait for (empty means all indices)

358

*/

359

public static void ensureGreen(String... indices);

360

361

/**

362

* Waits for the cluster to reach yellow or green health status.

363

*

364

* @param indices indices to wait for (empty means all indices)

365

*/

366

public static void ensureYellow(String... indices);

367

368

/**

369

* Waits for the cluster to have the specified health status.

370

*

371

* @param status required health status

372

* @param indices indices to check

373

*/

374

public static void ensureHealth(ClusterHealthStatus status, String... indices);

375

376

/**

377

* Refreshes the specified indices to make documents searchable.

378

*

379

* @param indices indices to refresh (empty means all indices)

380

*/

381

public static void refresh(String... indices);

382

383

/**

384

* Flushes the specified indices to persist changes to disk.

385

*

386

* @param indices indices to flush (empty means all indices)

387

*/

388

public static void flush(String... indices);

389

390

/**

391

* Waits for all pending cluster tasks to complete.

392

*

393

* @param timeout maximum time to wait

394

*/

395

public static void waitForPendingTasks(TimeValue timeout);

396

397

/**

398

* Returns the number of nodes in the cluster.

399

*

400

* @return node count

401

*/

402

public static int numNodes();

403

404

/**

405

* Returns settings that should be applied to all nodes in the cluster.

406

* Override this method to customize node configuration.

407

*

408

* @return settings for cluster nodes

409

*/

410

protected Settings nodeSettings(int nodeOrdinal);

411

412

/**

413

* Returns additional plugins that should be installed on cluster nodes.

414

*

415

* @return collection of plugin classes

416

*/

417

protected Collection<Class<? extends Plugin>> nodePlugins();

418

}

419

```

420

421

### ESIntegTestCase Usage Examples

422

423

```java

424

import org.elasticsearch.test.ESIntegTestCase;

425

import org.elasticsearch.action.search.SearchResponse;

426

import org.elasticsearch.index.query.QueryBuilders;

427

428

@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 3)

429

public class MyIntegrationTest extends ESIntegTestCase {

430

431

public void testIndexAndSearch() {

432

// Create index with custom settings

433

createIndex("test-index", Settings.builder()

434

.put("number_of_shards", 2)

435

.put("number_of_replicas", 1)

436

.build());

437

438

ensureGreen("test-index");

439

440

// Index some documents

441

for (int i = 0; i < 10; i++) {

442

client().prepareIndex("test-index")

443

.setId(String.valueOf(i))

444

.setSource("field1", "value" + i, "field2", i)

445

.get();

446

}

447

448

refresh("test-index");

449

450

// Search and verify results

451

SearchResponse response = client().prepareSearch("test-index")

452

.setQuery(QueryBuilders.rangeQuery("field2").gte(5))

453

.get();

454

455

assertThat(response.getHits().getTotalHits().value, equalTo(5L));

456

}

457

458

public void testClusterHealth() {

459

createIndex("health-test");

460

461

// Wait for green status

462

ensureGreen("health-test");

463

464

// Verify cluster is healthy

465

ClusterHealthResponse health = client().admin().cluster()

466

.prepareHealth("health-test")

467

.get();

468

469

assertThat(health.getStatus(), equalTo(ClusterHealthStatus.GREEN));

470

assertThat(health.getNumberOfDataNodes(), greaterThanOrEqualTo(1));

471

}

472

473

@Override

474

protected Settings nodeSettings(int nodeOrdinal) {

475

return Settings.builder()

476

.put(super.nodeSettings(nodeOrdinal))

477

.put("node.attr.custom", "value-" + nodeOrdinal)

478

.build();

479

}

480

481

@Override

482

protected Collection<Class<? extends Plugin>> nodePlugins() {

483

return Arrays.asList(MyTestPlugin.class);

484

}

485

}

486

```

487

488

## SingleNodeTestCase

489

490

Lightweight integration testing base class that runs tests against a single Elasticsearch node. More efficient than full cluster tests when cluster features are not needed.

491

492

```{ .api }

493

package org.elasticsearch.test;

494

495

import org.elasticsearch.client.internal.Client;

496

import org.elasticsearch.node.Node;

497

498

/**

499

* Base class for integration tests that require only a single Elasticsearch node.

500

* Provides faster test execution compared to full cluster tests while still offering

501

* integration testing capabilities.

502

*/

503

public abstract class SingleNodeTestCase extends ESTestCase {

504

505

/**

506

* Returns the client connected to the single test node.

507

*

508

* @return client for the test node

509

*/

510

protected static Client client();

511

512

/**

513

* Returns the test node instance.

514

*

515

* @return Node instance for direct node access

516

*/

517

protected static Node node();

518

519

/**

520

* Creates an index with the specified name.

521

*

522

* @param index index name

523

*/

524

protected static void createIndex(String index);

525

526

/**

527

* Creates an index with custom settings and mappings.

528

*

529

* @param index index name

530

* @param settings index settings

531

* @param mappings index mappings

532

*/

533

protected static void createIndex(String index, Settings settings, String mappings);

534

535

/**

536

* Returns settings for the test node. Override to customize node configuration.

537

*

538

* @return settings for the single test node

539

*/

540

protected Settings nodeSettings();

541

542

/**

543

* Returns plugins to install on the test node.

544

*

545

* @return collection of plugin classes

546

*/

547

protected Collection<Class<? extends Plugin>> getPlugins();

548

}

549

```

550

551

### SingleNodeTestCase Usage Example

552

553

```java

554

import org.elasticsearch.test.SingleNodeTestCase;

555

import org.elasticsearch.action.get.GetResponse;

556

557

public class MySingleNodeTest extends SingleNodeTestCase {

558

559

public void testBasicIndexing() {

560

createIndex("single-node-test");

561

562

// Index a document

563

client().prepareIndex("single-node-test")

564

.setId("1")

565

.setSource("title", "Test Document", "content", "This is a test")

566

.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)

567

.get();

568

569

// Retrieve and verify

570

GetResponse response = client().prepareGet("single-node-test", "1").get();

571

572

assertTrue("Document should exist", response.isExists());

573

assertThat(response.getSource().get("title"), equalTo("Test Document"));

574

}

575

576

@Override

577

protected Settings nodeSettings() {

578

return Settings.builder()

579

.put(super.nodeSettings())

580

.put("xpack.security.enabled", false)

581

.put("xpack.monitoring.enabled", false)

582

.build();

583

}

584

}

585

```

586

587

## TestCluster Interface

588

589

Abstract interface for cluster management used by integration test base classes.

590

591

```{ .api }

592

package org.elasticsearch.test;

593

594

import org.elasticsearch.client.internal.Client;

595

import org.elasticsearch.cluster.node.DiscoveryNode;

596

597

/**

598

* Interface for managing test clusters. Provides abstraction over cluster lifecycle

599

* and client management for different cluster implementations.

600

*/

601

public interface TestCluster extends Closeable {

602

603

/**

604

* Returns a client connected to the cluster.

605

*

606

* @return cluster client

607

*/

608

Client client();

609

610

/**

611

* Returns the number of nodes in the cluster.

612

*

613

* @return node count

614

*/

615

int size();

616

617

/**

618

* Returns the number of data nodes in the cluster.

619

*

620

* @return data node count

621

*/

622

int numDataNodes();

623

624

/**

625

* Returns the cluster name.

626

*

627

* @return cluster name

628

*/

629

String getClusterName();

630

631

/**

632

* Returns information about all nodes in the cluster.

633

*

634

* @return iterable of discovery nodes

635

*/

636

Iterable<DiscoveryNode> getNodes();

637

638

/**

639

* Starts the cluster if not already running.

640

*/

641

void beforeTest(Random random, double transportClientRatio);

642

643

/**

644

* Performs cleanup after test execution.

645

*/

646

void afterTest();

647

648

/**

649

* Wipes the cluster state clean between tests.

650

*/

651

void wipe(Set<String> excludeTemplates);

652

}

653

```

654

655

## Best Practices

656

657

### Test Isolation

658

- Always call `super.setUp()` and `super.tearDown()` in custom setup/teardown methods

659

- Use randomized data to catch edge cases and improve test coverage

660

- Keep tests independent - each test should work regardless of execution order

661

662

### Performance Optimization

663

- Use `SingleNodeTestCase` when cluster features are not needed

664

- Minimize cluster scope - prefer `Scope.TEST` over `Scope.SUITE` when appropriate

665

- Use `@ClusterScope` annotations to configure optimal cluster size

666

667

### Resource Management

668

- Properly clean up resources in tearDown methods

669

- Use try-with-resources for clients and connections

670

- Avoid resource leaks in long-running test suites

671

672

### Randomization

673

- Leverage built-in random data generators for comprehensive testing

674

- Use consistent seeds for reproducible test failures

675

- Combine deterministic assertions with randomized inputs

676

677

The core testing classes provide a solid foundation for all Elasticsearch testing scenarios, from simple unit tests to complex integration scenarios involving multiple nodes and cluster management.