diff --git a/.gitignore b/.gitignore index c43ada0..62c3d15 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ inject-tests/ test-output *~ *.iml +.idea diff --git a/pom.xml b/pom.xml index 93c9b86..e9f16ae 100644 --- a/pom.xml +++ b/pom.xml @@ -293,6 +293,11 @@ junit 1.11 + + org.jenkins-ci.plugins.workflow + workflow-step-api + 2.1 + diff --git a/src/main/java/hudson/plugins/testlink/AbstractTestLinkBuilder.java b/src/main/java/hudson/plugins/testlink/AbstractTestLinkBuilder.java index 0233483..60ba321 100644 --- a/src/main/java/hudson/plugins/testlink/AbstractTestLinkBuilder.java +++ b/src/main/java/hudson/plugins/testlink/AbstractTestLinkBuilder.java @@ -58,6 +58,10 @@ public class AbstractTestLinkBuilder extends Builder { * The name of the Build. */ protected String buildName; + /** + * The Build custom fields. + */ + protected String buildCustomFields; /** * The platform name. */ @@ -133,7 +137,7 @@ public class AbstractTestLinkBuilder extends Builder { * Create a AbstractTestLinkBuilder. */ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, String testPlanName, - String platformName, String buildName, String customFields, String testPlanCustomFields, List singleBuildSteps, + String platformName, String buildName, String buildCustomFields, String customFields, String testPlanCustomFields, List singleBuildSteps, List beforeIteratingAllTestCasesBuildSteps, List iterativeBuildSteps, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun, @@ -144,6 +148,7 @@ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, Stri this.testPlanName = testPlanName; this.platformName = platformName; this.buildName = buildName; + this.buildCustomFields = buildCustomFields; this.customFields = customFields; this.testPlanCustomFields = testPlanCustomFields; this.singleBuildSteps = singleBuildSteps; @@ -162,12 +167,12 @@ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, Stri * @deprecated to add test plan custom fields */ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, String testPlanName, - String platformName, String buildName, String customFields, List singleBuildSteps, + String platformName, String buildName, String buildCustomFields, String customFields, List singleBuildSteps, List beforeIteratingAllTestCasesBuildSteps, List iterativeBuildSteps, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun, List resultSeekers) { - this(testLinkName, testProjectName, testPlanName, platformName, buildName, customFields, + this(testLinkName, testProjectName, testPlanName, platformName, buildName, buildCustomFields, customFields, /*testPlanCustomFields*/ null, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, afterIteratingAllTestCasesBuildSteps, transactional, failedTestsMarkBuildAsFailure, failIfNoResults, failOnNotRun, resultSeekers); @@ -181,6 +186,7 @@ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, Stri * @param testPlanName TestLink Test Plan name. * @param platformName TestLink Platform name. * @param buildName TestLink Build name. + * @param buildCustomFields TestLink Build custom fields. * @param customFields TestLink comma-separated list of Custom Fields. * @param singleBuildSteps List of build steps to execute once for all automated test cases. * @param beforeIteratingAllTestCasesBuildSteps Command executed before iterating all test cases. @@ -193,13 +199,13 @@ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, Stri * @deprecated */ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, String testPlanName, - String platformName, String buildName, String customFields, Boolean executionStatusNotRun, + String platformName, String buildName, String buildCustomFields, String customFields, Boolean executionStatusNotRun, Boolean executionStatusPassed, Boolean executionStatusFailed, Boolean executionStatusBlocked, List singleBuildSteps, List beforeIteratingAllTestCasesBuildSteps, List iterativeBuildSteps, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun, List resultSeekers) { - this(testLinkName, testProjectName, testPlanName, platformName, buildName, customFields, + this(testLinkName, testProjectName, testPlanName, platformName, buildName, buildCustomFields, customFields, /*testPlanCustomFields*/ null, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, afterIteratingAllTestCasesBuildSteps, transactional, failedTestsMarkBuildAsFailure, failIfNoResults, failOnNotRun, resultSeekers); @@ -225,6 +231,8 @@ public String getBuildName() { return this.buildName; } + public String getBuildCustomFields() { return this.buildCustomFields; } + public String getCustomFields() { return this.customFields; } diff --git a/src/main/java/hudson/plugins/testlink/TestLinkBuildAction.java b/src/main/java/hudson/plugins/testlink/TestLinkBuildAction.java index 2e47e26..eef4635 100644 --- a/src/main/java/hudson/plugins/testlink/TestLinkBuildAction.java +++ b/src/main/java/hudson/plugins/testlink/TestLinkBuildAction.java @@ -23,7 +23,6 @@ */ package hudson.plugins.testlink; -import hudson.model.Action; import hudson.model.AbstractBuild; import hudson.model.Run; import hudson.plugins.testlink.util.TestLinkHelper; diff --git a/src/main/java/hudson/plugins/testlink/TestLinkBuilder.java b/src/main/java/hudson/plugins/testlink/TestLinkBuilder.java index bff56aa..5b38f87 100644 --- a/src/main/java/hudson/plugins/testlink/TestLinkBuilder.java +++ b/src/main/java/hudson/plugins/testlink/TestLinkBuilder.java @@ -28,6 +28,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -90,7 +91,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, List resultSeekers) { - this(testLinkName, testProjectName, testPlanName, buildName, + this(testLinkName, testProjectName, testPlanName, buildName, null, null, customFields, executionStatusNotRun, executionStatusPassed, executionStatusFailed, executionStatusBlocked, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, @@ -112,7 +113,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun, List resultSeekers) { - super(testLinkName, testProjectName, testPlanName, buildName, null, + super(testLinkName, testProjectName, testPlanName, buildName, null, null, customFields, executionStatusNotRun, executionStatusPassed, executionStatusFailed, executionStatusBlocked, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, @@ -125,7 +126,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName, * @deprecated to add test plan custom fields */ public TestLinkBuilder(String testLinkName, String testProjectName, - String testPlanName, String platformName, String buildName, String customFields, + String testPlanName, String platformName, String buildName, String buildCustomFields, String customFields, Boolean executionStatusNotRun, Boolean executionStatusPassed, Boolean executionStatusFailed, Boolean executionStatusBlocked, List singleBuildSteps, @@ -134,7 +135,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun, List resultSeekers) { - super(testLinkName, testProjectName, testPlanName, platformName, buildName, + super(testLinkName, testProjectName, testPlanName, platformName, buildName, buildCustomFields, customFields, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, afterIteratingAllTestCasesBuildSteps, transactional, failedTestsMarkBuildAsFailure, failIfNoResults, failOnNotRun, resultSeekers); @@ -142,7 +143,8 @@ public TestLinkBuilder(String testLinkName, String testProjectName, @DataBoundConstructor public TestLinkBuilder(String testLinkName, String testProjectName, - String testPlanName, String platformName, String buildName, String customFields, String testPlanCustomFields, + String testPlanName, String platformName, String buildName, + String buildCustomFields, String customFields, String testPlanCustomFields, Boolean executionStatusNotRun, Boolean executionStatusPassed, Boolean executionStatusFailed, Boolean executionStatusBlocked, List singleBuildSteps, @@ -151,7 +153,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName, List afterIteratingAllTestCasesBuildSteps, Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun, List resultSeekers) { - super(testLinkName, testProjectName, testPlanName, platformName, buildName, + super(testLinkName, testProjectName, testPlanName, platformName, buildName, buildCustomFields, customFields, testPlanCustomFields, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, afterIteratingAllTestCasesBuildSteps, transactional, failedTestsMarkBuildAsFailure, failIfNoResults, failOnNotRun, resultSeekers); @@ -194,6 +196,8 @@ public boolean perform(AbstractBuild build, Launcher launcher, build.getEnvironment(listener), getPlatformName()); final String buildName = TestLinkHelper.expandVariable(build.getBuildVariableResolver(), build.getEnvironment(listener), getBuildName()); + final String buildCustomFields = TestLinkHelper.expandVariable(build.getBuildVariableResolver(), + build.getEnvironment(listener), getBuildCustomFields()); final String buildNotes = Messages.TestLinkBuilder_Build_Notes(); if(LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "TestLink project name: ["+testProjectName+"]"); @@ -201,9 +205,10 @@ public boolean perform(AbstractBuild build, Launcher launcher, LOGGER.log(Level.FINE, "TestLink platform name: ["+platformName+"]"); LOGGER.log(Level.FINE, "TestLink build name: ["+buildName+"]"); LOGGER.log(Level.FINE, "TestLink build notes: ["+buildNotes+"]"); + LOGGER.log(Level.FINE, "TestLink build Custom Fields: ["+buildCustomFields+"]"); } // TestLink Site object - testLinkSite = this.getTestLinkSite(testLinkUrl, testLinkDevKey, testProjectName, testPlanName, platformName, buildName, buildNotes); + testLinkSite = this.getTestLinkSite(testLinkUrl, testLinkDevKey, testProjectName, testPlanName, platformName, buildName, buildCustomFields, buildNotes); if (StringUtils.isNotBlank(platformName) && testLinkSite.getPlatform() == null) listener.getLogger().println(Messages.TestLinkBuilder_PlatformNotFound(platformName)); @@ -257,7 +262,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, if(getResultSeekers() != null) { for (ResultSeeker resultSeeker : getResultSeekers()) { LOGGER.log(Level.INFO, "Seeking test results. Using: " + resultSeeker.getDescriptor().getDisplayName()); - resultSeeker.seek(automatedTestCases, build, launcher, listener, testLinkSite); + resultSeeker.seek(automatedTestCases, build, build.getWorkspace(), launcher, listener, testLinkSite); } } } catch (ResultSeekerException trse) { @@ -325,7 +330,7 @@ private TestCaseWrapper[] transform(TestCase[] testCases) { */ public TestLinkSite getTestLinkSite(String testLinkUrl, String testLinkDevKey, String testProjectName, String testPlanName, String platformName, - String buildName, String buildNotes) throws MalformedURLException { + String buildName, String buildCustomFields, String buildNotes) throws MalformedURLException { final TestLinkAPI api; final URL url = new URL(testLinkUrl); api = new TestLinkAPI(url, testLinkDevKey); @@ -344,7 +349,23 @@ public TestLinkSite getTestLinkSite(String testLinkUrl, String testLinkDevKey, } } + /* Extract custom fields and values */ + java.util.Map cfs = new HashMap(); + if(buildCustomFields != null && !(buildCustomFields.isEmpty())) { + for (String part: buildCustomFields.split(",")) { + String[] cf = part.split(":"); + String name = cf[0].replaceAll("\\s+", ""); + String value = cf[1].replaceAll("\\s+", ""); + cfs.put(name, value); + } + } + final Build build = api.createBuild(testPlan.getId(), buildName, buildNotes); + try { + api.updateBuildCustomFields(build.getId(), testProject.getId(), testPlan.getId(), cfs); + }catch(TestLinkAPIException e) { + LOGGER.log(Level.INFO, "TestLink builder failed ro update build custom fields. " + e); + } return new TestLinkSite(api, testProject, testPlan, platform, build); } diff --git a/src/main/java/hudson/plugins/testlink/TestLinkJunitWrapper.java b/src/main/java/hudson/plugins/testlink/TestLinkJunitWrapper.java new file mode 100644 index 0000000..77535b7 --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/TestLinkJunitWrapper.java @@ -0,0 +1,151 @@ +/* + * The MIT License + * + * Copyright (c) <2011> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.plugins.testlink; + +import hudson.tasks.junit.JUnitParser; +import hudson.tasks.junit.TestResult; +import hudson.model.Run; +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.TaskListener; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Map; +import java.util.HashMap; + +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.DirectoryScanner; +import hudson.Util; +import jenkins.MasterToSlaveFileCallable; +import hudson.remoting.VirtualChannel; +import org.dom4j.io.SAXReader; +import org.dom4j.Document; +import org.dom4j.Element; +import java.util.List; +import java.util.Iterator; +import java.util.logging.Logger; + +/** + * Created by azikha01 on 29/07/2016. + */ +public class TestLinkJunitWrapper extends JUnitParser { + private Map> customFields = null; + private PrintStream logger = null; + private static final Logger LOGGER = Logger.getLogger("hudson.plugins.testlink"); + + public TestLinkJunitWrapper(boolean keepLongStdio, boolean allowEmptyResults) { + super(keepLongStdio, allowEmptyResults); + } + + public TestResult parseResult(String testResultLocations, Run build, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { + + logger = listener.getLogger(); + TestResult r = super.parseResult(testResultLocations, build, workspace, launcher, listener); + + /* Second parse of files to find Test Case custom field values */ + this.customFields = (Map>)workspace.act(new TestLinkJunitWrapper.ParseResultCallable(testResultLocations)); + Iterator it = customFields.entrySet().iterator(); + while (it.hasNext()){ + Map.Entry pair = (Map.Entry)it.next(); + logger.println("Test Case " + pair.getKey()); + Map cfs = (Map)pair.getValue(); + Iterator itt = cfs.entrySet().iterator(); + while (itt.hasNext()) { + Map.Entry pairr = (Map.Entry)itt.next(); + logger.println("\tCustom field = " + pairr.getKey() + " value = " + pairr.getValue()); + } + } + return r; + } + + private static class ParseResultCallable extends MasterToSlaveFileCallable>> { + private final String testResults; + + private ParseResultCallable(String testResults) { + this.testResults = testResults; + } + + public Map> invoke(File ws, VirtualChannel channel) throws IOException { + FileSet fs = Util.createFileSet(ws, this.testResults); + DirectoryScanner ds = fs.getDirectoryScanner(); + Map> customFields = new HashMap>(); + String[] files = ds.getIncludedFiles(); + if(files.length > 0) { + String[] reportFiles = ds.getIncludedFiles(); + File baseDir = ds.getBasedir(); + + int len$ = reportFiles.length; + + for(int f = 0; f < len$; ++f) { + String value = reportFiles[f]; + File reportFile = new File(baseDir, value); + + try { + this.parseCustomFields(reportFile, customFields); + } catch (org.dom4j.DocumentException e) { + throw new IOException(e); + } + } + + } + + return customFields; + } + + private void parseCustomFields (File reportFile, Map> customFields) throws org.dom4j.DocumentException { + String xmlReport = reportFile.getName(); + SAXReader saxReader = new SAXReader(); + Document result = saxReader.read(reportFile); + Element root = result.getRootElement(); + List testCases = root.elements("testcase"); + + for(Iterator stdout = testCases.iterator(); stdout.hasNext();) { + Element tc = (Element)stdout.next(); + String m = tc.attributeValue("classname"); + Map cfs = new HashMap(); + // Get other attributes and extract custom fields + List children = tc.elements(); + for (Iterator child = children.iterator(); child.hasNext();){ + // get tag and text + Element childe = (Element)child.next(); + // exclude Junit defined names like error, failure, stdin, stdout + if (childe.getName().equals("skipped") || + childe.getName().equals("error") || + childe.getName().equals("failure") || + childe.getName().equals("system-out") || + childe.getName().equals("system-err") + ) { + continue; + } + cfs.put(childe.getName(), childe.getText()); + // what should we do with these custom fields + customFields.put(m, cfs); + } + } + } + } + + public Map> getCustomFields (){ return customFields;} +} diff --git a/src/main/java/hudson/plugins/testlink/TestLinkSite.java b/src/main/java/hudson/plugins/testlink/TestLinkSite.java index 1d94cc9..d4c2aae 100644 --- a/src/main/java/hudson/plugins/testlink/TestLinkSite.java +++ b/src/main/java/hudson/plugins/testlink/TestLinkSite.java @@ -218,7 +218,7 @@ public int updateTestCase(TestCaseWrapper testCase) { null, // bug id platformId, // platform id platformName, // platform name - null, // custom fields + testCase.getCustomFieldsExecutionValues(), // custom fields null); switch(testCase.getExecutionStatus()) { diff --git a/src/main/java/hudson/plugins/testlink/pipeline/TestLinkCreateBuildExecution.java b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkCreateBuildExecution.java new file mode 100644 index 0000000..665eb2c --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkCreateBuildExecution.java @@ -0,0 +1,87 @@ +package hudson.plugins.testlink.pipeline; + +import com.google.inject.Inject; +import hudson.AbortException; +import hudson.Launcher; +import hudson.model.*; +import hudson.plugins.testlink.TestLinkBuilder; +import hudson.plugins.testlink.TestLinkBuilderDescriptor; +import hudson.plugins.testlink.TestLinkInstallation; +import hudson.plugins.testlink.TestLinkSite; +import hudson.plugins.testlink.result.ResultSeeker; +import hudson.tasks.BuildStep; +import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; +import org.jenkinsci.plugins.workflow.steps.StepContextParameter; + +import java.util.ArrayList; + +/** + * Created by azikha01 on 11/10/2016. + */ +public class TestLinkCreateBuildExecution extends AbstractSynchronousNonBlockingStepExecution{ + + @Inject + private transient TestLinkCreateBuildStep config; + + @StepContextParameter + private transient TaskListener listener; + + @StepContextParameter + private transient Launcher launcher; + + @StepContextParameter + private transient Run build; + + @Override + protected Void run() throws Exception{ + listener.getLogger().println(config.getTestLinkName() + " \n" + + config.getTestProjectName() + " \n" + + config.getTestPlanName() + " \n" + + config.getTestPlanCustomFields() + " \n" + + config.getBuildName() + " \n" + + config.getBuildCustomFields() + " \n" + + config.getCustomFields() + " \n" + + config.getTestProjectName() + " \n" + ); + + TestLinkBuilderDescriptor DESCRIPTOR = new TestLinkBuilderDescriptor(); + final TestLinkInstallation installation = DESCRIPTOR + .getInstallationByTestLinkName(config.getTestLinkName()); + if (installation == null) { + throw new AbortException("Failed to find TestLink installation: " + config.getTestLinkName()); + } + + final TestLinkSite testLinkSite; + final String testLinkUrl = installation.getUrl(); + final String testLinkDevKey = installation.getDevKey(); + + TestLinkBuilder builder = new TestLinkBuilder(config.getTestLinkName(), + config.getTestProjectName(), + config.getTestPlanName(), + config.getPlatformName(), + config.getBuildName(), + config.getBuildCustomFields(), + config.getCustomFields(), + config.getTestPlanCustomFields(), + false, + false, + false, + false, + new ArrayList(), + new ArrayList(), + new ArrayList(), + new ArrayList(), + false, true, false, false, new ArrayList< ResultSeeker>() + ); + builder.getTestLinkSite(testLinkUrl, + testLinkDevKey, + config.getTestProjectName(), + config.getTestPlanName(), + config.getPlatformName(), + config.getBuildName(), + config.getBuildCustomFields(), + config.getBuildNotes()); + + return null; + } +} diff --git a/src/main/java/hudson/plugins/testlink/pipeline/TestLinkCreateBuildStep.java b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkCreateBuildStep.java new file mode 100644 index 0000000..20e9d60 --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkCreateBuildStep.java @@ -0,0 +1,126 @@ +package hudson.plugins.testlink.pipeline; + +import java.io.Serializable; + +import hudson.Extension; +import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; +import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; + +/** + * Created by azikha01 on 11/10/2016. + */ +public class TestLinkCreateBuildStep extends AbstractStepImpl implements Serializable { + private static final long serialVersionUID = 1L; + + /* --- Step properties --- */ + /** + * The name of the TestLink installation. + */ + @DataBoundSetter + private String testLinkName = "(Default)"; + /** + * The name of the Test Project. + */ + @DataBoundSetter + private String testProjectName = null; + /** + * The name of the Test Plan. + */ + @DataBoundSetter + private String testPlanName = null; + /** + * The name of the Build. + */ + @DataBoundSetter + private String buildName = null; + /** + * The Build custom fields. + */ + @DataBoundSetter + private String buildCustomFields = null; + /** + * The platform name. + */ + @DataBoundSetter + private String platformName = null; + /** + * Comma separated list of custom fields to download from TestLink. + */ + @DataBoundSetter + private String customFields = null; + + /** + * Comma separated list of test plan custom fields to download from TestLink. + */ + @DataBoundSetter + private String testPlanCustomFields = null; + + /** + * Build Notes + */ + @DataBoundSetter + private String buildNotes = null; + + @DataBoundConstructor + public TestLinkCreateBuildStep(){ + + } + + public String getTestLinkName(){ + return testLinkName; + } + + public String getTestProjectName(){ + return testProjectName; + } + + public String getTestPlanName(){ + return testPlanName; + } + + public String getBuildName(){ + return buildName; + } + + public String getBuildCustomFields(){ + return buildCustomFields; + } + + public String getPlatformName() { + return platformName; + } + + public String getCustomFields(){ + return customFields; + } + + public String getTestPlanCustomFields(){ + return testPlanCustomFields; + } + + public String getBuildNotes(){ + return buildNotes; + } + + @Extension + public static final class DescriptorImpl extends AbstractStepDescriptorImpl { + public static final String STEP_NAME = "testLinkCreateBuild"; + + public DescriptorImpl(){ + super(TestLinkCreateBuildExecution.class); + + } + + @Override + public String getFunctionName(){ + return STEP_NAME; + } + + @Override + public String getDisplayName(){ + return STEP_NAME; + } + } +} diff --git a/src/main/java/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanExecution.java b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanExecution.java new file mode 100644 index 0000000..36cd176 --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanExecution.java @@ -0,0 +1,124 @@ +package hudson.plugins.testlink.pipeline; + +import br.eti.kinoshita.testlinkjavaapi.TestLinkAPI; +import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus; +import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionType; +import br.eti.kinoshita.testlinkjavaapi.constants.ResponseDetails; +import br.eti.kinoshita.testlinkjavaapi.constants.TestCaseDetails; +import br.eti.kinoshita.testlinkjavaapi.model.*; +import com.google.inject.Inject; +import hudson.AbortException; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.plugins.testlink.TestLinkBuilderDescriptor; +import hudson.plugins.testlink.TestLinkInstallation; +import hudson.plugins.testlink.TestLinkSite; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; +import org.jenkinsci.plugins.workflow.steps.StepContextParameter; + +import java.io.File; +import java.io.FileWriter; +import java.net.URL; + +/** + * Created by azikha01 on 11/10/2016. + */ +public class TestLinkDownloadTestPlanExecution extends AbstractSynchronousNonBlockingStepExecution{ + + @Inject + private transient TestLinkDownloadTestPlanStep config; + + @StepContextParameter + private transient TaskListener listener; + + @StepContextParameter + private transient Launcher launcher; + + @StepContextParameter + private transient Run build; + + @Override + protected Void run() throws Exception{ + if (!(new File(config.getTestPlanFileName())).isAbsolute()){ + throw new Exception("Test plan path not absolute: " + config.getTestPlanFileName()); + } + TestLinkBuilderDescriptor DESCRIPTOR = new TestLinkBuilderDescriptor(); + final TestLinkInstallation installation = DESCRIPTOR + .getInstallationByTestLinkName(config.getTestLinkName()); + if (installation == null) { + throw new AbortException("Failed to find TestLink installation: " + config.getTestLinkName()); + } + + final TestLinkSite testLinkSite; + final String testLinkUrl = installation.getUrl(); + final String testLinkDevKey = installation.getDevKey(); + + final URL url = new URL(testLinkUrl); + TestLinkAPI api = new TestLinkAPI(url, testLinkDevKey); + final TestProject testProject = api.getTestProjectByName(config.getTestProjectName()); + final TestPlan testPlan = api.getTestPlanByName(config.getTestPlanName(), config.getTestProjectName()); + + String [] parts = config.getCustomFields().split(","); + String [] customFields = new String[parts.length]; + for (int i = 0; i < parts.length; i++){ + customFields[i] = parts[i].trim(); + } + + JSONObject testPlanJson = new JSONObject(); + testPlanJson.put("name", testPlan.getName()); + testPlanJson.put("id", testPlan.getId()); + testPlanJson.put("project_name", testProject.getName()); + testPlanJson.put("project_id", testProject.getId()); + + JSONArray testCasesJson = new JSONArray(); + + final TestCase[] testCases = api.getTestCasesForTestPlan( + testPlan.getId(), + null, + null, + null, + null, + null, + null, + null, // execute status + ExecutionType.AUTOMATED, + Boolean.TRUE, + TestCaseDetails.FULL); + + for( final TestCase testCase : testCases ) { + JSONObject testCaseJson = new JSONObject(); + testCaseJson.put("name", testCase.getName()); + testCaseJson.put("id", testCase.getId()); + JSONArray customFieldsJson = new JSONArray(); + + testCase.setTestProjectId(testProject.getId()); + testCase.setExecutionStatus(ExecutionStatus.NOT_RUN); + if (customFields != null) { + for(String customFieldName : customFields) { + final CustomField customField = api.getTestCaseCustomFieldDesignValue( + testCase.getId(), + null, /* testCaseExternalId */ + testCase.getVersion(), + testProject.getId(), + customFieldName, + ResponseDetails.FULL); + testCase.getCustomFields().add(customField); + JSONObject customFieldJson = new JSONObject(); + customFieldJson.put("name", customField.getName()); + customFieldJson.put("value", customField.getValue()); + customFieldsJson.add(customFieldJson); + } + testCaseJson.put("custom_fields", customFieldsJson); + } + listener.getLogger().println("Test Case: " + testCase.toString()); + testCasesJson.add(testCaseJson); + } + testPlanJson.put("test_cases", testCasesJson); + testPlanJson.write(new FileWriter(config.getTestPlanFileName())); + + return null; + } +} diff --git a/src/main/java/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanStep.java b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanStep.java new file mode 100644 index 0000000..4c172d7 --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanStep.java @@ -0,0 +1,80 @@ +package hudson.plugins.testlink.pipeline; + +import hudson.Extension; +import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; +import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; + +import java.io.Serializable; + +/** + * Created by azikha01 on 11/10/2016. + */ +public class TestLinkDownloadTestPlanStep extends AbstractStepImpl implements Serializable { + private static final long serialVersionUID = 1L; + + /* --- Step properties --- */ + /** + * The name of the TestLink installation. + */ + @DataBoundSetter + private String testLinkName = "(Default)"; + /** + * The name of the Test Project. + */ + @DataBoundSetter + private String testProjectName = null; + /** + * The name of the Test Plan. + */ + @DataBoundSetter + private String testPlanName = null; + + @DataBoundSetter + private String customFields = null; + + @DataBoundSetter + private String testPlanFileName = null; + + @DataBoundConstructor + public TestLinkDownloadTestPlanStep(){ + + } + + public String getTestLinkName(){ + return testLinkName; + } + + public String getTestProjectName(){ + return testProjectName; + } + + public String getTestPlanName(){ + return testPlanName; + } + + public String getCustomFields(){ return customFields; } + + public String getTestPlanFileName() {return testPlanFileName; } + + @Extension + public static final class DescriptorImpl extends AbstractStepDescriptorImpl { + public static final String STEP_NAME = "testLinkDownloadTestPlan"; + + public DescriptorImpl(){ + super(TestLinkDownloadTestPlanExecution.class); + + } + + @Override + public String getFunctionName(){ + return STEP_NAME; + } + + @Override + public String getDisplayName(){ + return STEP_NAME; + } + } +} diff --git a/src/main/java/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsExecution.java b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsExecution.java new file mode 100644 index 0000000..f2487ac --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsExecution.java @@ -0,0 +1,123 @@ +package hudson.plugins.testlink.pipeline; + +import br.eti.kinoshita.testlinkjavaapi.model.TestCase; +import br.eti.kinoshita.testlinkjavaapi.util.TestLinkAPIException; +import com.google.inject.Inject; +import hudson.AbortException; +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.plugins.testlink.*; +import hudson.plugins.testlink.result.JUnitCaseClassNameResultSeeker; +import hudson.plugins.testlink.result.ResultSeeker; +import hudson.plugins.testlink.result.ResultSeekerException; +import hudson.plugins.testlink.result.TestCaseWrapper; +import hudson.tasks.BuildStep; +import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; +import org.jenkinsci.plugins.workflow.steps.StepContextParameter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by azikha01 on 11/10/2016. + */ +public class TestLinkUploadTestResultsExecution extends AbstractSynchronousNonBlockingStepExecution { + + @Inject + private transient TestLinkUploadTestResultsStep config; + + @StepContextParameter + private transient TaskListener listener; + + @StepContextParameter + private transient Launcher launcher; + + @StepContextParameter + private transient Run build; + + @StepContextParameter + private transient FilePath workspace; + + @Override + protected Void run() throws Exception{ + listener.getLogger().println(config.getTestLinkName() + " \n" + + config.getTestProjectName() + " \n" + + config.getTestPlanName() + " \n" + + config.getTestPlanCustomFields() + " \n" + + config.getBuildName() + " \n" + + config.getBuildCustomFields() + " \n" + + config.getCustomFields() + " \n" + + config.getTestProjectName() + " \n" + + config.getResultsFilePattern() + " \n" + ); + + TestLinkBuilderDescriptor DESCRIPTOR = new TestLinkBuilderDescriptor(); + final TestLinkInstallation installation = DESCRIPTOR + .getInstallationByTestLinkName(config.getTestLinkName()); + if (installation == null) { + throw new AbortException("Failed to find TestLink installation: " + config.getTestLinkName()); + } + + final TestLinkSite testLinkSite; + final String testLinkUrl = installation.getUrl(); + final String testLinkDevKey = installation.getDevKey(); + + TestLinkBuilder builder = new TestLinkBuilder(config.getTestLinkName(), + config.getTestProjectName(), + config.getTestPlanName(), + config.getPlatformName(), + config.getBuildName(), + config.getBuildCustomFields(), + config.getCustomFields(), + config.getTestPlanCustomFields(), + false, + false, + false, + false, + new ArrayList(), + new ArrayList(), + new ArrayList(), + new ArrayList(), + false, true, false, false, new ArrayList< ResultSeeker>() + ); + testLinkSite = builder.getTestLinkSite(testLinkUrl, + testLinkDevKey, + config.getTestProjectName(), + config.getTestPlanName(), + config.getPlatformName(), + config.getBuildName(), + config.getBuildCustomFields(), + config.getBuildNotes()); + + ArrayList customFieldsList = new ArrayList(); + for (String cf : config.getCustomFields().split(",")){ + customFieldsList.add(cf.trim()); + } + String [] customFieldArray = new String[customFieldsList.size()]; + for (int i = 0; i < customFieldsList.size(); i++){ + customFieldArray[i] = customFieldsList.get(i); + } + TestCase[] testCases = testLinkSite.getAutomatedTestCases(customFieldArray); + List automatedTestCases = new ArrayList(); + for(TestCase testCase : testCases) { + TestCaseWrapper wrapper = new TestCaseWrapper(testCase); + automatedTestCases.add(wrapper); + } + TestCaseWrapper[] automatedTestCaseWrapper = automatedTestCases.toArray(new TestCaseWrapper[0]); + try { + ResultSeeker rs = new JUnitCaseClassNameResultSeeker(config.getResultsFilePattern(), + config.getKeyCustomField(), false, true); + rs.seek(automatedTestCaseWrapper, build, workspace, launcher, listener, testLinkSite); + } catch (ResultSeekerException trse) { + trse.printStackTrace(listener.fatalError(trse.getMessage())); + throw new AbortException(trse.getMessage()); + } catch (TestLinkAPIException tlae) { + tlae.printStackTrace(listener.fatalError(tlae.getMessage())); + throw new AbortException(tlae.getMessage()); + } + + return null; + } +} diff --git a/src/main/java/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsStep.java b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsStep.java new file mode 100644 index 0000000..7ce09a3 --- /dev/null +++ b/src/main/java/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsStep.java @@ -0,0 +1,142 @@ +package hudson.plugins.testlink.pipeline; + +import hudson.Extension; +import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; +import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; + +import java.io.Serializable; + +/** + * Created by azikha01 on 11/10/2016. + */ +public class TestLinkUploadTestResultsStep extends AbstractStepImpl implements Serializable { + private static final long serialVersionUID = 1L; + + /* --- Step properties --- */ + /** + * The name of the TestLink installation. + */ + @DataBoundSetter + private String testLinkName = "(Default)"; + /** + * The name of the Test Project. + */ + @DataBoundSetter + private String testProjectName = null; + /** + * The name of the Test Plan. + */ + @DataBoundSetter + private String testPlanName = null; + /** + * The name of the Build. + */ + @DataBoundSetter + private String buildName = null; + /** + * The Build custom fields. + */ + @DataBoundSetter + private String buildCustomFields = null; + /** + * The platform name. + */ + @DataBoundSetter + private String platformName = null; + /** + * Comma separated list of custom fields to download from TestLink. + */ + @DataBoundSetter + private String customFields = null; + + /** + * Comma separated list of test plan custom fields to download from TestLink. + */ + @DataBoundSetter + private String testPlanCustomFields = null; + + /** + * Build Notes + */ + @DataBoundSetter + private String buildNotes = null; + + /** + * Test results file (Junit.xml) path + */ + @DataBoundSetter + private String resultsFilePattern = null; + + /** + * Test results file (Junit.xml) path + */ + @DataBoundSetter + private String keyCustomField = null; + + @DataBoundConstructor + public TestLinkUploadTestResultsStep(){ + + } + + public String getTestLinkName(){ + return testLinkName; + } + + public String getTestProjectName(){ + return testProjectName; + } + + public String getTestPlanName(){ + return testPlanName; + } + + public String getBuildName(){ + return buildName; + } + + public String getBuildCustomFields(){ + return buildCustomFields; + } + + public String getPlatformName() { + return platformName; + } + + public String getCustomFields(){ + return customFields; + } + + public String getTestPlanCustomFields(){ + return testPlanCustomFields; + } + + public String getBuildNotes(){ + return buildNotes; + } + + public String getResultsFilePattern() { return resultsFilePattern; } + + public String getKeyCustomField() { return keyCustomField; } + + @Extension + public static final class DescriptorImpl extends AbstractStepDescriptorImpl { + public static final String STEP_NAME = "testLinkUploadTestResults"; + + public DescriptorImpl(){ + super(TestLinkUploadTestResultsExecution.class); + + } + + @Override + public String getFunctionName(){ + return STEP_NAME; + } + + @Override + public String getDisplayName(){ + return STEP_NAME; + } + } +} diff --git a/src/main/java/hudson/plugins/testlink/result/AbstractJUnitResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/AbstractJUnitResultSeeker.java index 7673276..0238219 100644 --- a/src/main/java/hudson/plugins/testlink/result/AbstractJUnitResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/AbstractJUnitResultSeeker.java @@ -26,16 +26,15 @@ import java.io.File; import java.io.IOException; +import hudson.FilePath; +import hudson.model.*; + import jenkins.MasterToSlaveFileCallable; import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus; import br.eti.kinoshita.testlinkjavaapi.model.Attachment; import br.eti.kinoshita.testlinkjavaapi.util.TestLinkAPIException; -import hudson.model.AbstractBuild; -import hudson.model.BuildListener; -import hudson.model.Result; import hudson.plugins.testlink.TestLinkSite; -import hudson.plugins.testlink.util.Messages; import hudson.remoting.VirtualChannel; import hudson.tasks.junit.SuiteResult; @@ -75,14 +74,13 @@ public boolean isAttachJUnitXML() { return attachJUnitXML; } - protected void handleResult(TestCaseWrapper automatedTestCase, AbstractBuild build, BuildListener listener, TestLinkSite testlink, final SuiteResult suiteResult) { + protected void handleResult(TestCaseWrapper automatedTestCase, Run build, FilePath workspace, TaskListener listener, TestLinkSite testlink, final SuiteResult suiteResult) { if(automatedTestCase.getExecutionStatus(this.keyCustomField) != ExecutionStatus.NOT_RUN) { try { - listener.getLogger().println( Messages.TestLinkBuilder_Update_AutomatedTestCases() ); final int executionId = testlink.updateTestCase(automatedTestCase); if(executionId > 0 && this.isAttachJUnitXML()) { - Attachment attachment = build.getWorkspace().act( new MasterToSlaveFileCallable() { + Attachment attachment = workspace.act( new MasterToSlaveFileCallable() { private static final long serialVersionUID = -5411683541842375558L; diff --git a/src/main/java/hudson/plugins/testlink/result/AbstractTAPFileNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/AbstractTAPFileNameResultSeeker.java index c0a67dd..55937e0 100644 --- a/src/main/java/hudson/plugins/testlink/result/AbstractTAPFileNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/AbstractTAPFileNameResultSeeker.java @@ -11,7 +11,10 @@ import java.util.Map.Entry; import java.util.Set; +import hudson.model.*; + import jenkins.MasterToSlaveFileCallable; + import org.tap4j.consumer.TapConsumer; import org.tap4j.consumer.TapConsumerFactory; import org.tap4j.model.Directive; @@ -25,10 +28,8 @@ import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus; import br.eti.kinoshita.testlinkjavaapi.model.Attachment; import br.eti.kinoshita.testlinkjavaapi.util.TestLinkAPIException; +import hudson.FilePath; import hudson.Launcher; -import hudson.model.AbstractBuild; -import hudson.model.BuildListener; -import hudson.model.Result; import hudson.plugins.testlink.TestLinkSite; import hudson.remoting.VirtualChannel; @@ -100,12 +101,12 @@ public void setCompareFullPath(Boolean compareFullPath) { * hudson.plugins.testlink.result.Report) */ @Override - public void seek(final TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, - final BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(final TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, + final TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { try { - final Map testSets = build.getWorkspace().act( - new MasterToSlaveFileCallable>() { + final Map testSets = workspace.act( + new MasterToSlaveFileCallable>() { private static final long serialVersionUID = 1L; private Map testSets; @@ -146,7 +147,7 @@ public Map invoke(File workspace, VirtualChannel channel) throw tapFileNameWithoutExtension.lastIndexOf('.')); } if (tapFileNameWithoutExtension.equals(value)) { - this.updateTestCase(testSets, key, automatedTestCase, value, build, listener, testlink); + this.updateTestCase(testSets, key, automatedTestCase, value, build, workspace, listener, testlink); } } } @@ -159,7 +160,7 @@ public Map invoke(File workspace, VirtualChannel channel) throw } protected void updateTestCase(Map testSets, String key, TestCaseWrapper automatedTestCase, - String value, AbstractBuild build, BuildListener listener, TestLinkSite testlink) { + String value, Run build, FilePath workspace, TaskListener listener, TestLinkSite testlink) { final ExecutionStatus status = this.getExecutionStatus(testSets.get(key)); automatedTestCase.addCustomFieldAndStatus(value, status); @@ -168,11 +169,11 @@ protected void updateTestCase(Map testSets, String key, TestCas automatedTestCase.appendNotes(notes); } - this.handleResult(automatedTestCase, build, listener, testlink, status, testSets, key); + this.handleResult(automatedTestCase, build, workspace, listener, testlink, status, testSets, key); } - protected void handleResult(TestCaseWrapper automatedTestCase, final AbstractBuild build, - BuildListener listener, TestLinkSite testlink, ExecutionStatus status, final Map testSets, + protected void handleResult(TestCaseWrapper automatedTestCase, final Run build, FilePath workspace, + TaskListener listener, TestLinkSite testlink, ExecutionStatus status, final Map testSets, final String key) { if (automatedTestCase.getExecutionStatus(this.keyCustomField) != ExecutionStatus.NOT_RUN) { String platform = this.retrievePlatform(testSets.get(key)); @@ -182,8 +183,8 @@ protected void handleResult(TestCaseWrapper automatedTestCase, final AbstractBui final int executionId = testlink.updateTestCase(automatedTestCase); if (executionId > 0 && this.isAttachTAPStream()) { - final String remoteWs = build.getWorkspace().getRemote(); - List attachments = build.getWorkspace().act(new MasterToSlaveFileCallable>() { + final String remoteWs = workspace.getRemote(); + List attachments = workspace.act(new MasterToSlaveFileCallable>() { private static final long serialVersionUID = -5411683541842375558L; diff --git a/src/main/java/hudson/plugins/testlink/result/AbstractTestNGResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/AbstractTestNGResultSeeker.java index acef732..a23995c 100644 --- a/src/main/java/hudson/plugins/testlink/result/AbstractTestNGResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/AbstractTestNGResultSeeker.java @@ -23,9 +23,10 @@ */ package hudson.plugins.testlink.result; -import hudson.model.BuildListener; import hudson.model.Result; -import hudson.model.AbstractBuild; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.FilePath; import hudson.plugins.testlink.TestLinkSite; import hudson.remoting.VirtualChannel; @@ -93,13 +94,13 @@ public boolean isMarkSkippedTestAsBlocked() { return markSkippedTestAsBlocked; } - protected void handleResult(TestCaseWrapper automatedTestCase, AbstractBuild build, BuildListener listener, TestLinkSite testlink, ExecutionStatus status, final Suite suiteResult) { + protected void handleResult(TestCaseWrapper automatedTestCase, Run build, FilePath workspace, TaskListener listener, TestLinkSite testlink, ExecutionStatus status, final Suite suiteResult) { if(automatedTestCase.getExecutionStatus(this.keyCustomField) != ExecutionStatus.NOT_RUN) { try { final int executionId = testlink.updateTestCase(automatedTestCase); if(executionId > 0 && this.isAttachTestNGXML()) { - Attachment attachment = build.getWorkspace().act( new MasterToSlaveFileCallable() { + Attachment attachment = workspace.act( new MasterToSlaveFileCallable() { private static final long serialVersionUID = -5411683541842375558L; diff --git a/src/main/java/hudson/plugins/testlink/result/JUnitCaseClassNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/JUnitCaseClassNameResultSeeker.java index 5a9d2a7..98415e6 100644 --- a/src/main/java/hudson/plugins/testlink/result/JUnitCaseClassNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/JUnitCaseClassNameResultSeeker.java @@ -24,12 +24,13 @@ package hudson.plugins.testlink.result; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.AbstractBuild; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.plugins.testlink.TestLinkJunitWrapper; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; -import hudson.tasks.junit.JUnitParser; import hudson.tasks.junit.SuiteResult; import hudson.tasks.junit.TestResult; import hudson.tasks.junit.CaseResult; @@ -87,12 +88,13 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_JUnit_LookingForTestClasses() ); // i18n try { - final JUnitParser parser = new JUnitParser(false); - final TestResult testResult = parser.parse(this.includePattern, build, launcher, listener); - + final TestLinkJunitWrapper parser = new TestLinkJunitWrapper(false, false); + final TestResult testResult = parser.parseResult(this.includePattern, build, workspace, launcher, listener); + final Map> customfields = parser.getCustomFields(); + for(final SuiteResult suiteResult : testResult.getSuites()) { final List caseResults = this.filter(suiteResult.getCases()); @@ -109,7 +111,11 @@ public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build //final ExecutionStatus previousStatus = automatedTestCase.getCustomFieldAndStatus().get(value); final ExecutionStatus status = this.getExecutionStatus(caseResult); automatedTestCase.addCustomFieldAndStatus(value, status); - + Map cfs = customfields.get(caseResult.getClassName()); + if (cfs != null && cfs.size() > 0){ + automatedTestCase.setCustomFieldExecutionValue(cfs); + } + if(this.isIncludeNotes()) { final String notes = this.getJUnitNotes(caseResult, build.number); automatedTestCase.appendNotes(notes); @@ -122,7 +128,7 @@ public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build // Here we update testlink with our findings for(Map.Entry entry : classNameTestCase.entrySet()) { - super.handleResult(entry.getValue(), build, listener, testlink, suiteResult); + super.handleResult(entry.getValue(), build, workspace, listener, testlink, suiteResult); } } @@ -221,3 +227,4 @@ private String getJUnitNotes( CaseResult testCase , int buildNumber) } } + diff --git a/src/main/java/hudson/plugins/testlink/result/JUnitCaseNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/JUnitCaseNameResultSeeker.java index c00abd1..b3a13d0 100644 --- a/src/main/java/hudson/plugins/testlink/result/JUnitCaseNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/JUnitCaseNameResultSeeker.java @@ -24,9 +24,10 @@ package hudson.plugins.testlink.result; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.AbstractBuild; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.tasks.junit.JUnitParser; @@ -81,11 +82,11 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_JUnit_LookingForTestCases() ); // i18n try { final JUnitParser parser = new JUnitParser(false); - final TestResult testResult = parser.parse(this.includePattern, build, launcher, listener); + final TestResult testResult = parser.parseResult(this.includePattern, build, workspace, launcher, listener); for(SuiteResult suiteResult : testResult.getSuites()) { for(CaseResult caseResult : suiteResult.getCases()) { @@ -100,7 +101,7 @@ public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build final String notes = this.getJUnitNotes(caseResult, build.number); automatedTestCase.appendNotes(notes); } - super.handleResult(automatedTestCase, build, listener, testlink, suiteResult); + super.handleResult(automatedTestCase, build, workspace, listener, testlink, suiteResult); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/JUnitMethodNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/JUnitMethodNameResultSeeker.java index 7add363..2cd9e39 100644 --- a/src/main/java/hudson/plugins/testlink/result/JUnitMethodNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/JUnitMethodNameResultSeeker.java @@ -24,9 +24,10 @@ package hudson.plugins.testlink.result; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.AbstractBuild; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.tasks.junit.JUnitParser; @@ -82,11 +83,11 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_JUnit_LookingForTestMethods() ); // i18n try { final JUnitParser parser = new JUnitParser(false); - final TestResult testResult = parser.parse(this.includePattern, build, launcher, listener); + final TestResult testResult = parser.parseResult(this.includePattern, build, workspace, launcher, listener); for(final SuiteResult suiteResult : testResult.getSuites()) { for(CaseResult caseResult : suiteResult.getCases()) { @@ -102,7 +103,7 @@ public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build final String notes = this.getJUnitNotes(caseResult, build.number); automatedTestCase.appendNotes(notes); } - super.handleResult(automatedTestCase, build, listener, testlink, suiteResult); + super.handleResult(automatedTestCase, build, workspace, listener, testlink, suiteResult); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/JUnitSuiteNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/JUnitSuiteNameResultSeeker.java index 9937f72..c1a5fc7 100644 --- a/src/main/java/hudson/plugins/testlink/result/JUnitSuiteNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/JUnitSuiteNameResultSeeker.java @@ -24,9 +24,10 @@ package hudson.plugins.testlink.result; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.AbstractBuild; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.tasks.junit.JUnitParser; @@ -85,11 +86,11 @@ public String getDisplayName() { * hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases,AbstractBuild build, Launcher launcher, BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_JUnit_LookingForTestSuites() ); try { final JUnitParser parser = new JUnitParser(false); - final TestResult testResult = parser.parse(this.includePattern, build, launcher, listener); + final TestResult testResult = parser.parseResult(this.includePattern, build, workspace, launcher, listener); for(SuiteResult suiteResult : testResult.getSuites()) { for(TestCaseWrapper automatedTestCase : automatedTestCases) { @@ -104,7 +105,7 @@ public void seek(TestCaseWrapper[] automatedTestCases,AbstractBuild build, automatedTestCase.appendNotes(notes); } - super.handleResult(automatedTestCase, build, listener, testlink, suiteResult); + super.handleResult(automatedTestCase, build, workspace, listener, testlink, suiteResult); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/ResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/ResultSeeker.java index b1105a7..9668c40 100644 --- a/src/main/java/hudson/plugins/testlink/result/ResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/ResultSeeker.java @@ -24,14 +24,10 @@ package hudson.plugins.testlink.result; import hudson.DescriptorExtensionList; +import hudson.FilePath; import hudson.Launcher; import hudson.Util; -import hudson.model.BuildListener; -import hudson.model.Describable; -import hudson.model.AbstractBuild; -import hudson.model.Descriptor; -import hudson.model.Hudson; -import hudson.model.Node; +import hudson.model.*; import hudson.plugins.testlink.TestLinkSite; import java.io.File; @@ -143,7 +139,7 @@ public static DescriptorExtensionList> al * @param testlink TestLink site for updating test status * @throws ResultSeekerException */ - public abstract void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, BuildListener listener, TestLinkSite testlink) throws ResultSeekerException; + public abstract void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, TaskListener listener, TestLinkSite testlink) throws ResultSeekerException; /** * Retrieves the file content encoded in Base64. @@ -171,7 +167,7 @@ protected String getBase64FileContent(File file) throws IOException { * pattern in the directory. * @throws IOException */ - protected String[] scan(final File directory, final String includes, final BuildListener listener) throws IOException { + protected String[] scan(final File directory, final String includes, final TaskListener listener) throws IOException { String[] fileNames = new String[0]; if (StringUtils.isNotBlank(includes)) { diff --git a/src/main/java/hudson/plugins/testlink/result/TAPFileNameMultiTestPointsResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/TAPFileNameMultiTestPointsResultSeeker.java index 71eb42e..198b984 100644 --- a/src/main/java/hudson/plugins/testlink/result/TAPFileNameMultiTestPointsResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/TAPFileNameMultiTestPointsResultSeeker.java @@ -24,8 +24,9 @@ package hudson.plugins.testlink.result; import hudson.Extension; -import hudson.model.BuildListener; -import hudson.model.AbstractBuild; +import hudson.FilePath; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import java.util.Map; @@ -73,7 +74,7 @@ public String getDisplayName() { @Override protected void updateTestCase(Map testSets, String key, TestCaseWrapper automatedTestCase, - String value, AbstractBuild build, BuildListener listener, TestLinkSite testlink) { + String value, Run build, FilePath workspace, TaskListener listener, TestLinkSite testlink) { final TestSet testSet = testSets.get(key); int executionNumbers = testSet.getNumberOfTestResults(); for (Integer i = 1; i <= executionNumbers; i++) { @@ -93,7 +94,7 @@ protected void updateTestCase(Map testSets, String key, TestCas automatedTestCase.appendNotes(notes); } - this.handleResult(automatedTestCase, build, listener, testlink, status, testSets, key); + this.handleResult(automatedTestCase, build, workspace, listener, testlink, status, testSets, key); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/TAPFileNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/TAPFileNameResultSeeker.java index 89a8065..d9b1d65 100644 --- a/src/main/java/hudson/plugins/testlink/result/TAPFileNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/TAPFileNameResultSeeker.java @@ -24,9 +24,10 @@ package hudson.plugins.testlink.result; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.AbstractBuild; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import org.kohsuke.stapler.DataBoundConstructor; @@ -63,7 +64,7 @@ public String getDisplayName() { } @Override - public void seek(final TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, final BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { - super.seek(automatedTestCases, build, launcher, listener, testlink); + public void seek(final TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, final TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { + super.seek(automatedTestCases, build, workspace, launcher, listener, testlink); } } \ No newline at end of file diff --git a/src/main/java/hudson/plugins/testlink/result/TestCaseWrapper.java b/src/main/java/hudson/plugins/testlink/result/TestCaseWrapper.java index c9611a5..76f7b47 100644 --- a/src/main/java/hudson/plugins/testlink/result/TestCaseWrapper.java +++ b/src/main/java/hudson/plugins/testlink/result/TestCaseWrapper.java @@ -74,6 +74,11 @@ public class TestCaseWrapper implements Serializable { */ private TestCase testCase; + /** + * Custom Field execution values + */ + private Map customFieldsExecutionValues = null; + public TestCaseWrapper() { this(new TestCase()); } @@ -147,6 +152,7 @@ public ExecutionStatus getExecutionStatus() { /** * Calculates the new value of this wrapped test case execution status, * given a number of custom fields. + * @param keyCustomFieldName * @return new value of this wrapped test case execution status */ public ExecutionStatus getExecutionStatus(String keyCustomFieldName) { @@ -307,4 +313,7 @@ public void setFullExternalId(String fullExternalId) { this.testCase.setFullExternalId(fullExternalId); } + public void setCustomFieldExecutionValue(Map cfs) {this.customFieldsExecutionValues = cfs;} + + public Map getCustomFieldsExecutionValues(){return this.customFieldsExecutionValues;} } diff --git a/src/main/java/hudson/plugins/testlink/result/TestNGClassNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/TestNGClassNameResultSeeker.java index 8769760..2700066 100644 --- a/src/main/java/hudson/plugins/testlink/result/TestNGClassNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/TestNGClassNameResultSeeker.java @@ -45,6 +45,8 @@ import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.remoting.VirtualChannel; @@ -90,10 +92,10 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, final BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, final TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_TestNG_LookingForTestSuites() ); try { - final List suites = build.getWorkspace().act(new MasterToSlaveFileCallable>() { + final List suites = workspace.act(new MasterToSlaveFileCallable>() { private static final long serialVersionUID = 1L; private List suites = new ArrayList(); @@ -130,7 +132,7 @@ public List invoke(File workspace, VirtualChannel channel) automatedTestCase.appendNotes(notes); } - super.handleResult(automatedTestCase, build, listener, testlink, status, suite); + super.handleResult(automatedTestCase, build, workspace, listener, testlink, status, suite); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameDataProviderNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameDataProviderNameResultSeeker.java index c2b3548..345a804 100644 --- a/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameDataProviderNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameDataProviderNameResultSeeker.java @@ -38,9 +38,12 @@ import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.remoting.VirtualChannel; @@ -103,10 +106,10 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, final BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, final TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_TestNG_LookingForTestMethodDataProvider() ); try { - final List suites = build.getWorkspace().act(new MasterToSlaveFileCallable>() { + final List suites = workspace.act(new MasterToSlaveFileCallable>() { private static final long serialVersionUID = 1L; private List suites = new ArrayList(); @@ -147,7 +150,7 @@ public List invoke(File workspace, VirtualChannel channel) automatedTestCase.appendNotes(notes); } - this.handleResult(automatedTestCase, build, listener, testlink, status, suite); + this.handleResult(automatedTestCase, build, workspace, listener, testlink, status, suite); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameResultSeeker.java index 25b0bad..ab677d6 100644 --- a/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/TestNGMethodNameResultSeeker.java @@ -38,9 +38,12 @@ import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.remoting.VirtualChannel; @@ -86,10 +89,10 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, final BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, final TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_TestNG_LookingForTestMethod() ); try { - final List suites = build.getWorkspace().act(new MasterToSlaveFileCallable>() { + final List suites = workspace.act(new MasterToSlaveFileCallable>() { private static final long serialVersionUID = 1L; private List suites = new ArrayList(); @@ -128,7 +131,7 @@ public List invoke(File workspace, VirtualChannel channel) automatedTestCase.appendNotes(notes); } - super.handleResult(automatedTestCase, build, listener, testlink, status, suite); + super.handleResult(automatedTestCase, build, workspace, listener, testlink, status, suite); } } } diff --git a/src/main/java/hudson/plugins/testlink/result/TestNGSuiteNameResultSeeker.java b/src/main/java/hudson/plugins/testlink/result/TestNGSuiteNameResultSeeker.java index a063007..a678acb 100644 --- a/src/main/java/hudson/plugins/testlink/result/TestNGSuiteNameResultSeeker.java +++ b/src/main/java/hudson/plugins/testlink/result/TestNGSuiteNameResultSeeker.java @@ -37,9 +37,12 @@ import br.eti.kinoshita.testlinkjavaapi.constants.ExecutionStatus; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.plugins.testlink.TestLinkSite; import hudson.plugins.testlink.util.Messages; import hudson.remoting.VirtualChannel; @@ -85,10 +88,10 @@ public String getDisplayName() { * @see hudson.plugins.testlink.result.ResultSeeker#seekAndUpdate(hudson.plugins.testlink.result.TestCaseWrapper[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, hudson.plugins.testlink.TestLinkSite, hudson.plugins.testlink.result.Report) */ @Override - public void seek(TestCaseWrapper[] automatedTestCases, AbstractBuild build, Launcher launcher, final BuildListener listener, TestLinkSite testlink) throws ResultSeekerException { + public void seek(TestCaseWrapper[] automatedTestCases, Run build, FilePath workspace, Launcher launcher, final TaskListener listener, TestLinkSite testlink) throws ResultSeekerException { listener.getLogger().println( Messages.Results_TestNG_LookingForTestSuites() ); try { - final List suites = build.getWorkspace().act(new MasterToSlaveFileCallable>() { + final List suites = workspace.act(new MasterToSlaveFileCallable>() { private static final long serialVersionUID = 1L; private List suites = new ArrayList(); @@ -123,7 +126,7 @@ public List invoke(File workspace, VirtualChannel channel) automatedTestCase.appendNotes(notes); } - super.handleResult(automatedTestCase, build, listener, testlink, status, suite); + super.handleResult(automatedTestCase, build, workspace, listener, testlink, status, suite); } } } diff --git a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.jelly b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.jelly index f280bec..f5be4e6 100644 --- a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.jelly +++ b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.jelly @@ -25,7 +25,11 @@ - + + + + + diff --git a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.properties b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.properties index d5b9d21..ad2209c 100644 --- a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.properties +++ b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config.properties @@ -3,6 +3,7 @@ Test\ Project\ Name=Test Project Name Test\ Plan\ Name=Test Plan Name Platform\ Name=Platform Name Build\ Name=Build Name +Build\ Custom\ Fields\ Values=Build Custom Fields Values Custom\ Fields=Custom Fields Test\ Plan\ Custom\ Fields=Test Plan Custom Fields Key\ Custom\ Field=Key Custom Field diff --git a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_es.properties b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_es.properties index bf41081..5dee8d9 100644 --- a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_es.properties +++ b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_es.properties @@ -3,6 +3,7 @@ Test\ Project\ Name=Nombre del Proyecto de Pruebas Test\ Plan\ Name=Nombre del Plan de Pruebas Platform\ Name=Nombre de la Plataforma Build\ Name=Nombre del Build +Build\ Custom\ Fields\ Values=Construir valores de campos personalizados Custom\ Fields=Campos personalizados Key\ Custom\ Field=Campo customizado chave para testes automatizados do TestLink Execution\ Status=Execution Status diff --git a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_pt.properties b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_pt.properties index 3db0262..1725fc9 100644 --- a/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_pt.properties +++ b/src/main/resources/hudson/plugins/testlink/TestLinkBuilder/config_pt.properties @@ -3,6 +3,7 @@ Test\ Project\ Name=Nome do Projeto de Testes Test\ Plan\ Name=Nome do Plano de Testes Platform\ Name=Nome da Plataforma Build\ Name=Nome do Build +Build\ Custom\ Fields\ Values=Construir valores personalizados Campos Custom\ Fields=Campos customizados Key\ Custom\ Field=Campo customizado chave para testes automatizados do TestLink Single\ Test\ Build\ Steps=Build Steps únicos diff --git a/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkCreateBuildStep/config.jelly b/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkCreateBuildStep/config.jelly new file mode 100644 index 0000000..03c409a --- /dev/null +++ b/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkCreateBuildStep/config.jelly @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanStep/config.jelly b/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanStep/config.jelly new file mode 100644 index 0000000..d3fff3c --- /dev/null +++ b/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkDownloadTestPlanStep/config.jelly @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsStep/config.jelly b/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsStep/config.jelly new file mode 100644 index 0000000..53c7d54 --- /dev/null +++ b/src/main/resources/hudson/plugins/testlink/pipeline/TestLinkUploadTestResultsStep/config.jelly @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/help-buildCustomFields.html b/src/main/webapp/help-buildCustomFields.html new file mode 100644 index 0000000..406e4ba --- /dev/null +++ b/src/main/webapp/help-buildCustomFields.html @@ -0,0 +1,11 @@ +
+

+ Give a list of custom fields values for build. +

+

+ Example: compiler:gcc, build_os:Windows +

+

You can use environment variables in this field. For example: + build_$BUILD_ID will be converted to something like + build_YYYY-MM-DD_HH-MI-SS.

+
\ No newline at end of file diff --git a/src/test/java/hudson/plugins/testlink/TestTestLinkBuilder.java b/src/test/java/hudson/plugins/testlink/TestTestLinkBuilder.java index 054c873..82f6baa 100644 --- a/src/test/java/hudson/plugins/testlink/TestTestLinkBuilder.java +++ b/src/test/java/hudson/plugins/testlink/TestTestLinkBuilder.java @@ -60,7 +60,7 @@ public class TestTestLinkBuilder { @Before public void setUp() throws Exception { - builder = new TestLinkBuilder("No testlink", "No project", "No plan", "No platform", "No build", + builder = new TestLinkBuilder("No testlink", "No project", "No plan", "No platform", "No build", "Not build custom field", "class, time, sample-job-$BUILD_ID", "host, user",Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, null, null, null, null, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, null); } @@ -89,7 +89,7 @@ public void testListOfCustomFields() { @Test public void testNull() { builder = new TestLinkBuilder(null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null); assertNotNull(builder); @@ -103,6 +103,8 @@ public void testNull() { assertNull(builder.getBuildName()); + assertNull(builder.getBuildCustomFields()); + assertNull(builder.getSingleBuildSteps()); assertNull(builder.getBeforeIteratingAllTestCasesBuildSteps()); @@ -133,7 +135,7 @@ public void testGetters() { List singleBuildSteps = new ArrayList(); singleBuildSteps.add(shell); - builder = new TestLinkBuilder("No testlink", "No project", "No plan", "No platform", "No build", "class, time", + builder = new TestLinkBuilder("No testlink", "No project", "No plan", "No platform", "No build", "No build custom fields", "class, time", "host, user", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, singleBuildSteps, null, null, null, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, null); @@ -157,6 +159,9 @@ public void testGetters() { assertNotNull(builder.getBuildName()); assertEquals(builder.getBuildName(), "No build"); + assertNotNull(builder.getBuildCustomFields()); + assertEquals(builder.getBuildCustomFields(), "No build custom fields"); + assertNotNull(builder.getSingleBuildSteps()); assertEquals(builder.getSingleBuildSteps(), singleBuildSteps); assertEquals(builder.getSingleBuildSteps().size(), 1); diff --git a/src/test/java/hudson/plugins/testlink/TestTestLinkSite.java b/src/test/java/hudson/plugins/testlink/TestTestLinkSite.java index 47c9575..19b0689 100644 --- a/src/test/java/hudson/plugins/testlink/TestTestLinkSite.java +++ b/src/test/java/hudson/plugins/testlink/TestTestLinkSite.java @@ -16,6 +16,7 @@ import static org.mockito.Mockito.when; import hudson.plugins.testlink.result.TestCaseWrapper; +import org.hamcrest.core.StringContains; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -33,6 +34,8 @@ import br.eti.kinoshita.testlinkjavaapi.model.TestPlan; import br.eti.kinoshita.testlinkjavaapi.model.TestProject; +import java.util.HashMap; + @RunWith(MockitoJUnitRunner.class) public class TestTestLinkSite { @@ -86,7 +89,7 @@ public void testUpdateTestCaseWithPassedStatus() { verify(api) .reportTCResult(3, 4, 2, status, null, 1, "build-name", "notes", null, null, null, "platform", - null, null); + new HashMap(), null); Report report = testLinkSite.getReport(); assertThat(report.getPassed(), is(1)); assertThat(report.getFailed(), is(0)); @@ -106,7 +109,7 @@ public void testUpdateTestCaseWithFailedStatus() { verify(api) .reportTCResult(3, 4, 2, status, null, 1, "build-name", "notes", null, null, null, "platform", - null, null); + new HashMap(), null); Report report = testLinkSite.getReport(); assertThat(report.getPassed(), is(0)); assertThat(report.getFailed(), is(1)); @@ -126,7 +129,7 @@ public void testUpdateTestCaseWithBlockedStatus() { verify(api) .reportTCResult(3, 4, 2, status, null, 1, "build-name", "notes", null, null, null, "platform", - null, null); + new HashMap(), null); Report report = testLinkSite.getReport(); assertThat(report.getPassed(), is(0)); assertThat(report.getFailed(), is(0)); diff --git a/src/test/java/hudson/plugins/testlink/result/ResultSeekerTestCase.java b/src/test/java/hudson/plugins/testlink/result/ResultSeekerTestCase.java index d2a6457..ab88048 100644 --- a/src/test/java/hudson/plugins/testlink/result/ResultSeekerTestCase.java +++ b/src/test/java/hudson/plugins/testlink/result/ResultSeekerTestCase.java @@ -138,7 +138,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, traverseDirectory(f); } - seeker.seek(tcs, build, launcher, listener, testlink); + seeker.seek(tcs, build, build.getWorkspace(), launcher, listener, testlink); return (seeker != null); } private static void traverseDirectory(FilePath f) throws InterruptedException, IOException {