Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plan and build custom fields support #20

Merged
merged 7 commits into from
Apr 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

<inceptionYear>2010</inceptionYear>

<artifactId>testlink</artifactId>
<name>Jenkins TestLink Plugin</name>
<version>3.12-SNAPSHOT</version>
<packaging>hpi</packaging>
<description>This plug-in integrates Jenkins to TestLink</description>
<artifactId>testlink</artifactId>
<name>Jenkins TestLink Plugin</name>
<version>3.13-SNAPSHOT</version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version value is changed by maven-release-plugin. When I run mvn clean release:prepare it runs the tests, does some other checks like git status and also asks for the next release version. Will fix it after merging.

<packaging>hpi</packaging>
<description>This plug-in integrates Jenkins to TestLink</description>

<url>http://wiki.jenkins-ci.org/display/JENKINS/TestLink+Plugin</url>

Expand Down Expand Up @@ -271,7 +271,7 @@
<dependency>
<groupId>br.eti.kinoshita</groupId>
<artifactId>testlink-java-api</artifactId>
<version>1.9.14-0-SNAPSHOT</version>
<version>1.9.14-0</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
Expand Down
38 changes: 35 additions & 3 deletions src/main/java/hudson/plugins/testlink/AbstractTestLinkBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public class AbstractTestLinkBuilder extends Builder {
*/
protected final String customFields;

/**
* Comma separated list of custom fields to download from TestLink.
*/
protected final String testPlanCustomFields;

/**
* List of build steps that are executed only once per job execution.
*/
Expand Down Expand Up @@ -138,7 +143,7 @@ public class AbstractTestLinkBuilder extends Builder {
* Create a AbstractTestLinkBuilder.
*/
public AbstractTestLinkBuilder(String testLinkName, String testProjectName, String testPlanName,
String platformName, String buildName, String customFields, List<BuildStep> singleBuildSteps,
String platformName, String buildName, String customFields, String testPlanCustomFields, List<BuildStep> singleBuildSteps,
List<BuildStep> beforeIteratingAllTestCasesBuildSteps, List<BuildStep> iterativeBuildSteps,
List<BuildStep> afterIteratingAllTestCasesBuildSteps, Boolean transactional,
Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults, Boolean failOnNotRun,
Expand All @@ -150,6 +155,7 @@ public AbstractTestLinkBuilder(String testLinkName, String testProjectName, Stri
this.platformName = platformName;
this.buildName = buildName;
this.customFields = customFields;
this.testPlanCustomFields = testPlanCustomFields;
this.singleBuildSteps = singleBuildSteps;
this.beforeIteratingAllTestCasesBuildSteps = beforeIteratingAllTestCasesBuildSteps;
this.iterativeBuildSteps = iterativeBuildSteps;
Expand Down Expand Up @@ -182,13 +188,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 customFields, String testPlanCustomFields, Boolean executionStatusNotRun,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deprecated constructor can be left as is, and just pass null/empty values to the current constructor.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I come from the C# world, all those deprecated tons of code and almost empty methods and constructors look really frustrating to me (since java does not have default param value in method declaration)
I thought that we can just replace it and if something brakes we have git history and smart IDEs to handle that,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not specifically for Java. But XStream, the library used to serialise XML in Jenkins, may try to load an XML or call the old constructor.

So we keep it for a while, just until users update their jobs.

A major release like 4.0 is a good opportunity to remove this deprecated constructor, giving notice with enough time to users too.

Boolean executionStatusPassed, Boolean executionStatusFailed, Boolean executionStatusBlocked,
List<BuildStep> singleBuildSteps, List<BuildStep> beforeIteratingAllTestCasesBuildSteps,
List<BuildStep> iterativeBuildSteps, List<BuildStep> afterIteratingAllTestCasesBuildSteps,
Boolean transactional, Boolean failedTestsMarkBuildAsFailure, Boolean failIfNoResults,
Boolean failOnNotRun, List<ResultSeeker> resultSeekers) {
this(testLinkName, testProjectName, testPlanName, platformName, buildName, customFields, singleBuildSteps,
this(testLinkName, testProjectName, testPlanName, platformName, buildName, customFields, testPlanCustomFields, singleBuildSteps,
beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps, afterIteratingAllTestCasesBuildSteps,
transactional, failedTestsMarkBuildAsFailure, failIfNoResults, failOnNotRun, resultSeekers);
}
Expand Down Expand Up @@ -230,6 +236,10 @@ public String getCustomFields() {
return this.customFields;
}

public String getTestPlanCustomFields(){
return this.testPlanCustomFields;
}

/**
* @deprecated
*/
Expand Down Expand Up @@ -361,4 +371,26 @@ protected String[] createArrayOfCustomFieldsNames(final VariableResolver<String>
return customFieldNamesArray;
}


protected String[] createArrayOfTestPlanCustomFieldsNames(final VariableResolver<String> variableResolver,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will try to merge createArrayOfTestPlanCustomFieldsNames and createArrayOfCustomFieldsNames methods.

You could have done that, but that would make this pull request harder to merge. By simply copying and pasting, you made it easier for me to review your code, and also to spot parts of the code that were not suitable for extensibility.

Kudos and thanks! 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you reading my mind?
I was going to make it later after the functionality merge!
You are so thoughtful

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, and again, thanks for not doing that in this commit. It made it waaaay easier to review the code 😁

final EnvVars envVars){
String[] customFieldNamesArray = new String[0];
String customFields = expandVariable(variableResolver, envVars, this.getTestPlanCustomFields());

if (StringUtils.isNotBlank(customFields)) {
StringTokenizer tokenizer = new StringTokenizer(customFields, COMMA);
if (tokenizer.countTokens() > 0) {
customFieldNamesArray = new String[tokenizer.countTokens()];
int index = 0;
while (tokenizer.hasMoreTokens()) {
String customFieldName = tokenizer.nextToken();
customFieldName = customFieldName.trim();
customFieldNamesArray[index] = customFieldName;
index = index + 1;
}
}
}

return customFieldNamesArray;
}
}
34 changes: 20 additions & 14 deletions src/main/java/hudson/plugins/testlink/TestLinkBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public class TestLinkBuilder extends AbstractTestLinkBuilder {
* @deprecated
*/
public TestLinkBuilder(String testLinkName, String testProjectName,
String testPlanName, String buildName, String customFields,
String testPlanName, String buildName, String customFields, String testPlanCustomFields,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto deprecated constructor.

Boolean executionStatusNotRun, Boolean executionStatusPassed,
Boolean executionStatusFailed, Boolean executionStatusBlocked,
List<BuildStep> singleBuildSteps,
Expand All @@ -92,7 +92,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName,
Boolean transactional, Boolean failedTestsMarkBuildAsFailure,
Boolean failIfNoResults, List<ResultSeeker> resultSeekers) {
super(testLinkName, testProjectName, testPlanName, buildName,
null, customFields, executionStatusNotRun, executionStatusPassed,
null, customFields, testPlanCustomFields, executionStatusNotRun, executionStatusPassed,
executionStatusFailed, executionStatusBlocked, singleBuildSteps,
beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps,
afterIteratingAllTestCasesBuildSteps, transactional,
Expand All @@ -104,7 +104,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName,
* @deprecated
*/
public TestLinkBuilder(String testLinkName, String testProjectName,
String testPlanName, String buildName, String customFields,
String testPlanName, String buildName, String customFields, String testPlanCustomFields,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

et hic

Boolean executionStatusNotRun, Boolean executionStatusPassed,
Boolean executionStatusFailed, Boolean executionStatusBlocked,
List<BuildStep> singleBuildSteps,
Expand All @@ -114,7 +114,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName,
Boolean transactional, Boolean failedTestsMarkBuildAsFailure,
Boolean failIfNoResults, Boolean failOnNotRun, List<ResultSeeker> resultSeekers) {
super(testLinkName, testProjectName, testPlanName, buildName, null,
customFields, executionStatusNotRun, executionStatusPassed,
customFields, testPlanCustomFields, executionStatusNotRun, executionStatusPassed,
executionStatusFailed, executionStatusBlocked, singleBuildSteps,
beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps,
afterIteratingAllTestCasesBuildSteps, transactional,
Expand All @@ -123,7 +123,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName,

@DataBoundConstructor
public TestLinkBuilder(String testLinkName, String testProjectName,
String testPlanName, String platformName, String buildName, String customFields,
String testPlanName, String platformName, String buildName, String customFields, String testPlanCustomFields,
Boolean executionStatusNotRun, Boolean executionStatusPassed,
Boolean executionStatusFailed, Boolean executionStatusBlocked,
List<BuildStep> singleBuildSteps,
Expand All @@ -133,7 +133,7 @@ public TestLinkBuilder(String testLinkName, String testProjectName,
Boolean transactional, Boolean failedTestsMarkBuildAsFailure,
Boolean failIfNoResults, Boolean failOnNotRun, List<ResultSeeker> resultSeekers) {
super(testLinkName, testProjectName, testPlanName, platformName, buildName,
customFields, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps,
customFields, testPlanCustomFields, singleBuildSteps, beforeIteratingAllTestCasesBuildSteps, iterativeBuildSteps,
afterIteratingAllTestCasesBuildSteps, transactional, failedTestsMarkBuildAsFailure,
failIfNoResults, failOnNotRun, resultSeekers);
}
Expand Down Expand Up @@ -163,6 +163,7 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
final TestCaseWrapper[] automatedTestCases;
final String testLinkUrl = installation.getUrl();
final String testLinkDevKey = installation.getDevKey();
TestPlan testPlan;
listener.getLogger().println(Messages.TestLinkBuilder_UsedTLURL(testLinkUrl));

try {
Expand All @@ -188,9 +189,13 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
if (StringUtils.isNotBlank(platformName) && testLinkSite.getPlatform() == null)
listener.getLogger().println(Messages.TestLinkBuilder_PlatformNotFound(platformName));

final String[] customFieldsNames = this.createArrayOfCustomFieldsNames(build.getBuildVariableResolver(), build.getEnvironment(listener));
final String[] testCaseCustomFieldsNames = this.createArrayOfCustomFieldsNames(build.getBuildVariableResolver(), build.getEnvironment(listener));
// Array of automated test cases
TestCase[] testCases = testLinkSite.getAutomatedTestCases(customFieldsNames);
TestCase[] testCases = testLinkSite.getAutomatedTestCases(testCaseCustomFieldsNames);

final String[] testPlanCustomFieldsNames = this.createArrayOfTestPlanCustomFieldsNames(build.getBuildVariableResolver(), build.getEnvironment(listener));

testPlan = testLinkSite.getTestPlanWithCustomFields(testPlanCustomFieldsNames);

// Transforms test cases into test case wrappers
automatedTestCases = this.transform(testCases);
Expand Down Expand Up @@ -219,10 +224,10 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
}

listener.getLogger().println(Messages.TestLinkBuilder_ExecutingSingleBuildSteps());
this.executeSingleBuildSteps(automatedTestCases.length, testLinkSite, build, launcher, listener);
this.executeSingleBuildSteps(automatedTestCases.length, testPlan, testLinkSite, build, launcher, listener);

listener.getLogger().println(Messages.TestLinkBuilder_ExecutingIterativeBuildSteps());
this.executeIterativeBuildSteps(automatedTestCases, testLinkSite, build, launcher, listener);
this.executeIterativeBuildSteps(automatedTestCases, testPlan, testLinkSite, build, launcher, listener);

// Here we search for test results. The return if a wrapped Test Case
// that
Expand Down Expand Up @@ -308,7 +313,7 @@ public TestLinkSite getTestLinkSite(String testLinkUrl, String testLinkDevKey,

final TestProject testProject = api.getTestProjectByName(testProjectName);
final TestPlan testPlan = api.getTestPlanByName(testPlanName, testProjectName);

Platform platform = null;
if (StringUtils.isNotBlank(platformName)){
final Platform platforms[] = api.getProjectPlatforms(testProject.getId());
Expand All @@ -335,15 +340,15 @@ public TestLinkSite getTestLinkSite(String testLinkUrl, String testLinkDevKey,
* @throws IOException
* @throws InterruptedException
*/
protected void executeSingleBuildSteps(int numberOfTests, TestLinkSite testLinkSite, AbstractBuild<?, ?> build,
protected void executeSingleBuildSteps(int numberOfTests, TestPlan testPlan, TestLinkSite testLinkSite, AbstractBuild<?, ?> build,
Launcher launcher, BuildListener listener) throws IOException,
InterruptedException {
if (singleBuildSteps != null) {
for (BuildStep b : singleBuildSteps) {
final EnvVars iterativeEnvVars = TestLinkHelper.buildTestCaseEnvVars(
numberOfTests,
testLinkSite.getTestProject(),
testLinkSite.getTestPlan(),
testPlan,
testLinkSite.getBuild(),
listener);
build.addAction(new EnvironmentContributingAction() {
Expand Down Expand Up @@ -385,6 +390,7 @@ public String getDisplayName() {
* @throws IOException
*/
protected void executeIterativeBuildSteps(TestCaseWrapper[] automatedTestCases,
TestPlan testPlan,
TestLinkSite testLinkSite, AbstractBuild<?, ?> build,
Launcher launcher, BuildListener listener) throws IOException,
InterruptedException {
Expand All @@ -405,7 +411,7 @@ protected void executeIterativeBuildSteps(TestCaseWrapper[] automatedTestCases,
if (iterativeBuildSteps != null) {
final EnvVars iterativeEnvVars = TestLinkHelper.buildTestCaseEnvVars(automatedTestCase,
testLinkSite.getTestProject(),
testLinkSite.getTestPlan(),
testPlan,
testLinkSite.getBuild(), listener);

build.addAction(new EnvironmentContributingAction() {
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/hudson/plugins/testlink/TestLinkSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,19 @@ public TestCase[] getAutomatedTestCases(String[] customFieldsNames) {

return filteredTestcases.toArray(new TestCase[filteredTestcases.size()]);
}


public TestPlan getTestPlanWithCustomFields(String[] customFieldNames){
TestPlan testPlan = getTestPlan();
for(String customFieldName: customFieldNames){
final CustomField customField = this.api.getTestPlanCustomFieldDesignValue(testPlan.getId(),
getTestProject().getId(),
customFieldName,
ResponseDetails.FULL);
testPlan.getCustomFields().add(customField);
}
return testPlan;
}

/**
* Updates the test cases status in TestLink (note and status) and
* uploads any existing attachments.
Expand Down
47 changes: 44 additions & 3 deletions src/main/java/hudson/plugins/testlink/util/TestLinkHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public final class TestLinkHelper {

// Environment Variables names.
private static final String TESTLINK_TESTCASE_PREFIX = "TESTLINK_TESTCASE_";
private static final String TESTLINK_TESTPLAN_PREFIX = "TESTLINK_TESTPLAN_";
private static final String TESTLINK_BUILD_PREFIX = "TESTLINK_BUILD_";
private static final String TESTLINK_TESTCASE_STEP_PREFIX = "TESTLINK_TESTCASE_STEP_";
private static final String TESTLINK_TESTCASE_ID_ENVVAR = "TESTLINK_TESTCASE_ID";
private static final String TESTLINK_TESTCASE_NAME_ENVVAR = "TESTLINK_TESTCASE_NAME";
Expand Down Expand Up @@ -181,11 +183,17 @@ public static Map<String, String> createTestLinkEnvironmentVariables(TestCaseWra
testLinkEnvVar.put( TESTLINK_TESTPLAN_NAME_ENVVAR, StringUtils.defaultIfEmpty(testPlan.getName(), ""));
testLinkEnvVar.put( TESTLINK_TESTPROJECT_NAME_ENVVAR, StringUtils.defaultIfEmpty(testProject.getName(), ""));

List<CustomField> customFields = testCase.getCustomFields();
for (CustomField customField : customFields) {
List<CustomField> testCaseCustomFields = testCase.getCustomFields();
for (CustomField customField : testCaseCustomFields) {
addCustomFieldEnvironmentVariableName( customField, testLinkEnvVar );
}

List<CustomField> testPlanCustomFields = testPlan.getCustomFields();

for(CustomField customField: testPlanCustomFields){
addTestPlanCustomFieldEnvironmentVariableName(customField, testLinkEnvVar);
}

List<TestCaseStep> steps = testCase.getSteps();
testLinkEnvVar.put(TESTLINK_TESTCASE_STEP_PREFIX + "TOTAL", Integer.toString(steps.size()));
for (TestCaseStep step : steps) {
Expand Down Expand Up @@ -271,7 +279,40 @@ public static void addCustomFieldEnvironmentVariableName(CustomField customField
}
}
}


public static void addTestPlanCustomFieldEnvironmentVariableName(CustomField customField, Map<String, String> testLinkEnvVar){
String customFieldName = customField.getName();
String customFieldValue = customField.getValue();

customFieldName = customFieldName.toUpperCase(); // uppercase
customFieldName = customFieldName.trim(); // trim
customFieldName = TESTLINK_TESTPLAN_PREFIX + customFieldName; // add prefix
customFieldName = customFieldName.replaceAll( "\\s+", "_" ); // replace white spaces

testLinkEnvVar.put(customFieldName, customFieldValue);

if (StringUtils.isNotBlank( customFieldValue )) {
StringTokenizer tokenizer = new StringTokenizer(customFieldValue, ",");
if (tokenizer.countTokens() > 1) {
int index = 0;
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
token = token.trim();

customFieldName = customField.getName();
customFieldName = customFieldName.toUpperCase(); // uppercase
customFieldName = customFieldName.trim(); // trim

String tokenName = TESTLINK_TESTPLAN_PREFIX + customFieldName + "_" + index; // add prefix
tokenName = tokenName.replaceAll( "\\s+", "_" ); // replace white spaces

testLinkEnvVar.put(tokenName, token);
++index;
}
}
}
}

/**
* Creates EnvVars for a TestLink Test Case.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@
<f:entry title="${%Custom Fields}" help="${rootURL}/../plugin/testlink/help-customFields.html">
<f:textbox id="customFields" name="TestLinkBuilder.customFields" value="${instance.customFields}" />
</f:entry>


<f:entry title="${%Test Plan Custom Fields}" help="${rootURL}/../plugin/testlink/help-planCustomFields.html">
<f:textbox id="testPlanCustomFields" name="TestLinkBuilder.testPlanCustomFields" value="${instance.testPlanCustomFields}" />
</f:entry>

<f:advanced>

<f:entry title="${%Platform Name}" help="${rootURL}/../plugin/testlink/help-platformName.html">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Test\ Plan\ Name=Test Plan Name
Platform\ Name=Platform Name
Build\ Name=Build Name
Custom\ Fields=Custom Fields
Test\ Plan\ Custom\ Fields=Test Plan Custom Fields
Key\ Custom\ Field=Key Custom Field
Execution\ Status=Execution Status
Not\ Run=Not Run
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
"class, time, sample-job-$BUILD_ID", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, null,
"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);
}

Expand Down Expand Up @@ -129,7 +129,7 @@ public void testGetters() {
List<BuildStep> singleBuildSteps = new ArrayList<BuildStep>();
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", "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);

Expand Down Expand Up @@ -160,6 +160,9 @@ public void testGetters() {
assertNotNull(builder.getCustomFields());
assertEquals(builder.getCustomFields(), "class, time");

assertNotNull(builder.getTestPlanCustomFields());
assertEquals(builder.getTestPlanCustomFields(), "host, user");

assertFalse(builder.getTransactional());
assertFalse(builder.getFailIfNoResults());
assertFalse(builder.getFailOnNotRun());
Expand Down