diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestSuiteRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestSuiteRepository.java index b4137d70ae1..7d661bffe10 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestSuiteRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestSuiteRepository.java @@ -31,7 +31,7 @@ public class TestSuiteRepository extends EntityRepository { @Override public TestSuite setFields(TestSuite entity, EntityUtil.Fields fields) throws IOException { - entity.setPipeline(fields.contains("pipelines") ? getIngestionPipeline(entity) : null); + entity.setPipelines(fields.contains("pipelines") ? getIngestionPipelines(entity) : null); return entity.withTests(fields.contains("tests") ? getTestCases(entity) : null); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/ChangeEventParser.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/ChangeEventParser.java index eb1a06d0b0d..268a83cb683 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/ChangeEventParser.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/ChangeEventParser.java @@ -180,18 +180,26 @@ public final class ChangeEventParser { } public static String getEntityUrl(PUBLISH_TO publishTo, ChangeEvent event) { + String fqn; + String entityType; EntityInterface entity = (EntityInterface) event.getEntity(); URI urlInstance = entity.getHref(); - String fqn = event.getEntityFullyQualifiedName(); + if (entity instanceof TestCase) { + fqn = ((TestCase) entity).getTestSuite().getFullyQualifiedName(); + entityType = "test-suites"; + } else { + fqn = event.getEntityFullyQualifiedName(); + entityType = event.getEntityType(); + } if (Objects.nonNull(urlInstance)) { String scheme = urlInstance.getScheme(); String host = urlInstance.getHost(); if (publishTo == PUBLISH_TO.SLACK || publishTo == PUBLISH_TO.GCHAT) { - return String.format("<%s://%s/%s/%s|%s>", scheme, host, event.getEntityType(), fqn, fqn); + return String.format("<%s://%s/%s/%s|%s>", scheme, host, entityType, fqn, fqn); } else if (publishTo == PUBLISH_TO.TEAMS) { - return String.format("[%s](%s://%s/%s/%s)", fqn, scheme, host, event.getEntityType(), fqn); + return String.format("[%s](%s://%s/%s/%s)", fqn, scheme, host, entityType, fqn); } else if (publishTo == PUBLISH_TO.EMAIL) { - return String.format("%s://%s/%s/%s", scheme, host, event.getEntityType(), fqn); + return String.format("%s://%s/%s/%s", scheme, host, entityType, fqn); } } return ""; @@ -201,7 +209,13 @@ public final class ChangeEventParser { SlackMessage slackMessage = new SlackMessage(); slackMessage.setUsername(event.getUserName()); if (event.getEntity() != null) { - String headerTxt = "%s posted on " + event.getEntityType() + " %s"; + String eventType; + if ((EntityInterface) event.getEntity() instanceof TestCase) { + eventType = "testSuite"; + } else { + eventType = event.getEntityType(); + } + String headerTxt = "%s posted on " + eventType + " %s"; String headerText = String.format(headerTxt, event.getUserName(), getEntityUrl(PUBLISH_TO.SLACK, event)); slackMessage.setText(headerText); } @@ -594,10 +608,10 @@ public final class ChangeEventParser { if (result != null) { String format = String.format( - "Test Case %s is %s in %s/%s", - getBold(publishTo), + "Test Case status for %s against table/column %s is %s in test suite %s", getBold(publishTo), EntityLink.parse(testCaseEntity.getEntityLink()).getEntityFQN(), + getBold(publishTo), testCaseEntity.getTestSuite().getName()); return String.format(format, testCaseName, result.getTestCaseStatus()); } else { diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/alerts/AlertsURLFormattingTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/alerts/AlertsURLFormattingTest.java new file mode 100644 index 00000000000..d3a9c70499f --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/alerts/AlertsURLFormattingTest.java @@ -0,0 +1,93 @@ +package org.openmetadata.service.alerts; + +import java.net.URI; +import java.util.ArrayList; +import java.util.UUID; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.entity.data.Table; +import org.openmetadata.schema.tests.TestCase; +import org.openmetadata.schema.type.ChangeEvent; +import org.openmetadata.schema.type.Column; +import org.openmetadata.schema.type.ColumnDataType; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.EventType; +import org.openmetadata.service.util.ChangeEventParser; + +public class AlertsURLFormattingTest { + + private static ChangeEvent testCaseChangeEvent; + private static ChangeEvent tableChangeEvent; + + @BeforeAll + static void setUp() { + UUID testCaseId = UUID.randomUUID(); + UUID tableId = UUID.randomUUID(); + testCaseChangeEvent = + new ChangeEvent() + .withEventType(EventType.ENTITY_UPDATED) + .withEntityType("TestCase") + .withEntityId(UUID.randomUUID()) + .withEntityFullyQualifiedName("UnitTest.TestCase") + .withUserName("UnitTestUser") + .withTimestamp(System.currentTimeMillis()) + .withEntity( + new TestCase() + .withName("TestCaseForUnitTest") + .withId(testCaseId) + .withFullyQualifiedName("UnitTest.TestCase") + .withEntityLink("<#E::table::Table.For.UnitTest>") + .withEntityFQN("Table.For.UnitTest") + .withHref(URI.create(String.format("http://localhost:8080/api/v1/testCase/%s", testCaseId))) + .withTestSuite( + new EntityReference() + .withId(UUID.randomUUID()) + .withName("TestSuiteForUnitTest") + .withFullyQualifiedName("UnitTest.TestSuite"))); + + ArrayList columns = new ArrayList<>(); + + for (int i = 0; i < 3; i++) { + columns.add( + new Column() + .withName("col" + i) + .withDataType(ColumnDataType.INT) + .withFullyQualifiedName("database.TableForUnitTest.col" + i)); + } + columns.add( + new Column() + .withName("col1") + .withDataType(ColumnDataType.INT) + .withFullyQualifiedName("database.TableForUnitTest.col1")); + + tableChangeEvent = + new ChangeEvent() + .withEventType(EventType.ENTITY_UPDATED) + .withEntityType("table") + .withEntityId(UUID.randomUUID()) + .withEntityFullyQualifiedName("UnitTestService.database.TableForUnitTest") + .withUserName("UnitTestUser") + .withTimestamp(System.currentTimeMillis()) + .withEntity( + new Table() + .withId(tableId) + .withName("database.TableForUnitTest") + .withFullyQualifiedName("UnitTestService.database.TableForUnitTest") + .withHref(URI.create(String.format("http://localhost:8080/api/v1/table/%s", tableId))) + .withColumns(columns) + .withDatabase( + new EntityReference() + .withId(UUID.randomUUID()) + .withName("database") + .withFullyQualifiedName("UnitTestService.database"))); + } + + @Test + void testAlertsSlackURLFormatting() { + String testCaseUrl = ChangeEventParser.getEntityUrl(ChangeEventParser.PUBLISH_TO.SLACK, testCaseChangeEvent); + assert testCaseUrl.equals(""); + String tableUrl = ChangeEventParser.getEntityUrl(ChangeEventParser.PUBLISH_TO.SLACK, tableChangeEvent); + assert tableUrl.equals( + ""); + } +} diff --git a/openmetadata-spec/src/main/resources/json/schema/tests/testSuite.json b/openmetadata-spec/src/main/resources/json/schema/tests/testSuite.json index 6f3479f54fe..c069286d072 100644 --- a/openmetadata-spec/src/main/resources/json/schema/tests/testSuite.json +++ b/openmetadata-spec/src/main/resources/json/schema/tests/testSuite.json @@ -5,8 +5,22 @@ "description": "TestSuite is a set of test cases to capture data quality tests against data entities.", "type": "object", "javaType": "org.openmetadata.schema.tests.TestSuite", - "javaInterfaces": ["org.openmetadata.schema.EntityInterface"], - "definitions": {}, + "javaInterfaces": [ + "org.openmetadata.schema.ServiceEntityInterface" + ], + "definitions": { + "testSuiteConnection": { + "type": "object", + "javaInterfaces": [ + "org.openmetadata.schema.ServiceConnectionEntityInterface" + ], + "properties": { + "config": { + "type": "null" + } + } + } + }, "properties": { "id": { "description": "Unique identifier of this test suite instance.", @@ -35,11 +49,24 @@ }, "default": null }, - "pipeline": { + "connection": { + "$ref": "#/definitions/testSuiteConnection" + }, + "testConnectionResult": { + "$ref": "../entity/services/connections/testConnectionResult.json" + }, + "pipelines": { "description": "References to pipelines deployed for this database service to extract metadata, usage, lineage etc..", - "$ref": "../type/entityReference.json", + "$ref": "../type/entityReference.json#/definitions/entityReferenceList", "default": null }, + "serviceType": { + "description": "Type of database service such as MySQL, BigQuery, Snowflake, Redshift, Postgres...", + "javaInterfaces": ["org.openmetadata.schema.EnumInterface"], + "type": "string", + "enum": ["TestSuite"], + "default": "TestSuite" + }, "owner": { "description": "Owner of this TestCase definition.", "$ref": "../type/entityReference.json",