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

org.unitils.testlink.TestLinkConnector Maven / Gradle / Ivy

/*
 * Copyright 2012,  Unitils.org
 *
 * 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 org.unitils.testlink;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.unitils.core.UnitilsException;

import br.eti.kinoshita.testlinkjavaapi.TestLinkAPI;
import br.eti.kinoshita.testlinkjavaapi.constants.ActionOnDuplicate;
import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus;
import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionType;
import br.eti.kinoshita.testlinkjavaapi.constants.TestCaseDetails;
import br.eti.kinoshita.testlinkjavaapi.model.Build;
import br.eti.kinoshita.testlinkjavaapi.model.TestCase;
import br.eti.kinoshita.testlinkjavaapi.model.TestCaseStep;
import br.eti.kinoshita.testlinkjavaapi.model.TestPlan;
import br.eti.kinoshita.testlinkjavaapi.model.TestProject;
import br.eti.kinoshita.testlinkjavaapi.model.TestSuite;
import br.eti.kinoshita.testlinkjavaapi.util.TestLinkAPIException;
import java.util.Map;

/**
 * @author Jeroen Horemans
 * @author Thomas De Rycke
 * 
 * @since 3.3.1
 */
public class TestLinkConnector {

    private static final Logger LOGGER = Logger.getLogger(TestLinkConnector.class);

    private TestLinkAPI api;

    private String testPlanName;

    private Boolean overwrite = true;

    private String buildName;

    private String projectName;

    private Boolean createPlanIfNeeded = false;

    private Boolean createTestIfNeeded = false;

    private Boolean assignTestToPlan = false;

    private String username;
    
    private Map nameToTCTable;


    public TestLinkConnector(TestLinkAPI api, String projectName, String username, String testPlan, Boolean overwrite, String buildName) {
        this.api = api;
        this.projectName = projectName;
        this.username = username;
        this.testPlanName = testPlan;
        this.overwrite = overwrite;
        this.buildName = buildName;
        this.nameToTCTable = new HashMap();
    }


    public TestLinkConnector(TestLinkAPI api, String projectName, String username,String testPlanId, Boolean overwrite, String buildName, Boolean createPlanIfNeeded, Boolean createTestIfNeeded, Boolean assignTestToPlan) {
        this(api, projectName, username,testPlanId, overwrite, buildName);
        this.createPlanIfNeeded = createPlanIfNeeded;
        this.createTestIfNeeded = createTestIfNeeded;
        this.assignTestToPlan = assignTestToPlan;

    }

    /**
     * The method searches the testcase with that specific externalId and the testcase 
     * is added to the testplan.
     * @param externalId
     * @param msg
     * @param suite 
     * @param ex
     * @return {@link TestCase}
     */
    public TestCase updateTestCase(String externalId, String suite, String msg, Throwable ex) {

        ExecutionStatus status = getStatus(ex);
        String notes = getNotes(ex);

        TestPlan testPlan = getTestPlan(testPlanName, projectName);
        Build build = getBuild(testPlan.getId(), buildName);

        TestCase testCase = getTestCase(externalId, suite);

        try {
            api.setTestCaseExecutionResult(testCase.getId(), null, testPlan.getId(), status, build.getId(), buildName, notes, true, "", null, "", new HashMap(), overwrite);
        } catch (TestLinkAPIException e) {
            if (createTestIfNeeded) {
                // the searching for a testcase on a testplan is broken, so trial and error is the only way until the api gets fixed in a
                // future version.
                addTestCaseToTestPlan(testCase, testPlan);
                api.setTestCaseExecutionResult(testCase.getId(), null, testPlan.getId(), status, build.getId(), buildName, notes, true, "", null, "", new HashMap(), overwrite);
            } else {
                throw e;
            }
        }


        return testCase;
    }

    /**
     * It searches the testcase.
     * First the method will try to find the testcase by it's externalID
     * If it was't found the testcase is searched on projectName.
     * @param externalId
     * @param suite 
     * @return {@link TestCase}
     */
    protected TestCase getTestCase(String externalId, String suite) {
        // There is no other way than trial and error to see if the case exists.
        // first try : did we already build a mapping table ?
        if(this.nameToTCTable.containsKey(externalId)) {
            return this.nameToTCTable.get(externalId);
        }
        // if not, try to get it via external ID
        try {
            return api.getTestCaseByExternalId(externalId, null);
        } catch (TestLinkAPIException e) {            
            //do nothing            
        }
        
        TestSuite testSuite = getTestSuite(suite, getCurrentProject().getId(), getTestPlan(testPlanName, projectName).getId());
                
        //do not search for name when the externalID begins with the prefix of the project --> problems: Testlink uses the externalID as a name
        if (!externalId.startsWith(api.getTestProjectByName(this.projectName).getPrefix())) {
            LOGGER.debug("externalID not found  " + externalId + "lets try by name");
            try {
                Integer id = api.getTestCaseIDByName(externalId, testSuite.getName(), projectName, null);
                return api.getTestCase(id, null, null);
            } catch (TestLinkAPIException e) {
                if (!createTestIfNeeded) {
                    throw e;
                }
            }
        } else {
            // the name starts with the prefix, so it should be present... let's try to find them
            // via the testplan.
            if(this.nameToTCTable.isEmpty()) {                
                for(TestCase tc : api.getTestCasesForTestPlan(getTestPlan(testPlanName, projectName).getId(), null, null, null, null, false, null, null, ExecutionType.AUTOMATED, false, TestCaseDetails.SIMPLE)) {
                    this.nameToTCTable.put(tc.getFullExternalId(), tc);
                }
                LOGGER.info("Fetched "+this.nameToTCTable.size()+" automated testcases ");
            }
            if(this.nameToTCTable.containsKey(externalId)) {
                return this.nameToTCTable.get(externalId);
            }
        }


        LOGGER.info("case " + externalId + " not found, creating it now");

        return createTestCase(externalId, testSuite.getId());

    }

    /**
     * A test case is created with the externalId.
     * @param externalId
     * @param suite 
     * @return {@link TestCase}
     */
    protected TestCase createTestCase(String externalId, Integer suiteId) {
        if (!createTestIfNeeded) {
            throw new UnitilsException("error in TestLink module, plz contact the quality assurance team");
        }
        TestProject project = getCurrentProject();

        TestCase result = api.createTestCase(externalId, suiteId, project.getId(), username, "To be fixed", new ArrayList(), "", null, null, null, null, true, ActionOnDuplicate.CREATE_NEW_VERSION);
        result.setVersion(1);
        return result;
    }

    /**
     * It looks for a test project that has the same name as the projectName (org.unitils.testlink.project in unitils-jenkins.properties).
     * @return {@link TestProject}
     */
    private TestProject getCurrentProject() {
        return api.getTestProjectByName(projectName);
    }

    /**
     * This method looks if there is a suite with this name
     * -YES: returns the {@link TestSuite}
     * -NO: creates a {@link TestSuite} with this name and returns it.
     * @param suiteId
     * @param suiteName
     * @param projectId
     * @param testPlanId
     * @return {@link TestSuite}
     */
    protected TestSuite getTestSuite(String suiteName, Integer projectId, Integer testPlanId) {
        String[] suiteNames = suiteName.split("/");
        List suites = new ArrayList(Arrays.asList(api.getTestSuitesForTestPlan(testPlanId)));

        int index = 0;
        TestSuite testSuite = null;
        for (int i = 0; i < suiteNames.length; i++) {
            String suite = suiteNames[i];
            if (index == 0) {
                //, (suiteNames.length == 1)
                testSuite = createOrGetTestSuite(suite, projectId, suites, null);
            } else {
                //, (i == (suiteNames.length - 1))
                testSuite = createOrGetTestSuite(suite, projectId, suites, testSuite.getId());
            }
            index++;
        }  
        return testSuite;
    }
    //, boolean last
    private TestSuite createOrGetTestSuite(String suiteName, Integer projectId, List suites, Integer parentId) {
        if (suiteName.isEmpty()) {
            return suites.get(0);
        }

        for (TestSuite testSuite : suites) {
            if (testSuite.getName().equals(suiteName) && (testSuite.getParentId().equals(parentId) || parentId == null)) {
                return testSuite;
            }
        }

        //no suitename found
        TestSuite suite = api.createTestSuite(projectId, suiteName, "", parentId, 1, true, ActionOnDuplicate.CREATE_NEW_VERSION);
        suites.add(suite);
        return suite;
    }

    /**
     * If the property assingTestIfNeeded in the unitils-jenkins.properties is set to true; 
     * than the test is added to the test plan. 
     * @param testCase
     * @param testPlan
     */
    protected void addTestCaseToTestPlan(TestCase testCase, TestPlan testPlan) {
        if (assignTestToPlan) {
            TestProject project = getCurrentProject();
            api.addTestCaseToTestPlan(project.getId(), testPlan.getId(), testCase.getId(), testCase.getVersion(), null, null, null);
        }
    }

    /***
     * It retrieves the test plan from Testlink
     * @param testPlanName2
     * @param projectName1
     * @return {@link TestPlan}
     */
    protected TestPlan getTestPlan(String testPlanName2, String projectName1) {

        try {
            return api.getTestPlanByName(testPlanName, projectName1);
        } catch (TestLinkAPIException e) {
            if (!createPlanIfNeeded) {
                throw e;
            }
        }
        return api.createTestPlan(testPlanName2, projectName1, null, true, true);
    }

    /**
     * Retrieves the build with a given buildname from a given test plan.
     * If there isn't a build with that name, than a build with that name is created.
     * @param testPlanId
     * @param buildName1
     * @return {@link Build}
     */
    protected Build getBuild(Integer testPlanId, String buildName1) {
        Build[] builds = api.getBuildsForTestPlan(testPlanId);

        if (builds != null) {
            for (Build build : builds) {
                if (buildName1.equalsIgnoreCase(build.getName())) {
                    return build;
                }
            }
        }
        return api.createBuild(testPlanId, buildName1, "");
    }

    /**
     * If the ex isn't null, the method will give you the message of the throwable.
     * Otherwise the method returns 'ok'.
     * @param ex
     * @return {@link String}
     */
    protected String getNotes(Throwable ex) {
        if (ex != null) {
            return ex.getMessage();
        }
        return "ok";
    }

    /**
     * If the param ex is null, it will return passed, otherwise failed will be returned.
     * @param ex
     * @return {@link ExecutionStatus}
     */
    protected ExecutionStatus getStatus(Throwable ex) {
        if (ex != null) {
            return ExecutionStatus.FAILED;
        }
        return ExecutionStatus.PASSED;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy