* fix(search): column bulk operations search not returning results at scale When searching by column name pattern (e.g., "MAT") in column bulk operations, the composite aggregation returned ALL column names from matching documents, then post-filtered in Java. With 20000+ columns, the first composite page of 25 names rarely contained matches, so users saw 0 results. Switch to terms aggregation with `include` regex when a search pattern is set. This filters at the ES/OS aggregation level — only matching column names produce buckets. Two-phase approach: (1) lightweight names query to get all matching names + accurate total, (2) targeted data query with top_hits for the current page only. * test(search): add integration tests for column pattern search regex against ES |
||
|---|---|---|
| .. | ||
| src/test | ||
| K8S_TESTS.md | ||
| pom.xml | ||
| README.md | ||
| TEST_MIGRATION_TRACKER.md | ||
OpenMetadata Integration Tests
This module contains SDK-based integration tests that run against a real OpenMetadata server using Testcontainers. Tests execute in parallel and are isolated using TestNamespace.
Quick Start
# Run all tests with MySQL + Elasticsearch (default)
mvn test -pl :openmetadata-integration-tests
# Run with PostgreSQL + OpenSearch
mvn test -pl :openmetadata-integration-tests -Ppostgres-opensearch
# Run a specific test
mvn test -pl :openmetadata-integration-tests -Dtest="TableResourceIT"
Available Profiles
| Profile | Database | Search Engine |
|---|---|---|
mysql-elasticsearch (default) |
MySQL 8.3.0 | Elasticsearch 8.11.4 |
postgres-opensearch |
PostgreSQL 15 | OpenSearch 2.19.0 |
postgres-elasticsearch |
PostgreSQL 15 | Elasticsearch 8.11.4 |
mysql-opensearch |
MySQL 8.3.0 | OpenSearch 2.19.0 |
Writing a New Integration Test
1. Create the Test Class
Extend BaseEntityIT for entity CRUD tests or create a standalone test class:
package org.openmetadata.it.tests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.schema.api.data.CreateTable;
import org.openmetadata.schema.entity.data.Table;
public class MyFeatureIT extends BaseEntityIT<Table, CreateTable> {
@Override
protected String getEntityType() {
return "table";
}
@Override
protected Table createEntity(CreateTable request) {
return SdkClients.adminClient().tables().create(request);
}
@Override
protected CreateTable createRequest(String name, TestNamespace ns) {
return new CreateTable()
.withName(name)
.withDatabaseSchema(SharedEntities.getSchema().getFullyQualifiedName())
.withColumns(List.of(new Column().withName("id").withDataType(ColumnDataType.INT)));
}
@Test
void myCustomTest(TestNamespace ns) throws Exception {
CreateTable request = createRequest(ns.prefix("myTable"), ns);
Table table = createEntity(request);
assertNotNull(table.getId());
assertEquals(request.getName(), table.getName());
}
}
2. Key Concepts
TestNamespace
Every test method receives a TestNamespace parameter that provides unique prefixes for entity names:
@Test
void myTest(TestNamespace ns) {
String uniqueName = ns.prefix("myEntity"); // e.g., "abc123_myEntity"
}
This ensures tests don't conflict when running in parallel.
SdkClients
Get pre-configured SDK clients for different users:
OpenMetadataClient adminClient = SdkClients.adminClient();
OpenMetadataClient user1Client = SdkClients.user1Client();
OpenMetadataClient botClient = SdkClients.botClient();
SharedEntities
Access pre-created entities for tests:
DatabaseService service = SharedEntities.getService();
Database database = SharedEntities.getDatabase();
DatabaseSchema schema = SharedEntities.getSchema();
User adminUser = SharedEntities.getAdminUser();
3. BaseEntityIT Features
When extending BaseEntityIT, you get these tests automatically:
| Test | Description |
|---|---|
post_entityCreate_200 |
Create entity successfully |
get_entity_200_OK |
Get entity by ID |
get_entityByName_200 |
Get entity by FQN |
get_entityNotFound_404 |
Get non-existent entity |
put_entityCreate_200 |
Create via PUT |
patch_entityAttributes_200 |
Patch entity attributes |
delete_entityAsAdmin_200 |
Delete entity |
get_entityListWithPagination_200 |
List with pagination |
test_sdkCRUDOperations |
Full CRUD via SDK |
| ... and 30+ more |
4. Controlling Test Behavior
Use flags to customize which inherited tests run:
public class MyEntityIT extends BaseEntityIT<MyEntity, CreateMyEntity> {
{
supportsPatch = true; // Enable PATCH tests
supportsTags = true; // Enable tag tests
supportsOwner = true; // Enable owner tests
supportsSearchIndex = true; // Enable search tests
supportsDomains = true; // Enable domain tests
}
}
5. Best Practices
- Use
TestNamespace.prefix()for all entity names to ensure uniqueness - Don't clean up entities - TestNamespace isolation handles this
- Use specific imports - No wildcard imports (
import static ....*) - Keep tests independent - Don't rely on order of execution
- Use Awaitility for async operations - Not
Thread.sleep()
Awaitility.await()
.atMost(Duration.ofSeconds(30))
.pollInterval(Duration.ofMillis(500))
.until(() -> someCondition());
- Avoid single-line comments - Write self-documenting code
Project Structure
openmetadata-integration-tests/
├── src/test/java/org/openmetadata/it/
│ ├── auth/ # JWT token generation
│ ├── env/ # Test infrastructure (TestSuiteBootstrap)
│ ├── factories/ # Entity factory classes
│ ├── tests/ # Integration test classes
│ └── util/ # Utilities (SdkClients, TestNamespace)
└── src/test/resources/
├── openmetadata-secure-test.yaml # Test config
└── *.der # JWT keys
Test Infrastructure
Tests use TestSuiteBootstrap (a JUnit LauncherSessionListener) that:
- Starts database container (MySQL or PostgreSQL)
- Starts search container (Elasticsearch or OpenSearch)
- Starts Fuseki SPARQL container (for RDF tests)
- Starts the OpenMetadata application
- Initializes
SharedEntities
All containers are started once per test run and shared across all tests.
Running in CI
GitHub workflows run these tests on every PR:
integration-tests-mysql-elasticsearch.yml- MySQL + Elasticsearchintegration-tests-postgres-opensearch.yml- PostgreSQL + OpenSearch
Tests require the "safe to test" label on PRs.