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.