All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.qytera.qtaf.testrail.event_subscriber.UploadTestsSubscriber Maven / Gradle / Ivy

There is a newer version: 0.2.23
Show newest version
// Generated by delombok at Tue Jun 25 12:09:13 UTC 2024
package de.qytera.qtaf.testrail.event_subscriber;

import de.qytera.qtaf.core.QtafFactory;
import de.qytera.qtaf.core.config.ConfigurationFactory;
import de.qytera.qtaf.core.config.entity.ConfigMap;
import de.qytera.qtaf.core.config.exception.MissingConfigurationValueException;
import de.qytera.qtaf.core.events.QtafEvents;
import de.qytera.qtaf.core.events.interfaces.IEventSubscriber;
import de.qytera.qtaf.core.log.model.collection.TestFeatureLogCollection;
import de.qytera.qtaf.core.log.model.collection.TestScenarioLogCollection;
import de.qytera.qtaf.core.log.model.collection.TestSuiteLogCollection;
import de.qytera.qtaf.core.log.model.message.LogMessage;
import de.qytera.qtaf.core.log.model.message.StepInformationLogMessage;
import de.qytera.qtaf.security.aes.AES;
import de.qytera.qtaf.testrail.annotations.TestRail;
import de.qytera.qtaf.testrail.config.TestRailConfigHelper;
import de.qytera.qtaf.testrail.entity.Attachment;
import de.qytera.qtaf.testrail.entity.Attachments;
import de.qytera.qtaf.testrail.utils.APIClient;
import de.qytera.qtaf.testrail.utils.TestRailManager;
import rx.Subscription;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * This subscriber binds to the test finished event and uploads the tests to the TestRail API.
 */
public class UploadTestsSubscriber implements IEventSubscriber {
    /**
     * QTAF Event Subscription.
     */
    private Subscription testFinishedSubscription;
    /**
     * Configuration.
     */
    private static final ConfigMap CONFIG = QtafFactory.getConfiguration();
    /**
     * testRail API client.
     */
    private APIClient client = null;

    @Override
    public void initialize() {
        if (this.testFinishedSubscription == null) {
            this.testFinishedSubscription = QtafEvents.logsPersisted.subscribe(this::onFinishedTesting);
        }
    }

    /**
     * Set up the client for the TestRail API.
     *
     * @return the client
     * @throws GeneralSecurityException           if encrypted values cannot be decrypted
     * @throws MissingConfigurationValueException if the configuration is invalid
     */
    public APIClient setUpClient() throws GeneralSecurityException, MissingConfigurationValueException {
        if (client == null) {
            // Load values from configuration file
            String url = CONFIG.getString(TestRailConfigHelper.TESTRAIL_URL);
            String clientId = CONFIG.getString(TestRailConfigHelper.TESTRAIL_AUTHENTICATION_CLIENT_ID);
            String clientSecret = CONFIG.getString(TestRailConfigHelper.TESTRAIL_AUTHENTICATION_CLIENT_SECRET);
            String key = CONFIG.getString(TestRailConfigHelper.SECURITY_KEY);
            client = new APIClient(url);
            // Check if id and secret exist
            if (clientId == null || clientId.isBlank()) {
                throw new MissingConfigurationValueException(TestRailConfigHelper.TESTRAIL_AUTHENTICATION_CLIENT_ID, CONFIG);
            }
            if (clientSecret == null || clientSecret.isBlank()) {
                throw new MissingConfigurationValueException(TestRailConfigHelper.TESTRAIL_AUTHENTICATION_CLIENT_SECRET, CONFIG);
            }
            if (key == null || key.isBlank()) {
                // credentials are not encrypted
                client.setUser(clientId);
                client.setPassword(clientSecret);
            } else {
                // credentials are encrypted
                client.setUser(AES.decrypt(clientId, key));
                client.setPassword(AES.decrypt(clientSecret, key));
            }
        }
        return client;
    }

    /**
     * Event handler for finished testing event.
     *
     * @param testingContext Test context event payload
     */
    public void onFinishedTesting(String testingContext) {
        if (Boolean.FALSE.equals(CONFIG.getBoolean(TestRailConfigHelper.TESTRAIL_ENABLED))) {
            return;
        }
        try {
            client = setUpClient();
        } catch (GeneralSecurityException | MissingConfigurationValueException exception) {
            QtafFactory.getLogger().error("[QTAF Testrail Plugin] Failed to set up API client", exception);
            return;
        }
        TestSuiteLogCollection logCollection = TestSuiteLogCollection.getInstance();
        for (TestFeatureLogCollection testFeatureLogCollection : logCollection.getTestFeatureLogCollections()) {
            testFeatureLogCollection.getScenarioLogCollection().forEach(this::handleScenario);
        }
    }

    private void handleScenario(TestScenarioLogCollection scenarioLog) {
        if (scenarioLog.getStatus() == null) {
            return;
        }
        TestRail testRailIdAnnotation = scenarioLog.getAnnotation(TestRail.class);
        if (testRailIdAnnotation != null) {
            Arrays.stream(testRailIdAnnotation.caseId()).forEach(caseId -> {
                try {
                    Attachments attachments = TestRailManager.getAttachmentsForTestCase(client, caseId);
                    if (attachments != null) {
                        for (Attachment attachment : attachments.getAttachments()) {
                            TestRailManager.deleteAttachmentForTestCase(client, attachment.getId());
                        }
                    }
                } catch (Exception e) {
                    QtafFactory.getLogger().error("[QTAF TestRail Plugin] Failed to delete attachments of case %s".formatted(caseId));
                    QtafFactory.getLogger().error(e);
                }
            });
            if (scenarioLog.getStatus().equals(TestScenarioLogCollection.Status.FAILURE)) {
                handleScenarioFailure(scenarioLog, testRailIdAnnotation);
            } else if (scenarioLog.getStatus().equals(TestScenarioLogCollection.Status.SUCCESS)) {
                handleScenarioSuccess(testRailIdAnnotation);
            }
        }
    }

    /**
     * Handle scenario success.
     *
     * @param testRailIdAnnotation testrail annotation of scenario
     */
    public void handleScenarioSuccess(TestRail testRailIdAnnotation) {
        Arrays.stream(testRailIdAnnotation.caseId()).forEach(caseId -> {
            try {
                TestRailManager.addResultForTestCase(client, caseId, getRunId(testRailIdAnnotation), 1, "");
                QtafFactory.getLogger().info("Results are uploaded to testRail");
            } catch (Exception e) {
                QtafFactory.getLogger().error(e);
            }
        });
    }

    /**
     * Handle scenario failure.
     *
     * @param scenarioLog          step logs
     * @param testRailIdAnnotation testrail annotation of scenario
     */
    public void handleScenarioFailure(TestScenarioLogCollection scenarioLog, TestRail testRailIdAnnotation) {
        String errorMessage = scenarioLog.getLogMessages(StepInformationLogMessage.class).stream().filter(d -> d.getStatus().equals(StepInformationLogMessage.Status.FAILED)).map(LogMessage::getMessage).findFirst().orElseThrow(() -> new IllegalStateException("expected at least one failed step"));
        for (String caseId : testRailIdAnnotation.caseId()) {
            try {
                TestRailManager.addResultForTestCase(client, caseId, getRunId(testRailIdAnnotation), 5, "Failure found in: " + errorMessage);
                TestRailManager.addAttachmentForTestCase(client, caseId, QtafFactory.getTestSuiteLogCollection().getLogDirectory() + "/Report.html");
                Set attachmentPaths = new HashSet<>();
                for (String screenshotPath : scenarioLog.getScreenshotPaths()) {
                    attachmentPaths.add(Path.of(screenshotPath).toAbsolutePath());
                }
                for (StepInformationLogMessage step : scenarioLog.getLogMessages(StepInformationLogMessage.class)) {
                    attachmentPaths.add(Path.of(step.getScreenshotBefore()).toAbsolutePath());
                    attachmentPaths.add(Path.of(step.getScreenshotAfter()).toAbsolutePath());
                }
                for (Path path : attachmentPaths) {
                    if (path.toFile().isFile()) {
                        TestRailManager.addAttachmentForTestCase(client, caseId, path.toString());
                    }
                }
                QtafFactory.getLogger().info("Results are uploaded to testRail");
            } catch (Exception e) {
                QtafFactory.getLogger().error(e);
            }
        }
    }

    /**
     * Returns the runId. The runId set in the configuration file is preferred to the runId set in the annotation.
     *
     * @param testRailIdAnnotation the annotation Object
     * @return the runId
     */
    public String getRunId(TestRail testRailIdAnnotation) {
        ConfigMap config = ConfigurationFactory.getInstance();
        String runId;
        if (null != config.getString("testrail.runId")) {
            runId = config.getString("testrail.runId");
            return runId;
        }
        if (null == testRailIdAnnotation) {
            throw new NullPointerException("The passed testRailId annotation is null");
        }
        if (testRailIdAnnotation.runId().isEmpty()) {
            throw new IllegalArgumentException("No runId could be assigned to the test case. " + "The runId must be set either via the configuration file (testrail.runId) " + "or via the corresponding annotation.(@TestRail)");
        }
        runId = testRailIdAnnotation.runId();
        return runId;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public UploadTestsSubscriber() {
    }

    /**
     * QTAF Event Subscription.
     */
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public Subscription getTestFinishedSubscription() {
        return this.testFinishedSubscription;
    }

    /**
     * testRail API client.
     */
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public APIClient getClient() {
        return this.client;
    }

    /**
     * QTAF Event Subscription.
     */
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public void setTestFinishedSubscription(final Subscription testFinishedSubscription) {
        this.testFinishedSubscription = testFinishedSubscription;
    }

    /**
     * testRail API client.
     */
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public void setClient(final APIClient client) {
        this.client = client;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (!(o instanceof UploadTestsSubscriber)) return false;
        final UploadTestsSubscriber other = (UploadTestsSubscriber) o;
        if (!other.canEqual((java.lang.Object) this)) return false;
        final java.lang.Object this$testFinishedSubscription = this.getTestFinishedSubscription();
        final java.lang.Object other$testFinishedSubscription = other.getTestFinishedSubscription();
        if (this$testFinishedSubscription == null ? other$testFinishedSubscription != null : !this$testFinishedSubscription.equals(other$testFinishedSubscription)) return false;
        final java.lang.Object this$client = this.getClient();
        final java.lang.Object other$client = other.getClient();
        if (this$client == null ? other$client != null : !this$client.equals(other$client)) return false;
        return true;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    protected boolean canEqual(final java.lang.Object other) {
        return other instanceof UploadTestsSubscriber;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final java.lang.Object $testFinishedSubscription = this.getTestFinishedSubscription();
        result = result * PRIME + ($testFinishedSubscription == null ? 43 : $testFinishedSubscription.hashCode());
        final java.lang.Object $client = this.getClient();
        result = result * PRIME + ($client == null ? 43 : $client.hashCode());
        return result;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public java.lang.String toString() {
        return "UploadTestsSubscriber(testFinishedSubscription=" + this.getTestFinishedSubscription() + ", client=" + this.getClient() + ")";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy