From b7e366d885f79aa56cdb1f8a70982d55552e728c Mon Sep 17 00:00:00 2001 From: MiriamKyoseva Date: Fri, 31 May 2024 14:56:19 +0300 Subject: [PATCH 1/5] Updated Bellatrix.Core plugin logic Added TestDurationWatcher and TimeRecord for tests --- .../bellatrix/core/plugins/Plugin.java | 17 +++++++++++ .../core/plugins/PluginExecutionEngine.java | 27 +++++++++++++++++ .../bellatrix/core/plugins/TimeRecord.java | 27 +++++++++++++++++ .../core/plugins/junit/BaseTest.java | 6 +++- .../plugins/junit/TestDurationWatcher.java | 29 +++++++++++++++++++ .../core/plugins/junit/TestResultWatcher.java | 16 +++++++--- .../core/plugins/testng/BaseTest.java | 9 ++++-- .../plugins/testng/TestResultListener.java | 4 +++ 8 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/TimeRecord.java create mode 100644 bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestDurationWatcher.java diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java index ad91978e..ad1b759a 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java @@ -36,15 +36,32 @@ public void preBeforeTest(TestResult testResult, Method memberInfo) throws Excep public void postBeforeTest(TestResult testResult, Method memberInfo) { } + public void beforeTestFailed(Exception e) throws Exception { } + /** + * Deprecated.
+ * Use {@link #preAfterTest(TestResult, TimeRecord, Method)} as it offers more information about the test. + */ + @Deprecated public void preAfterTest(TestResult testResult, Method memberInfo) throws IOException { } + public void preAfterTest(TestResult testResult, TimeRecord timeRecord, Method memberInfo) throws IOException { + } + + /** + * Deprecated.
+ * Use {@link #postAfterTest(TestResult, TimeRecord, Method, Throwable)} as it offers more information about the test. + */ + @Deprecated public void postAfterTest(TestResult testResult, Method memberInfo, Throwable failedTestException) { } + public void postAfterTest(TestResult testResult, TimeRecord timeRecord, Method memberInfo, Throwable failedTestException) { + } + public void afterTestFailed(Exception e) { } diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java index 448e18e2..cd03f289 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java @@ -13,6 +13,8 @@ package solutions.bellatrix.core.plugins; +import org.apache.http.annotation.Obsolete; + import java.lang.reflect.Method; import java.util.HashSet; import java.util.LinkedHashSet; @@ -68,6 +70,7 @@ public static void postBeforeTest(TestResult result, Method memberInfo) { } } + public static void beforeTestFailed(Exception e) throws Exception { for (var currentObserver : PLUGINS) { if (currentObserver != null) @@ -75,6 +78,11 @@ public static void beforeTestFailed(Exception e) throws Exception { } } + /** + * Deprecated.
+ * Use {@link #preAfterTest(TestResult, TimeRecord, Method)} as it offers more information about the test. + */ + @Deprecated public static void preAfterTest(TestResult result, Method memberInfo) throws Exception { for (var currentObserver : PLUGINS) { if (currentObserver != null) @@ -82,6 +90,18 @@ public static void preAfterTest(TestResult result, Method memberInfo) throws Exc } } + public static void preAfterTest(TestResult result, TimeRecord timeRecord, Method memberInfo) throws Exception { + for (var currentObserver : PLUGINS) { + if (currentObserver != null) + currentObserver.preAfterTest(result, timeRecord, memberInfo); + } + } + + /** + * Deprecated.
+ * Use {@link #postAfterTest(TestResult, TimeRecord, Method, Throwable)} as it offers more information about the test. + */ + @Deprecated public static void postAfterTest(TestResult result, Method memberInfo, Throwable failedTestException) { for (var currentObserver : PLUGINS) { if (currentObserver != null) @@ -89,6 +109,13 @@ public static void postAfterTest(TestResult result, Method memberInfo, Throwable } } + public static void postAfterTest(TestResult result, TimeRecord timeRecord, Method memberInfo, Throwable failedTestException) { + for (var currentObserver : PLUGINS) { + if (currentObserver != null) + currentObserver.postAfterTest(result, timeRecord, memberInfo, failedTestException); + } + } + public static void afterTestFailed(Exception e) { for (var currentObserver : PLUGINS) { if (currentObserver != null) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/TimeRecord.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/TimeRecord.java new file mode 100644 index 00000000..da059857 --- /dev/null +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/TimeRecord.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package solutions.bellatrix.core.plugins; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class TimeRecord { + private long startTime; + private long endTime; + + public long getDuration() { + return endTime - startTime; + } +} diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/BaseTest.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/BaseTest.java index fdf6339a..ff451d7e 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/BaseTest.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/BaseTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import solutions.bellatrix.core.plugins.PluginExecutionEngine; import solutions.bellatrix.core.plugins.TestResult; +import solutions.bellatrix.core.plugins.TimeRecord; import solutions.bellatrix.core.plugins.UsesPlugins; import java.util.ArrayList; @@ -28,8 +29,10 @@ import java.util.List; @ExtendWith(TestResultWatcher.class) +@ExtendWith(TestDurationWatcher.class) public class BaseTest extends UsesPlugins { static final ThreadLocal CURRENT_TEST_RESULT = new ThreadLocal<>(); + static final ThreadLocal CURRENT_TEST_TIME_RECORD = ThreadLocal.withInitial(TimeRecord::new); private static final ThreadLocal CONFIGURATION_EXECUTED = new ThreadLocal<>(); private static final List ALREADY_EXECUTED_BEFORE_CLASSES = Collections.synchronizedList(new ArrayList<>()); private TestInfo testInfo; @@ -93,7 +96,8 @@ public void afterMethodCore(TestInfo testInfo) { var testClass = this.getClass(); assert testInfo.getTestMethod().isPresent(); var methodInfo = testClass.getMethod(testInfo.getTestMethod().get().getName()); - PluginExecutionEngine.preAfterTest(CURRENT_TEST_RESULT.get(), methodInfo); + PluginExecutionEngine.preAfterTest(CURRENT_TEST_RESULT.get(), methodInfo); // DEPRECATED, LEFT FOR COMPATIBILITY + PluginExecutionEngine.preAfterTest(CURRENT_TEST_RESULT.get(), CURRENT_TEST_TIME_RECORD.get(), methodInfo); afterEach(); // PluginExecutionEngine.postAfterTest(CURRENT_TEST_RESULT.get(), methodInfo); } catch (Exception e) { diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestDurationWatcher.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestDurationWatcher.java new file mode 100644 index 00000000..39d642e9 --- /dev/null +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestDurationWatcher.java @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package solutions.bellatrix.core.plugins.junit; + +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +public class TestDurationWatcher implements BeforeTestExecutionCallback, AfterTestExecutionCallback { + @Override + public void beforeTestExecution(ExtensionContext context) { + BaseTest.CURRENT_TEST_TIME_RECORD.get().setStartTime(System.currentTimeMillis()); + } + + @Override + public void afterTestExecution(ExtensionContext context) { + BaseTest.CURRENT_TEST_TIME_RECORD.get().setEndTime(System.currentTimeMillis()); + } +} diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestResultWatcher.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestResultWatcher.java index 65dc3e43..232ba2e6 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestResultWatcher.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/junit/TestResultWatcher.java @@ -25,7 +25,9 @@ public void testAborted(ExtensionContext extensionContext, Throwable throwable) BaseTest.CURRENT_TEST_RESULT.set(TestResult.FAILURE); try { - PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), throwable); + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), throwable); // DEPRECATED, LEFT FOR COMPATIBILITY + + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), BaseTest.CURRENT_TEST_TIME_RECORD.get(), extensionContext.getTestMethod().get(), throwable); } catch (Exception e) { PluginExecutionEngine.afterTestFailed(e); } @@ -36,7 +38,9 @@ public void testDisabled(ExtensionContext extensionContext, Optional opt BaseTest.CURRENT_TEST_RESULT.set(TestResult.SUCCESS); try { - PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), null); + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), null); // DEPRECATED, LEFT FOR COMPATIBILITY + + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), BaseTest.CURRENT_TEST_TIME_RECORD.get(), extensionContext.getTestMethod().get(), null); } catch (Exception e) { PluginExecutionEngine.afterTestFailed(e); } @@ -47,7 +51,9 @@ public void testFailed(ExtensionContext extensionContext, Throwable throwable) { BaseTest.CURRENT_TEST_RESULT.set(TestResult.FAILURE); try { - PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), throwable); + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), throwable); // DEPRECATED, LEFT FOR COMPATIBILITY + + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), BaseTest.CURRENT_TEST_TIME_RECORD.get(), extensionContext.getTestMethod().get(), throwable); } catch (Exception e) { PluginExecutionEngine.afterTestFailed(e); } @@ -58,7 +64,9 @@ public void testSuccessful(ExtensionContext extensionContext) { BaseTest.CURRENT_TEST_RESULT.set(TestResult.SUCCESS); try { - PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), null); + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), extensionContext.getTestMethod().get(), null); // DEPRECATED, LEFT FOR COMPATIBILITY + + PluginExecutionEngine.postAfterTest(BaseTest.CURRENT_TEST_RESULT.get(), BaseTest.CURRENT_TEST_TIME_RECORD.get(), extensionContext.getTestMethod().get(), null); } catch (Exception e) { PluginExecutionEngine.afterTestFailed(e); } diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/BaseTest.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/BaseTest.java index 930e7467..e50622bf 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/BaseTest.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/BaseTest.java @@ -17,6 +17,7 @@ import org.testng.annotations.*; import solutions.bellatrix.core.plugins.PluginExecutionEngine; import solutions.bellatrix.core.plugins.TestResult; +import solutions.bellatrix.core.plugins.TimeRecord; import solutions.bellatrix.core.plugins.UsesPlugins; import java.util.ArrayList; @@ -26,6 +27,7 @@ @Listeners(TestResultListener.class) public class BaseTest extends UsesPlugins { static final ThreadLocal CURRENT_TEST_RESULT = new ThreadLocal<>(); + static final ThreadLocal CURRENT_TEST_TIME_RECORD = ThreadLocal.withInitial(TimeRecord::new); private static final ThreadLocal CONFIGURATION_EXECUTED = new ThreadLocal<>(); private static final List ALREADY_EXECUTED_BEFORE_CLASSES = Collections.synchronizedList(new ArrayList<>()); @@ -82,9 +84,12 @@ public void afterMethodCore(ITestResult result) { try { var testClass = this.getClass(); var methodInfo = testClass.getMethod(result.getMethod().getMethodName()); - PluginExecutionEngine.preAfterTest(CURRENT_TEST_RESULT.get(), methodInfo); + PluginExecutionEngine.preAfterTest(CURRENT_TEST_RESULT.get(), methodInfo); // DEPRECATED, LEFT FOR COMPATIBILITY + PluginExecutionEngine.preAfterTest(CURRENT_TEST_RESULT.get(), CURRENT_TEST_TIME_RECORD.get(), methodInfo); afterEach(); - PluginExecutionEngine.postAfterTest(CURRENT_TEST_RESULT.get(), methodInfo, result.getThrowable()); + PluginExecutionEngine.postAfterTest(CURRENT_TEST_RESULT.get(), methodInfo, result.getThrowable()); // DEPRECATED, LEFT FOR COMPATIBILITY + PluginExecutionEngine.postAfterTest(CURRENT_TEST_RESULT.get(), CURRENT_TEST_TIME_RECORD.get(), methodInfo, result.getThrowable()); + } catch (Exception e) { PluginExecutionEngine.afterTestFailed(e); } diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/TestResultListener.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/TestResultListener.java index e9b8e456..32802d68 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/TestResultListener.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/testng/TestResultListener.java @@ -20,10 +20,14 @@ public class TestResultListener implements ITestListener { @Override public void onTestSuccess(ITestResult result) { BaseTest.CURRENT_TEST_RESULT.set(TestResult.SUCCESS); + BaseTest.CURRENT_TEST_TIME_RECORD.get().setStartTime(result.getStartMillis()); + BaseTest.CURRENT_TEST_TIME_RECORD.get().setEndTime(result.getEndMillis()); } @Override public void onTestFailure(ITestResult result) { BaseTest.CURRENT_TEST_RESULT.set(TestResult.FAILURE); + BaseTest.CURRENT_TEST_TIME_RECORD.get().setStartTime(result.getStartMillis()); + BaseTest.CURRENT_TEST_TIME_RECORD.get().setEndTime(result.getEndMillis()); } } From de3186267e97e81e4dfde489ef36e750d75555ff Mon Sep 17 00:00:00 2001 From: MiriamKyoseva Date: Fri, 31 May 2024 14:57:12 +0300 Subject: [PATCH 2/5] Added bellatrix.plugins.jira.zephyr --- bellatrix.plugins.jira.zephyr/pom.xml | 29 ++++ .../plugins/jira/zephyr/ZephyrPlugin.java | 150 ++++++++++++++++++ .../zephyr/annotations/ZephyrProject.java | 21 +++ .../zephyr/annotations/ZephyrTestCase.java | 21 +++ .../jira/zephyr/config/ZephyrSettings.java | 26 +++ .../jira/zephyr/data/ZephyrTestCase.java | 16 ++ .../jira/zephyr/data/ZephyrTestCycle.java | 31 ++++ .../zephyr/data/ZephyrTestCycleResponse.java | 22 +++ .../events/ZephyrCyclePluginEventArgs.java | 27 ++++ .../ZephyrExecutionPluginEventArgs.java | 24 +++ .../zephyr/services/ZephyrApiService.java | 133 ++++++++++++++++ .../zephyr/utilities/DateTimeUtilities.java | 26 +++ pom.xml | 1 + 13 files changed, 527 insertions(+) create mode 100644 bellatrix.plugins.jira.zephyr/pom.xml create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrExecutionPluginEventArgs.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/utilities/DateTimeUtilities.java diff --git a/bellatrix.plugins.jira.zephyr/pom.xml b/bellatrix.plugins.jira.zephyr/pom.xml new file mode 100644 index 00000000..2210c21d --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + + bellatrix + solutions.bellatrix + 1.0-SNAPSHOT + + + bellatrix.plugins.jira.zephyr + 1.0 + + + + solutions.bellatrix + bellatrix.core + 1.0 + + + io.rest-assured + rest-assured + 5.4.0 + compile + + + + + \ No newline at end of file diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java new file mode 100644 index 00000000..3af6679a --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java @@ -0,0 +1,150 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr; + +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import lombok.Getter; +import lombok.Setter; +import plugins.jira.zephyr.annotations.ZephyrProject; +import plugins.jira.zephyr.annotations.ZephyrTestCase; +import plugins.jira.zephyr.data.ZephyrTestCycle; +import plugins.jira.zephyr.data.ZephyrTestCycleResponse; +import plugins.jira.zephyr.config.ZephyrSettings; +import plugins.jira.zephyr.events.ZephyrCyclePluginEventArgs; +import plugins.jira.zephyr.events.ZephyrExecutionPluginEventArgs; +import plugins.jira.zephyr.services.ZephyrApiService; +import plugins.jira.zephyr.utilities.DateTimeUtilities; +import solutions.bellatrix.core.configuration.ConfigurationService; +import solutions.bellatrix.core.plugins.EventListener; +import solutions.bellatrix.core.plugins.Plugin; +import solutions.bellatrix.core.plugins.TestResult; +import solutions.bellatrix.core.plugins.TimeRecord; + +import java.lang.reflect.Method; + +import static io.restassured.RestAssured.given; + +public class ZephyrPlugin extends Plugin { + public static final EventListener ZEPHYR_CYCLE_CREATED = new EventListener<>(); + public static final EventListener ZEPHYR_TEST_CASE_EXECUTION_FAILED = new EventListener<>(); + public static final EventListener ZEPHYR_TEST_CASE_EXECUTED = new EventListener<>(); + public static final EventListener ZEPHYR_CYCLE_STATUS_UPDATE_FAILED = new EventListener<>(); + + private ZephyrLocalData data; + + public ZephyrPlugin() { + String authToken = settings().getToken(); + + RestAssured.baseURI = settings().getApiUrl(); + RestAssured.requestSpecification = new RequestSpecBuilder() + .addHeader("Authorization", "Bearer " + authToken) + .addHeader("Content-Type", "application/json") + .build(); + + data = new ZephyrLocalData(); + } + + private ZephyrSettings settings() { + return ConfigurationService.get(ZephyrSettings.class); + } + + private boolean isEnabled() { + return settings().isEnabled(); + } + + private String getExecutionId(Method memberInfo) { + if (memberInfo.isAnnotationPresent(ZephyrTestCase.class)) { + return memberInfo.getAnnotation(ZephyrTestCase.class).id(); + } else { + return ""; + } + } + + private String getProjectId(Method memberInfo) { + if (memberInfo.getDeclaringClass().isAnnotationPresent(ZephyrProject.class)) { + return memberInfo.getDeclaringClass().getAnnotation(ZephyrProject.class).id(); + } else { + try { + return settings().getDefaultProjectKey(); + } catch (Exception ex) { + return ""; + } + } + } + + private String getStatus(TestResult testResult) { + if (testResult.equals(TestResult.SUCCESS)) { + return "Pass"; + } else { + return "Fail"; + } + } + + @Override + public void postBeforeClass(Class type) { + if (!isEnabled()) return; + + var testCycleName = String.format("%s %s", + DateTimeUtilities.getUtcNow(), + settings().getTestCycleName().isBlank() ? settings().getTestCycleName() : "BELLATRIX RUN"); + + var testCycle = new ZephyrTestCycle(settings().getDefaultProjectKey(), testCycleName, "In Progress"); + testCycle.setPlannedStartDate(DateTimeUtilities.getUtcNow()); + data.setTestCycle(testCycle); + + var testCycleResponse = ZephyrApiService.createTestCycle(data); + data.setTestCycleResponse(testCycleResponse); + + ZEPHYR_CYCLE_CREATED.broadcast(new ZephyrCyclePluginEventArgs(testCycleResponse)); + } + + @Override + public void postAfterTest(TestResult testResult, TimeRecord timeRecord, Method memberInfo, Throwable failedTestException) { + if (!isEnabled()) return; + + var testCase = new plugins.jira.zephyr.data.ZephyrTestCase(getProjectId(memberInfo), data.getTestCycleResponse().getKey(), getExecutionId(memberInfo), getStatus(testResult), timeRecord.getDuration()); + + if (testCase.testCaseId().isEmpty() || testCase.status().isEmpty() || getProjectId(memberInfo).isEmpty()) { + ZEPHYR_TEST_CASE_EXECUTION_FAILED.broadcast(new ZephyrExecutionPluginEventArgs(testCase)); + return; + } + + var response = ZephyrApiService.executeTestCase(testCase); + + if (response.statusCode() >= 400) { + ZEPHYR_TEST_CASE_EXECUTION_FAILED.broadcast(new ZephyrExecutionPluginEventArgs(testCase)); + } + + ZEPHYR_TEST_CASE_EXECUTED.broadcast(new ZephyrExecutionPluginEventArgs(testCase)); + } + + @Override + public void preAfterClass(Class type) { + if (!isEnabled()) return; + + data.getTestCycle().setPlannedEndDate(DateTimeUtilities.getUtcNow()); + + var response = ZephyrApiService.markTestCycleDone(data); + + if (response.statusCode() >= 400) { + ZEPHYR_CYCLE_STATUS_UPDATE_FAILED.broadcast(new ZephyrCyclePluginEventArgs()); + } + } + + @Getter @Setter + public static class ZephyrLocalData { + private ZephyrTestCycleResponse testCycleResponse; + private ZephyrTestCycle testCycle; + } +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java new file mode 100644 index 00000000..94d7bea9 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ZephyrProject { + String id(); +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java new file mode 100644 index 00000000..8cd7245a --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ZephyrTestCase { + String id(); +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java new file mode 100644 index 00000000..3c3eaa21 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.config; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public final class ZephyrSettings { + private boolean isEnabled; + private String apiUrl; + private String token; + private String defaultProjectKey; + private String testCycleName; + private String cycleFinalStatus; +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java new file mode 100644 index 00000000..16eecbd0 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.data; + +public record ZephyrTestCase(String projectId, String testCycleId, String testCaseId, String status, long duration) { +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java new file mode 100644 index 00000000..924732ef --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.data; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class ZephyrTestCycle { + public ZephyrTestCycle(String projectKey, String name, String statusName) { + this.projectKey = projectKey; + this.name = name; + this.statusName = statusName; + } + + private String projectKey; + private String name; + private String statusName; + private String plannedStartDate; + private String plannedEndDate; +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java new file mode 100644 index 00000000..d8041a58 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.data; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class ZephyrTestCycleResponse { + private String id; + private String key; +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java new file mode 100644 index 00000000..cc1b9010 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.events; + +import lombok.Getter; +import plugins.jira.zephyr.data.ZephyrTestCycleResponse; + +public class ZephyrCyclePluginEventArgs { + @Getter private ZephyrTestCycleResponse testCycle; + + public ZephyrCyclePluginEventArgs(ZephyrTestCycleResponse testCycle) { + this.testCycle = testCycle; + } + + public ZephyrCyclePluginEventArgs() { + } +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrExecutionPluginEventArgs.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrExecutionPluginEventArgs.java new file mode 100644 index 00000000..9207c8fd --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrExecutionPluginEventArgs.java @@ -0,0 +1,24 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.events; + +import lombok.Getter; +import plugins.jira.zephyr.data.ZephyrTestCase; + +public class ZephyrExecutionPluginEventArgs { + @Getter private final ZephyrTestCase testCase; + + public ZephyrExecutionPluginEventArgs(ZephyrTestCase testCase) { + this.testCase = testCase; + } +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java new file mode 100644 index 00000000..7c40ec0b --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java @@ -0,0 +1,133 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.services; + +import io.restassured.mapper.ObjectMapperType; +import io.restassured.response.Response; +import lombok.experimental.UtilityClass; +import plugins.jira.zephyr.ZephyrPlugin; +import plugins.jira.zephyr.config.ZephyrSettings; +import plugins.jira.zephyr.data.ZephyrTestCycleResponse; +import solutions.bellatrix.core.configuration.ConfigurationService; +import solutions.bellatrix.core.utilities.DebugInformation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static io.restassured.RestAssured.given; + +@UtilityClass +public class ZephyrApiService { + private ZephyrSettings settings() { + return ConfigurationService.get(ZephyrSettings.class); + } + + public ZephyrTestCycleResponse createTestCycle(ZephyrPlugin.ZephyrLocalData data) { + var body = Map.of( + "projectKey", data.getTestCycle().getProjectKey(), + "name", data.getTestCycle().getName(), + "statusName", data.getTestCycle().getStatusName() + ); + + return given() + .body(body, ObjectMapperType.GSON) + .when() + .post("/testcycles") + .then() + .extract().response().body().as(ZephyrTestCycleResponse.class, ObjectMapperType.GSON); + } + + public Response executeTestCase(plugins.jira.zephyr.data.ZephyrTestCase testCase) { + var body = Map.of( + "projectKey", testCase.projectId(), + "testCycleKey", testCase.testCycleId(), + "testCaseKey", testCase.testCaseId(), + "statusName", testCase.status(), + "executionTime", (int)testCase.duration() + ); + + return given() + .body(body, ObjectMapperType.GSON) + .when() + .post("/testexecutions") + .then() + .extract().response(); + } + + public Response markTestCycleDone(ZephyrPlugin.ZephyrLocalData data) { + var body = Map.of( + "id", data.getTestCycleResponse().getId(), + "key", data.getTestCycleResponse().getKey(), + "name", data.getTestCycle().getName(), + "project", Map.of("id", ZephyrApiService.getProjectId(data.getTestCycleResponse().getKey())), + "status", Map.of("id", ZephyrApiService.getStatusId(settings().getCycleFinalStatus().isBlank() ? settings().getCycleFinalStatus() : "Done", data.getTestCycle().getProjectKey())), + "plannedEndDate", data.getTestCycle().getPlannedEndDate() + ); + + return given() + .body(body, ObjectMapperType.GSON) + .put("/testcycles/" + settings().getDefaultProjectKey()) + .then() + .extract().response(); + } + + private static String getProjectId(String testCycleIdOrKey) { + return given() + .get("/testcycles/" + testCycleIdOrKey) + .then() + .extract().as(TestCycle.class, ObjectMapperType.GSON).project.id; + } + + private static String getStatusId(String statusName, String projectKey) { + try { + return getStatuses(projectKey).stream() + .filter(status -> status.name.equalsIgnoreCase(statusName)) + .map(status -> status.id) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException( + String.format("Could not find a status in project %s with the provided status name: %s", projectKey, statusName) + )); + } catch (IllegalArgumentException ex) { + DebugInformation.debugInfo(ex.getMessage()); + return ""; + } + } + + private static List getStatuses(String projectKey) { + return given() + .queryParam("maxResults", "100") + .queryParam("projectKey", projectKey) + .queryParam("statusType", "TEST_CYCLE") + .get("/statuses") + .then() + .extract().as(Statuses.class, ObjectMapperType.GSON).values; + } + + private static final class Status { + private String id; + private String name; + } + + private static final class Statuses { + private ArrayList values; + } + + private static final class Project { + private String id; + } + + private static final class TestCycle { + private Project project; + } +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/utilities/DateTimeUtilities.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/utilities/DateTimeUtilities.java new file mode 100644 index 00000000..7fe5d9ec --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/utilities/DateTimeUtilities.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.utilities; + +import lombok.experimental.UtilityClass; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +@UtilityClass +public class DateTimeUtilities { + public static String getUtcNow() { + return ZonedDateTime.now(ZoneId.of("UTC")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")); + } +} diff --git a/pom.xml b/pom.xml index 74222f9b..3f60e4e0 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ bellatrix.core bellatrix.plugins.screenshots bellatrix.plugins.video + bellatrix.plugins.jira.zephyr bellatrix.web bellatrix.playwright bellatrix.desktop From eb423c517fcc1b6da527f001c21e09fdc2953959 Mon Sep 17 00:00:00 2001 From: MiriamKyoseva <133047546+MiriamKyoseva@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:55:23 +0300 Subject: [PATCH 3/5] Minor fixes --- .../main/java/solutions/bellatrix/core/plugins/Plugin.java | 1 - .../bellatrix/core/plugins/PluginExecutionEngine.java | 4 ---- 2 files changed, 5 deletions(-) diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java index ad1b759a..508b4b21 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/Plugin.java @@ -36,7 +36,6 @@ public void preBeforeTest(TestResult testResult, Method memberInfo) throws Excep public void postBeforeTest(TestResult testResult, Method memberInfo) { } - public void beforeTestFailed(Exception e) throws Exception { } diff --git a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java index cd03f289..97a2a60f 100644 --- a/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java +++ b/bellatrix.core/src/main/java/solutions/bellatrix/core/plugins/PluginExecutionEngine.java @@ -13,10 +13,7 @@ package solutions.bellatrix.core.plugins; -import org.apache.http.annotation.Obsolete; - import java.lang.reflect.Method; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; @@ -70,7 +67,6 @@ public static void postBeforeTest(TestResult result, Method memberInfo) { } } - public static void beforeTestFailed(Exception e) throws Exception { for (var currentObserver : PLUGINS) { if (currentObserver != null) From 8857da7c81238fceaf15a24430bb7b3d744f8092 Mon Sep 17 00:00:00 2001 From: MiriamKyoseva Date: Fri, 7 Jun 2024 17:33:30 +0300 Subject: [PATCH 4/5] Changes to bellatrix.plugins.jira.zephyr --- bellatrix.plugins.jira.zephyr/pom.xml | 6 -- .../plugins/jira/zephyr/ZephyrPlugin.java | 65 +++++++------ ...{ZephyrProject.java => ZephyrCycleId.java} | 4 +- .../zephyr/annotations/ZephyrProjectId.java | 21 +++++ .../zephyr/annotations/ZephyrTestCase.java | 10 ++ .../jira/zephyr/config/ZephyrSettings.java | 1 + .../jira/zephyr/data/ZephyrTestCase.java | 2 +- .../zephyr/data/ZephyrTestCycleStatus.java | 28 ++++++ .../data/ZephyrTestExecutionStatus.java | 30 ++++++ .../zephyr/services/ZephyrApiService.java | 93 ++++++++++--------- 10 files changed, 178 insertions(+), 82 deletions(-) rename bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/{ZephyrProject.java => ZephyrCycleId.java} (93%) create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProjectId.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleStatus.java create mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestExecutionStatus.java diff --git a/bellatrix.plugins.jira.zephyr/pom.xml b/bellatrix.plugins.jira.zephyr/pom.xml index 2210c21d..aa294157 100644 --- a/bellatrix.plugins.jira.zephyr/pom.xml +++ b/bellatrix.plugins.jira.zephyr/pom.xml @@ -17,12 +17,6 @@ bellatrix.core 1.0 - - io.rest-assured - rest-assured - 5.4.0 - compile - diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java index 3af6679a..21318231 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java @@ -14,13 +14,14 @@ import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; -import lombok.Getter; -import lombok.Setter; -import plugins.jira.zephyr.annotations.ZephyrProject; +import plugins.jira.zephyr.annotations.ZephyrCycleId; +import plugins.jira.zephyr.annotations.ZephyrProjectId; import plugins.jira.zephyr.annotations.ZephyrTestCase; import plugins.jira.zephyr.data.ZephyrTestCycle; import plugins.jira.zephyr.data.ZephyrTestCycleResponse; import plugins.jira.zephyr.config.ZephyrSettings; +import plugins.jira.zephyr.data.ZephyrTestCycleStatus; +import plugins.jira.zephyr.data.ZephyrTestExecutionStatus; import plugins.jira.zephyr.events.ZephyrCyclePluginEventArgs; import plugins.jira.zephyr.events.ZephyrExecutionPluginEventArgs; import plugins.jira.zephyr.services.ZephyrApiService; @@ -33,16 +34,15 @@ import java.lang.reflect.Method; -import static io.restassured.RestAssured.given; - public class ZephyrPlugin extends Plugin { public static final EventListener ZEPHYR_CYCLE_CREATED = new EventListener<>(); public static final EventListener ZEPHYR_TEST_CASE_EXECUTION_FAILED = new EventListener<>(); public static final EventListener ZEPHYR_TEST_CASE_EXECUTED = new EventListener<>(); public static final EventListener ZEPHYR_CYCLE_STATUS_UPDATE_FAILED = new EventListener<>(); - private ZephyrLocalData data; - + private ZephyrTestCycleResponse testCycleResponse; + private ZephyrTestCycle testCycle; + public ZephyrPlugin() { String authToken = settings().getToken(); @@ -51,8 +51,6 @@ public ZephyrPlugin() { .addHeader("Authorization", "Bearer " + authToken) .addHeader("Content-Type", "application/json") .build(); - - data = new ZephyrLocalData(); } private ZephyrSettings settings() { @@ -63,6 +61,18 @@ private boolean isEnabled() { return settings().isEnabled(); } + private String getCycleId(Method memberInfo) { + if (!settings().isExistingCycle()) return testCycleResponse.getKey(); + + if (memberInfo.isAnnotationPresent(ZephyrTestCase.class) && !memberInfo.getAnnotation(ZephyrTestCase.class).cycleId().isBlank()) { + return memberInfo.getAnnotation(ZephyrTestCase.class).cycleId(); + } else if (memberInfo.getDeclaringClass().isAnnotationPresent(ZephyrTestCase.class)) { + return memberInfo.getDeclaringClass().getAnnotation(ZephyrCycleId.class).value(); + } else { + return ""; + } + } + private String getExecutionId(Method memberInfo) { if (memberInfo.isAnnotationPresent(ZephyrTestCase.class)) { return memberInfo.getAnnotation(ZephyrTestCase.class).id(); @@ -72,8 +82,10 @@ private String getExecutionId(Method memberInfo) { } private String getProjectId(Method memberInfo) { - if (memberInfo.getDeclaringClass().isAnnotationPresent(ZephyrProject.class)) { - return memberInfo.getDeclaringClass().getAnnotation(ZephyrProject.class).id(); + if (memberInfo.isAnnotationPresent(ZephyrTestCase.class) && !memberInfo.getAnnotation(ZephyrTestCase.class).projectId().isBlank()) { + return memberInfo.getAnnotation(ZephyrTestCase.class).projectId(); + } else if (memberInfo.getDeclaringClass().isAnnotationPresent(ZephyrProjectId.class)) { + return memberInfo.getDeclaringClass().getAnnotation(ZephyrProjectId.class).value(); } else { try { return settings().getDefaultProjectKey(); @@ -85,26 +97,25 @@ private String getProjectId(Method memberInfo) { private String getStatus(TestResult testResult) { if (testResult.equals(TestResult.SUCCESS)) { - return "Pass"; + return ZephyrTestExecutionStatus.PASS.getValue(); } else { - return "Fail"; + return ZephyrTestExecutionStatus.FAIL.getValue(); } } @Override public void postBeforeClass(Class type) { - if (!isEnabled()) return; + if (!isEnabled() || settings().isExistingCycle()) return; + + var isDefaultValueAvailableInConfig = settings().getTestCycleName() != null && !settings().getTestCycleName().isBlank(); var testCycleName = String.format("%s %s", - DateTimeUtilities.getUtcNow(), - settings().getTestCycleName().isBlank() ? settings().getTestCycleName() : "BELLATRIX RUN"); + DateTimeUtilities.getUtcNow(), isDefaultValueAvailableInConfig ? settings().getTestCycleName() : "BELLATRIX RUN"); - var testCycle = new ZephyrTestCycle(settings().getDefaultProjectKey(), testCycleName, "In Progress"); + testCycle = new ZephyrTestCycle(settings().getDefaultProjectKey(), testCycleName, ZephyrTestCycleStatus.IN_PROGRESS.getValue()); testCycle.setPlannedStartDate(DateTimeUtilities.getUtcNow()); - data.setTestCycle(testCycle); - var testCycleResponse = ZephyrApiService.createTestCycle(data); - data.setTestCycleResponse(testCycleResponse); + testCycleResponse = ZephyrApiService.createTestCycle(testCycle); ZEPHYR_CYCLE_CREATED.broadcast(new ZephyrCyclePluginEventArgs(testCycleResponse)); } @@ -113,7 +124,7 @@ public void postBeforeClass(Class type) { public void postAfterTest(TestResult testResult, TimeRecord timeRecord, Method memberInfo, Throwable failedTestException) { if (!isEnabled()) return; - var testCase = new plugins.jira.zephyr.data.ZephyrTestCase(getProjectId(memberInfo), data.getTestCycleResponse().getKey(), getExecutionId(memberInfo), getStatus(testResult), timeRecord.getDuration()); + var testCase = new plugins.jira.zephyr.data.ZephyrTestCase(getProjectId(memberInfo), getCycleId(memberInfo), getExecutionId(memberInfo), getStatus(testResult), timeRecord.getDuration(), failedTestException); if (testCase.testCaseId().isEmpty() || testCase.status().isEmpty() || getProjectId(memberInfo).isEmpty()) { ZEPHYR_TEST_CASE_EXECUTION_FAILED.broadcast(new ZephyrExecutionPluginEventArgs(testCase)); @@ -131,20 +142,14 @@ public void postAfterTest(TestResult testResult, TimeRecord timeRecord, Method m @Override public void preAfterClass(Class type) { - if (!isEnabled()) return; + if (!isEnabled() || settings().isExistingCycle()) return; - data.getTestCycle().setPlannedEndDate(DateTimeUtilities.getUtcNow()); + testCycle.setPlannedEndDate(DateTimeUtilities.getUtcNow()); - var response = ZephyrApiService.markTestCycleDone(data); + var response = ZephyrApiService.changeTestCycleStatus(testCycle, testCycleResponse); if (response.statusCode() >= 400) { ZEPHYR_CYCLE_STATUS_UPDATE_FAILED.broadcast(new ZephyrCyclePluginEventArgs()); } } - - @Getter @Setter - public static class ZephyrLocalData { - private ZephyrTestCycleResponse testCycleResponse; - private ZephyrTestCycle testCycle; - } } diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrCycleId.java similarity index 93% rename from bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java rename to bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrCycleId.java index 94d7bea9..04f4753f 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProject.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrCycleId.java @@ -16,6 +16,6 @@ import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) -public @interface ZephyrProject { - String id(); +public @interface ZephyrCycleId { + String value(); } diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProjectId.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProjectId.java new file mode 100644 index 00000000..550378a8 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrProjectId.java @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ZephyrProjectId { + String value(); +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java index 8cd7245a..fc0cef72 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/annotations/ZephyrTestCase.java @@ -18,4 +18,14 @@ @Retention(RetentionPolicy.RUNTIME) public @interface ZephyrTestCase { String id(); + + /** + * If empty, will take the value of {@link ZephyrCycleId} from the declaring class. + */ + String cycleId() default ""; + + /** + * If empty, will take the value of {@link ZephyrProjectId} from the declaring class. + */ + String projectId() default ""; } diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java index 3c3eaa21..8d531a69 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/config/ZephyrSettings.java @@ -23,4 +23,5 @@ public final class ZephyrSettings { private String defaultProjectKey; private String testCycleName; private String cycleFinalStatus; + private boolean isExistingCycle; } diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java index 16eecbd0..5d0375bc 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCase.java @@ -12,5 +12,5 @@ */ package plugins.jira.zephyr.data; -public record ZephyrTestCase(String projectId, String testCycleId, String testCaseId, String status, long duration) { +public record ZephyrTestCase(String projectId, String testCycleId, String testCaseId, String status, long duration, Throwable error) { } diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleStatus.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleStatus.java new file mode 100644 index 00000000..7d01b828 --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleStatus.java @@ -0,0 +1,28 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.data; + +import lombok.Getter; + +@Getter +public enum ZephyrTestCycleStatus { + NOT_EXECUTED("Not Executed"), + IN_PROGRESS("In Progress"), + DONE("Done"); + + ZephyrTestCycleStatus(String value) { + this.value = value; + } + + private final String value; +} \ No newline at end of file diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestExecutionStatus.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestExecutionStatus.java new file mode 100644 index 00000000..ec16a3ee --- /dev/null +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestExecutionStatus.java @@ -0,0 +1,30 @@ +/* + * Copyright 2024 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package plugins.jira.zephyr.data; + +import lombok.Getter; + +@Getter +public enum ZephyrTestExecutionStatus { + NOT_EXECUTED("Not Executed"), + IN_PROGRESS("In Progress"), + PASS("Pass"), + FAIL("Fail"), + BLOCKED("Blocked"); + + ZephyrTestExecutionStatus(String value) { + this.value = value; + } + + private final String value; +} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java index 7c40ec0b..623311a7 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java @@ -13,15 +13,22 @@ package plugins.jira.zephyr.services; import io.restassured.mapper.ObjectMapperType; +import io.restassured.path.json.JsonPath; import io.restassured.response.Response; import lombok.experimental.UtilityClass; -import plugins.jira.zephyr.ZephyrPlugin; +import net.minidev.json.JSONObject; +import org.apache.commons.text.StringEscapeUtils; import plugins.jira.zephyr.config.ZephyrSettings; +import plugins.jira.zephyr.data.ZephyrTestCycle; import plugins.jira.zephyr.data.ZephyrTestCycleResponse; +import plugins.jira.zephyr.data.ZephyrTestCycleStatus; import solutions.bellatrix.core.configuration.ConfigurationService; import solutions.bellatrix.core.utilities.DebugInformation; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -33,11 +40,11 @@ private ZephyrSettings settings() { return ConfigurationService.get(ZephyrSettings.class); } - public ZephyrTestCycleResponse createTestCycle(ZephyrPlugin.ZephyrLocalData data) { + public ZephyrTestCycleResponse createTestCycle(ZephyrTestCycle testCycle) { var body = Map.of( - "projectKey", data.getTestCycle().getProjectKey(), - "name", data.getTestCycle().getName(), - "statusName", data.getTestCycle().getStatusName() + "projectKey", testCycle.getProjectKey(), + "name", testCycle.getName(), + "statusName", testCycle.getStatusName() ); return given() @@ -49,13 +56,17 @@ public ZephyrTestCycleResponse createTestCycle(ZephyrPlugin.ZephyrLocalData data } public Response executeTestCase(plugins.jira.zephyr.data.ZephyrTestCase testCase) { - var body = Map.of( + var body = new java.util.HashMap(Map.of( "projectKey", testCase.projectId(), "testCycleKey", testCase.testCycleId(), "testCaseKey", testCase.testCaseId(), "statusName", testCase.status(), "executionTime", (int)testCase.duration() - ); + )); + + if (testCase.error() != null) { + body.put("comment", formatError(testCase.error())); + } return given() .body(body, ObjectMapperType.GSON) @@ -65,14 +76,17 @@ public Response executeTestCase(plugins.jira.zephyr.data.ZephyrTestCase testCase .extract().response(); } - public Response markTestCycleDone(ZephyrPlugin.ZephyrLocalData data) { + public Response changeTestCycleStatus(ZephyrTestCycle cycleData, ZephyrTestCycleResponse cycleCreationResponse) { + var isDefaultValueAvailableInConfig = settings().getCycleFinalStatus() != null && !settings().getCycleFinalStatus().isBlank(); + var body = Map.of( - "id", data.getTestCycleResponse().getId(), - "key", data.getTestCycleResponse().getKey(), - "name", data.getTestCycle().getName(), - "project", Map.of("id", ZephyrApiService.getProjectId(data.getTestCycleResponse().getKey())), - "status", Map.of("id", ZephyrApiService.getStatusId(settings().getCycleFinalStatus().isBlank() ? settings().getCycleFinalStatus() : "Done", data.getTestCycle().getProjectKey())), - "plannedEndDate", data.getTestCycle().getPlannedEndDate() + "id", cycleCreationResponse.getId(), + "key", cycleCreationResponse.getKey(), + "name", cycleData.getName(), + "project", Map.of("id", ZephyrApiService.getProjectId(cycleCreationResponse.getKey())), + "status", Map.of("id", ZephyrApiService.getStatusId(isDefaultValueAvailableInConfig ? + settings().getCycleFinalStatus() : ZephyrTestCycleStatus.DONE.getValue(), cycleData.getProjectKey())), + "plannedEndDate", cycleData.getPlannedEndDate() ); return given() @@ -83,51 +97,44 @@ public Response markTestCycleDone(ZephyrPlugin.ZephyrLocalData data) { } private static String getProjectId(String testCycleIdOrKey) { - return given() + return String.valueOf(given() .get("/testcycles/" + testCycleIdOrKey) .then() - .extract().as(TestCycle.class, ObjectMapperType.GSON).project.id; + .extract().jsonPath().get("project.id")); } private static String getStatusId(String statusName, String projectKey) { - try { - return getStatuses(projectKey).stream() - .filter(status -> status.name.equalsIgnoreCase(statusName)) - .map(status -> status.id) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException( - String.format("Could not find a status in project %s with the provided status name: %s", projectKey, statusName) - )); - } catch (IllegalArgumentException ex) { - DebugInformation.debugInfo(ex.getMessage()); - return ""; - } + return getStatuses(projectKey).stream() + .filter(status -> String.valueOf(status.get("name")).equalsIgnoreCase(statusName)) + .map(status -> String.valueOf(status.get("id"))) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException( + String.format("Could not find a status in project %s with the provided status name: %s", projectKey, statusName) + )); } - private static List getStatuses(String projectKey) { - return given() + private static List> getStatuses(String projectKey) { + JsonPath jsonPath = given() .queryParam("maxResults", "100") .queryParam("projectKey", projectKey) .queryParam("statusType", "TEST_CYCLE") .get("/statuses") .then() - .extract().as(Statuses.class, ObjectMapperType.GSON).values; - } + .extract() + .jsonPath(); - private static final class Status { - private String id; - private String name; + return jsonPath.getList("values"); } - private static final class Statuses { - private ArrayList values; - } + private static String formatError(Throwable error) { - private static final class Project { - private String id; - } - private static final class TestCycle { - private Project project; + var errorInfo = String.format("Failure details:\n\nError message:\n%s\n\nStack Trace:
%s
", + StringEscapeUtils.escapeHtml4(error.getMessage()), + String.join("\n", Arrays.stream(error.getStackTrace()).map(StackTraceElement::toString).toList()) + ); + + return errorInfo.replace("\n", "
"); } + } From 4b27d132eaa59e224d0248657a778a91ed5e3dd8 Mon Sep 17 00:00:00 2001 From: MiriamKyoseva Date: Fri, 7 Jun 2024 22:47:12 +0300 Subject: [PATCH 5/5] Removed ZephyrTestCycleResponse and moved id and key fields to ZephyrTestCycle --- .../plugins/jira/zephyr/ZephyrPlugin.java | 13 +++++----- .../jira/zephyr/data/ZephyrTestCycle.java | 2 ++ .../zephyr/data/ZephyrTestCycleResponse.java | 22 ---------------- .../events/ZephyrCyclePluginEventArgs.java | 6 ++--- .../zephyr/services/ZephyrApiService.java | 26 +++++++++---------- 5 files changed, 24 insertions(+), 45 deletions(-) delete mode 100644 bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java index 21318231..73c2f1f7 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/ZephyrPlugin.java @@ -18,7 +18,6 @@ import plugins.jira.zephyr.annotations.ZephyrProjectId; import plugins.jira.zephyr.annotations.ZephyrTestCase; import plugins.jira.zephyr.data.ZephyrTestCycle; -import plugins.jira.zephyr.data.ZephyrTestCycleResponse; import plugins.jira.zephyr.config.ZephyrSettings; import plugins.jira.zephyr.data.ZephyrTestCycleStatus; import plugins.jira.zephyr.data.ZephyrTestExecutionStatus; @@ -33,6 +32,7 @@ import solutions.bellatrix.core.plugins.TimeRecord; import java.lang.reflect.Method; +import java.util.Map; public class ZephyrPlugin extends Plugin { public static final EventListener ZEPHYR_CYCLE_CREATED = new EventListener<>(); @@ -40,7 +40,6 @@ public class ZephyrPlugin extends Plugin { public static final EventListener ZEPHYR_TEST_CASE_EXECUTED = new EventListener<>(); public static final EventListener ZEPHYR_CYCLE_STATUS_UPDATE_FAILED = new EventListener<>(); - private ZephyrTestCycleResponse testCycleResponse; private ZephyrTestCycle testCycle; public ZephyrPlugin() { @@ -62,7 +61,7 @@ private boolean isEnabled() { } private String getCycleId(Method memberInfo) { - if (!settings().isExistingCycle()) return testCycleResponse.getKey(); + if (!settings().isExistingCycle()) return testCycle.getKey(); if (memberInfo.isAnnotationPresent(ZephyrTestCase.class) && !memberInfo.getAnnotation(ZephyrTestCase.class).cycleId().isBlank()) { return memberInfo.getAnnotation(ZephyrTestCase.class).cycleId(); @@ -115,9 +114,9 @@ public void postBeforeClass(Class type) { testCycle = new ZephyrTestCycle(settings().getDefaultProjectKey(), testCycleName, ZephyrTestCycleStatus.IN_PROGRESS.getValue()); testCycle.setPlannedStartDate(DateTimeUtilities.getUtcNow()); - testCycleResponse = ZephyrApiService.createTestCycle(testCycle); + ZephyrApiService.createTestCycle(testCycle); - ZEPHYR_CYCLE_CREATED.broadcast(new ZephyrCyclePluginEventArgs(testCycleResponse)); + ZEPHYR_CYCLE_CREATED.broadcast(new ZephyrCyclePluginEventArgs(testCycle)); } @Override @@ -133,6 +132,8 @@ public void postAfterTest(TestResult testResult, TimeRecord timeRecord, Method m var response = ZephyrApiService.executeTestCase(testCase); + var responseBody = response.body().prettyPrint(); + if (response.statusCode() >= 400) { ZEPHYR_TEST_CASE_EXECUTION_FAILED.broadcast(new ZephyrExecutionPluginEventArgs(testCase)); } @@ -146,7 +147,7 @@ public void preAfterClass(Class type) { testCycle.setPlannedEndDate(DateTimeUtilities.getUtcNow()); - var response = ZephyrApiService.changeTestCycleStatus(testCycle, testCycleResponse); + var response = ZephyrApiService.changeTestCycleStatus(testCycle); if (response.statusCode() >= 400) { ZEPHYR_CYCLE_STATUS_UPDATE_FAILED.broadcast(new ZephyrCyclePluginEventArgs()); diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java index 924732ef..14404958 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycle.java @@ -23,6 +23,8 @@ public ZephyrTestCycle(String projectKey, String name, String statusName) { this.statusName = statusName; } + private String id; + private String key; private String projectKey; private String name; private String statusName; diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java deleted file mode 100644 index d8041a58..00000000 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/data/ZephyrTestCycleResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2024 Automate The Planet Ltd. - * Author: Miriam Kyoseva - * Licensed under the Apache License, Version 2.0 (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package plugins.jira.zephyr.data; - -import lombok.Getter; -import lombok.Setter; - -@Getter @Setter -public class ZephyrTestCycleResponse { - private String id; - private String key; -} diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java index cc1b9010..e5f6392a 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/events/ZephyrCyclePluginEventArgs.java @@ -13,12 +13,12 @@ package plugins.jira.zephyr.events; import lombok.Getter; -import plugins.jira.zephyr.data.ZephyrTestCycleResponse; +import plugins.jira.zephyr.data.ZephyrTestCycle; public class ZephyrCyclePluginEventArgs { - @Getter private ZephyrTestCycleResponse testCycle; + @Getter private ZephyrTestCycle testCycle; - public ZephyrCyclePluginEventArgs(ZephyrTestCycleResponse testCycle) { + public ZephyrCyclePluginEventArgs(ZephyrTestCycle testCycle) { this.testCycle = testCycle; } diff --git a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java index 623311a7..64b398fa 100644 --- a/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java +++ b/bellatrix.plugins.jira.zephyr/src/main/java/plugins/jira/zephyr/services/ZephyrApiService.java @@ -16,18 +16,12 @@ import io.restassured.path.json.JsonPath; import io.restassured.response.Response; import lombok.experimental.UtilityClass; -import net.minidev.json.JSONObject; import org.apache.commons.text.StringEscapeUtils; import plugins.jira.zephyr.config.ZephyrSettings; import plugins.jira.zephyr.data.ZephyrTestCycle; -import plugins.jira.zephyr.data.ZephyrTestCycleResponse; import plugins.jira.zephyr.data.ZephyrTestCycleStatus; import solutions.bellatrix.core.configuration.ConfigurationService; -import solutions.bellatrix.core.utilities.DebugInformation; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -40,19 +34,24 @@ private ZephyrSettings settings() { return ConfigurationService.get(ZephyrSettings.class); } - public ZephyrTestCycleResponse createTestCycle(ZephyrTestCycle testCycle) { + public Response createTestCycle(ZephyrTestCycle testCycle) { var body = Map.of( "projectKey", testCycle.getProjectKey(), "name", testCycle.getName(), "statusName", testCycle.getStatusName() ); - return given() + var extractableResponse = given() .body(body, ObjectMapperType.GSON) .when() .post("/testcycles") .then() - .extract().response().body().as(ZephyrTestCycleResponse.class, ObjectMapperType.GSON); + .extract(); + + testCycle.setId(extractableResponse.jsonPath().getString("id")); + testCycle.setKey(extractableResponse.jsonPath().getString("key")); + + return extractableResponse.response(); } public Response executeTestCase(plugins.jira.zephyr.data.ZephyrTestCase testCase) { @@ -76,14 +75,14 @@ public Response executeTestCase(plugins.jira.zephyr.data.ZephyrTestCase testCase .extract().response(); } - public Response changeTestCycleStatus(ZephyrTestCycle cycleData, ZephyrTestCycleResponse cycleCreationResponse) { + public Response changeTestCycleStatus(ZephyrTestCycle cycleData) { var isDefaultValueAvailableInConfig = settings().getCycleFinalStatus() != null && !settings().getCycleFinalStatus().isBlank(); var body = Map.of( - "id", cycleCreationResponse.getId(), - "key", cycleCreationResponse.getKey(), + "id", cycleData.getId(), + "key", cycleData.getKey(), "name", cycleData.getName(), - "project", Map.of("id", ZephyrApiService.getProjectId(cycleCreationResponse.getKey())), + "project", Map.of("id", ZephyrApiService.getProjectId(cycleData.getKey())), "status", Map.of("id", ZephyrApiService.getStatusId(isDefaultValueAvailableInConfig ? settings().getCycleFinalStatus() : ZephyrTestCycleStatus.DONE.getValue(), cycleData.getProjectKey())), "plannedEndDate", cycleData.getPlannedEndDate() @@ -136,5 +135,4 @@ private static String formatError(Throwable error) { return errorInfo.replace("\n", "
"); } - }