Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added health scale factor
  • Loading branch information
slide committed Oct 22, 2017
1 parent fc5a102 commit 129accb
Show file tree
Hide file tree
Showing 11 changed files with 621 additions and 27 deletions.
9 changes: 2 additions & 7 deletions src/main/java/hudson/plugins/nunit/NUnitArchiver.java
Expand Up @@ -41,10 +41,10 @@ public class NUnitArchiver extends MasterToSlaveCallable<Boolean, IOException> {

private int fileCount;

public NUnitArchiver(String root, TaskListener listener, String testResultsPatter, TestReportTransformer unitReportTransformer, boolean failIfNoResults) {
public NUnitArchiver(String root, TaskListener listener, String testResultsPattern, TestReportTransformer unitReportTransformer, boolean failIfNoResults) {
this.root = root;
this.listener = listener;
this.testResultsPattern = testResultsPatter;
this.testResultsPattern = testResultsPattern;
this.unitReportTransformer = unitReportTransformer;
this.failIfNoResults = failIfNoResults;
}
Expand Down Expand Up @@ -104,9 +104,4 @@ private String[] findNUnitReports(File parentPath) {
}
return nunitFiles;
}

@Override
public void checkRoles(RoleChecker roleChecker) throws SecurityException {
roleChecker.check((RoleSensitive) this, Roles.MASTER);
}
}
24 changes: 20 additions & 4 deletions src/main/java/hudson/plugins/nunit/NUnitPublisher.java
Expand Up @@ -58,6 +58,7 @@ public class NUnitPublisher extends Recorder implements Serializable, SimpleBuil
private boolean debug = false;
private boolean keepJUnitReports = false;
private boolean skipJUnitArchiver = false;
private Double healthScaleFactor;

/**
* <p>Flag that when set, <strong>marks the build as failed if there are
Expand Down Expand Up @@ -124,6 +125,14 @@ public void setKeepJUnitReports(boolean keepJUnitReports){
}
}

public double getHealthScaleFactor() {
return healthScaleFactor == null ? 1.0 : healthScaleFactor;
}
@DataBoundSetter
public void setHealthScaleFactor(double healthScaleFactor) {
this.healthScaleFactor = Math.max(0.0, healthScaleFactor);
}

public boolean getSkipJUnitArchiver() {
return skipJUnitArchiver;
}
Expand Down Expand Up @@ -185,18 +194,21 @@ private boolean recordTestResult(String junitFilePattern, Run<?, ?> build, TaskL
action.setResult(result, listener);
}

action.setHealthScaleFactor(getHealthScaleFactor());

if (this.failIfNoResults && result.getPassCount() == 0 && result.getFailCount() == 0 && result.getSkipCount() == 0) {
listener.getLogger().println("None of the test reports contained any result");
build.setResult(Result.FAILURE);
return true;
}

if (existingAction == null) {
build.getActions().add(action);
build.addAction(action);
}

if (action.getResult().getFailCount() > 0)
if (action.getResult().getFailCount() > 0) {
build.setResult(Result.UNSTABLE);
}

return true;
}
Expand Down Expand Up @@ -225,7 +237,7 @@ public TestResult call() throws IOException {
if(files.length==0) {
if (failIfNoResults) {
// no test result. Most likely a configuration error or fatal problem
throw new AbortException("No test report files were found. Configuration error?");
throw new AbortException("No test report files were found or the NUnit input XML file contained no tests.");
} else {
return new TestResult();
}
Expand Down Expand Up @@ -280,8 +292,12 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath ws, @Nonnull Launc
// this should only happen if failIfNoResults is true and there are no result files, see NUnitArchiver.
run.setResult(Result.FAILURE);
}

} catch(AbortException e) {
// this is used internally to signal issues, so we just rethrow instead of letting the IOException
// catch it below.
throw e;
} catch (IOException e) {
listener.getLogger().println("Error in NUnit processing: " + e.getMessage());
throw new AbortException("Could not read the XSL XML file. Please report this issue to the plugin author");
}
}
Expand Down
Expand Up @@ -10,20 +10,21 @@
Basedir of the fileset is &lt;a href='ws/'>the workspace root&lt;/a>.
">
<f:textbox value="${instance.testResultsPattern}" />
<f:advanced>
<f:entry title="Fail the build if no test results are present" field="failIfNoResults">
<f:checkbox value="${instance.failIfNoResults}" checked="${instance.failIfNoResults}" default="true" />
</f:entry>
</f:advanced>
</f:entry>
<f:entry title="${%Fail the build if no test results are present}" field="failIfNoResults">
<f:checkbox value="${instance.failIfNoResults}" checked="${instance.failIfNoResults}" default="true" />
</f:entry>
<f:entry field="healthScaleFactor" title="${%Health report amplification factor}">
<f:number default="1.0" min="0" step="0.1" size="10"/>
</f:entry>
<j:if test="${instance.debug}">
<f:entry title="Debug" field="debug">
<f:entry title="${%Debug}" field="debug">
<f:checkbox checked="${instance.debug}"/>
</f:entry>
<f:entry title="Keep JUnit report files" field="keepJunitReports">
<f:entry title="${%Keep JUnit report files}" field="keepJunitReports">
<f:checkbox checked="${instance.keepJunitReports}"/>
</f:entry>
<f:entry title="Skip JUnit archiving" field="skipJunitArchiver">
<f:entry title="${%Skip JUnit archiving}" field="skipJunitArchiver">
<f:checkbox checked="${instance.skipJunitArchiver}"/>
</f:entry>
</j:if>
Expand Down
@@ -0,0 +1,17 @@
<div>
The amplification factor to apply to test failures when computing the test result contribution to the build health
score.
<br />
The default factor is <code>1.0</code>
<ul>
<li>A factor of <code>0.0</code> will disable the test result contribution to build health score.</li>
<li>A factor of <code>0.1</code> means that 10% of tests failing will score 99% health</li>
<li>A factor of <code>0.5</code> means that 10% of tests failing will score 95% health</li>
<li>A factor of <code>1.0</code> means that 10% of tests failing will score 90% health</li>
<li>A factor of <code>2.0</code> means that 10% of tests failing will score 80% health</li>
<li>A factor of <code>2.5</code> means that 10% of tests failing will score 75% health</li>
<li>A factor of <code>5.0</code> means that 10% of tests failing will score 50% health</li>
<li>A factor of <code>10.0</code> means that 10% of tests failing will score 0% health</li>
</ul>
The factor is persisted with the build results, so changes will only be reflected in new builds.
</div>
@@ -0,0 +1,16 @@
<div>
空模様(ビルドの状態)へのテスト結果の影響を算出する際の失敗したテストに適用する倍率です。
  <br />
デフォルトの倍率は<code>1.0</code>です。
<ul>
<li>倍率 <code>0.0</code> の場合、空模様の算出にテスト結果は使用しません。</li>
<li>倍率 <code>0.1</code> の場合、テストの10%が失敗すると空模様は99%になります。</li>
<li>倍率 <code>0.5</code> の場合、テストの10%が失敗すると空模様は95%になります。</li>
<li>倍率 <code>1.0</code> の場合、テストの10%が失敗すると空模様は90%になります。</li>
<li>倍率 <code>2.0</code> の場合、テストの10%が失敗すると空模様は80%になります。</li>
<li>倍率 <code>2.5</code> の場合、テストの10%が失敗すると空模様は750%になります。</li>
<li>倍率 <code>5.0</code> の場合、テストの10%が失敗すると空模様は50%になります。</li>
<li>倍率 <code>10.0</code> の場合、テストの10%が失敗すると空模様は0%になります。</li>
</ul>
倍率はビルドごとに保存されるので、変更は新規のビルドから反映されます。
</div>
57 changes: 49 additions & 8 deletions src/test/java/hudson/plugins/nunit/NUnitPublisherTest.java
@@ -1,14 +1,9 @@
package hudson.plugins.nunit;

import hudson.Launcher;
import hudson.model.Action;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Project;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Result;
import hudson.model.*;
import hudson.slaves.DumbSlave;
import hudson.tasks.junit.TestResultAction;
import hudson.tasks.test.TestResultProjectAction;

import static org.junit.Assert.*;
Expand Down Expand Up @@ -148,4 +143,50 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
FreeStyleBuild b = prj.scheduleBuild2(0).get();
j.assertBuildStatus(Result.SUCCESS, b);
}

@Test
public void testAgent() throws Exception {
Slave agent = j.createOnlineSlave();
FreeStyleProject prj = j.createFreeStyleProject("foo");
prj.setAssignedNode(agent);

prj.getBuildersList().add(new TestBuilder() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
build.getWorkspace().child("nunit.xml").copyFrom(this.getClass().getResourceAsStream("NUnit-issue44315-3.xml"));
return true;
}
});

NUnitPublisher publisher = new NUnitPublisher("**/*.xml");
publisher.setKeepJUnitReports(true);

prj.getPublishersList().add(publisher);
FreeStyleBuild b = prj.scheduleBuild2(0).get();
j.assertBuildStatus(Result.SUCCESS, b);
}

@Test
public void testHealthScaleFactor() throws Exception {
NUnitPublisher publisher = new NUnitPublisher("**/*.xml");
publisher.setHealthScaleFactor(5.0);
FreeStyleProject prj = j.createFreeStyleProject("foo");
prj.getBuildersList().add(new TestBuilder() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
build.getWorkspace().child("nunit.xml").copyFrom(this.getClass().getResourceAsStream("NUnit-healthReport.xml"));
return true;
}
});

prj.getPublishersList().add(publisher);
FreeStyleBuild b = prj.scheduleBuild2(0).get();
j.assertBuildStatus(Result.UNSTABLE, b);
TestResultAction a = b.getAction(TestResultAction.class);
assertNotNull(a);
assertEquals( 5.0, a.getHealthScaleFactor(), 0.01);
HealthReport r = a.getBuildHealth();
assertNotNull(r);
assertEquals(50, r.getScore());
}
}
13 changes: 13 additions & 0 deletions src/test/java/hudson/plugins/nunit/NUnitReportTransformerTest.java
Expand Up @@ -64,6 +64,19 @@ public void testIssue44315() throws Exception {
assertJunitFiles(195);
}


@Test
public void testIssue44315_2() throws Exception {
transformer.transform(getClass().getResourceAsStream("NUnit-issue44315-2.xml"), tempFilePath);
assertJunitFiles(1);
}

@Test
public void testIssue44315_3() throws Exception {
transformer.transform(getClass().getResourceAsStream("NUnit-issue44315-3.xml"), tempFilePath);
assertJunitFiles(13);
}

@Issue("JENKINS-44527")
@Test
public void testIssue44527() throws Exception {
Expand Down
39 changes: 39 additions & 0 deletions src/test/resources/hudson/plugins/nunit/NUnit-healthReport.xml
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<test-results name="/home/erik/coding/test/nunittests/Tests.dll" total="4" failures="1" not-run="0" date="2007-07-27" time="11:18:43">
<environment nunit-version="2.2.8.0" clr-version="2.0.50727.42" os-version="Unix 2.6.18.4" platform="Unix" cwd="/home/erik/coding/test/nunittests" machine-name="akira.ramfelt.se" user="erik" user-domain="akira.ramfelt.se" />
<culture-info current-culture="sv-SE" current-uiculture="sv-SE" />
<test-suite name="/home/erik/coding/test/nunittests/Tests.dll" success="False" time="0.404" asserts="0">
<results>
<test-suite name="UnitTests" success="False" time="0.393" asserts="0">
<results>
<test-suite name="UnitTests.MainClassTest" success="False" time="0.289" asserts="0">
<results>
<test-case name="UnitTests.MainClassTest.TestPropertyValue" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestMethodUpdateValue" executed="True" success="True" time="0.001" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestFailure" executed="True" success="False" time="0.092" asserts="1">
<failure>
<message><![CDATA[ Expected failure
Expected: 30
But was: 20
]]></message>
<stack-trace><![CDATA[ at UnitTests.MainClassTest.TestFailure () [0x00000]
at <0x00000> <unknown method>
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (object,object[])
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000]
]]></stack-trace>
</failure>
</test-case>
<test-case name="UnitTests.MainClassTest.TestPropertyValue1" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestPropertyValue2" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestPropertyValue3" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestPropertyValue4" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestPropertyValue5" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestPropertyValue6" executed="True" success="True" time="0.146" asserts="1" />
<test-case name="UnitTests.MainClassTest.TestPropertyValue7" executed="True" success="True" time="0.146" asserts="1" />
</results>
</test-suite>
</results>
</test-suite>
</results>
</test-suite>
</test-results>

0 comments on commit 129accb

Please sign in to comment.