diff --git a/docs/consumers-guide.md b/docs/consumers-guide.md
index ddc53412..2fd6d2d2 100644
--- a/docs/consumers-guide.md
+++ b/docs/consumers-guide.md
@@ -62,3 +62,12 @@ getContext().get(ChecksInfo.class)
Currently, the `ChecksInfo` object only includes a `name` specified by users,
it is recommended that you look for this name and set it over your default checks name
+## Integration Testing
+
+An implementation of `ChecksPublisher` that captures all published `ChecksDetails` is provided
+in the `test` classifier, as `io.jenkins.plugins.checks.api.test.CapturingChecksPublisher`.
+
+Adding the factory for this publisher as a `TestExtension` will allow inspection of published checks after running a job
+on a `JenkinsRule`.
+
+An example of this can be found in [PublishChecksStepITest](../src/test/java/io/jenkins/plugins/checks/steps/PublishChecksStepITest.java).
diff --git a/pom.xml b/pom.xml
index bce66b18..4fe8161e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,6 +126,22 @@
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+ **/api/test/**
+
+
+
+
+
diff --git a/src/main/java/io/jenkins/plugins/checks/steps/PublishChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/PublishChecksStep.java
index 29b55b33..22724010 100644
--- a/src/main/java/io/jenkins/plugins/checks/steps/PublishChecksStep.java
+++ b/src/main/java/io/jenkins/plugins/checks/steps/PublishChecksStep.java
@@ -180,9 +180,16 @@ protected Void run() throws IOException, InterruptedException {
}
@VisibleForTesting
- ChecksDetails extractChecksDetails() {
+ ChecksDetails extractChecksDetails() throws IOException, InterruptedException {
+ // If a checks name has been provided as part of the step, use that.
+ // If not, check to see if there is an active ChecksInfo context (e.g. from withChecks).
+ String checksName = StringUtils.defaultIfEmpty(step.getName(),
+ Optional.ofNullable(getContext().get(ChecksInfo.class))
+ .map(ChecksInfo::getName)
+ .orElse(StringUtils.EMPTY)
+ );
return new ChecksDetails.ChecksDetailsBuilder()
- .withName(step.getName())
+ .withName(checksName)
.withStatus(step.getStatus())
.withConclusion(step.getConclusion())
.withDetailsURL(step.getDetailsURL())
diff --git a/src/test/java/io/jenkins/plugins/checks/api/test/CapturingChecksPublisher.java b/src/test/java/io/jenkins/plugins/checks/api/test/CapturingChecksPublisher.java
new file mode 100644
index 00000000..b29d900c
--- /dev/null
+++ b/src/test/java/io/jenkins/plugins/checks/api/test/CapturingChecksPublisher.java
@@ -0,0 +1,75 @@
+package io.jenkins.plugins.checks.api.test;
+
+import hudson.ExtensionList;
+import hudson.model.Job;
+import hudson.model.Run;
+import hudson.model.TaskListener;
+import io.jenkins.plugins.checks.api.ChecksDetails;
+import io.jenkins.plugins.checks.api.ChecksPublisher;
+import io.jenkins.plugins.checks.api.ChecksPublisherFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Implementation of {@link ChecksPublisher} for use in testing, that records each captured checks in a simple list.
+ *
+ * For example:
+ *
+ *
+ * public class ChecksPublishingTest extends IntegrationTestWithJenkinsPerTest {
+ *
+ * @TestExtension
+ * public static final CapturingChecksPublisher.Factory PUBLISHER_FACTORY = new CapturingChecksPublisher.Factory();
+ *
+ * @After
+ * public void clearPublishedChecks() {
+ * PUBLISHER_FACTORY.getPublishedChecks().clear();
+ * }
+ *
+ * @Test
+ * public void testChecksPublishing() {
+ *
+ * // ...Run a test job...
+ *
+ * List<ChecksDetails> publishedDetails = PUBLISHER_FACTORY.getPublishedChecks();
+ *
+ * // ...Inspect published checks...
+ * }
+ * }
+ *
+ *
+ * An example of this can be found in {@link io.jenkins.plugins.checks.steps.PublishChecksStepITest}
+ */
+public class CapturingChecksPublisher extends ChecksPublisher {
+
+ private final List publishedChecks = new ArrayList<>();
+
+ @Override
+ public void publish(final ChecksDetails details) {
+ publishedChecks.add(details);
+ }
+
+ /**
+ * Implementation of {@link ChecksPublisherFactory} that returns a {@link CapturingChecksPublisher}.
+ */
+ public static class Factory extends ChecksPublisherFactory {
+
+ private final CapturingChecksPublisher publisher = new CapturingChecksPublisher();
+
+ @Override
+ protected Optional createPublisher(final Run, ?> run, final TaskListener listener) {
+ return Optional.of(publisher);
+ }
+
+ @Override
+ protected Optional createPublisher(final Job, ?> job, final TaskListener listener) {
+ return Optional.of(publisher);
+ }
+
+ public List getPublishedChecks() {
+ return ExtensionList.lookup(Factory.class).get(0).publisher.publishedChecks;
+ }
+ }
+}
diff --git a/src/test/java/io/jenkins/plugins/checks/steps/PublishChecksStepITest.java b/src/test/java/io/jenkins/plugins/checks/steps/PublishChecksStepITest.java
index 6dc792df..f76ff38c 100644
--- a/src/test/java/io/jenkins/plugins/checks/steps/PublishChecksStepITest.java
+++ b/src/test/java/io/jenkins/plugins/checks/steps/PublishChecksStepITest.java
@@ -1,9 +1,15 @@
package io.jenkins.plugins.checks.steps;
+import io.jenkins.plugins.checks.api.ChecksConclusion;
+import io.jenkins.plugins.checks.api.ChecksDetails;
+import io.jenkins.plugins.checks.api.ChecksOutput;
+import io.jenkins.plugins.checks.api.ChecksStatus;
+import io.jenkins.plugins.checks.api.test.CapturingChecksPublisher;
import io.jenkins.plugins.util.IntegrationTestWithJenkinsPerTest;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.TestExtension;
import java.io.IOException;
@@ -13,6 +19,13 @@
* Tests the pipeline step to publish checks.
*/
public class PublishChecksStepITest extends IntegrationTestWithJenkinsPerTest {
+
+ /**
+ * Provide a {@link CapturingChecksPublisher} to check published checks on each test.
+ */
+ @TestExtension
+ public static final CapturingChecksPublisher.Factory PUBLISHER_FACTORY = new CapturingChecksPublisher.Factory();
+
/**
* Tests that the step "publishChecks" can be used in pipeline script.
*
@@ -26,7 +39,20 @@ public void shouldPublishChecksWhenUsingPipeline() throws IOException {
+ "text: 'Pipeline support for checks', status: 'IN_PROGRESS', conclusion: 'NONE'"));
assertThat(JenkinsRule.getLog(buildSuccessfully(job)))
- .contains("[Pipeline] publishChecks")
- .contains("[Checks API] No suitable checks publisher found.");
+ .contains("[Pipeline] publishChecks");
+
+ assertThat(PUBLISHER_FACTORY.getPublishedChecks().size()).isEqualTo(1);
+
+ ChecksDetails details = PUBLISHER_FACTORY.getPublishedChecks().get(0);
+
+ assertThat(details.getName()).isPresent().get().isEqualTo("customized-check");
+ assertThat(details.getOutput()).isPresent();
+ assertThat(details.getStatus()).isEqualTo(ChecksStatus.IN_PROGRESS);
+ assertThat(details.getConclusion()).isEqualTo(ChecksConclusion.NONE);
+
+ ChecksOutput output = details.getOutput().get();
+ assertThat(output.getTitle()).isPresent().get().isEqualTo("Publish Checks Step");
+ assertThat(output.getSummary()).isPresent().get().isEqualTo("customized check created in pipeline");
+ assertThat(output.getText()).isPresent().get().isEqualTo("Pipeline support for checks");
}
}
diff --git a/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java b/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java
index a6dc5bab..2cc2517b 100644
--- a/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java
+++ b/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java
@@ -1,9 +1,14 @@
package io.jenkins.plugins.checks.steps;
import hudson.model.Run;
+import io.jenkins.plugins.checks.api.ChecksConclusion;
+import io.jenkins.plugins.checks.api.ChecksDetails;
+import io.jenkins.plugins.checks.api.ChecksStatus;
+import io.jenkins.plugins.checks.api.test.CapturingChecksPublisher;
import io.jenkins.plugins.util.IntegrationTestWithJenkinsPerTest;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.steps.*;
+import org.junit.After;
import org.junit.Test;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.DataBoundConstructor;
@@ -20,6 +25,7 @@
* Tests the "withChecks" step.
*/
public class WithChecksStepITest extends IntegrationTestWithJenkinsPerTest {
+
/**
* Tests that the step can inject the {@link ChecksInfo} into the closure.
*/
@@ -31,6 +37,66 @@ public void shouldInjectChecksInfoIntoClosure() {
buildSuccessfully(job);
}
+ /**
+ * Provide a {@link CapturingChecksPublisher} to check published checks on each test.
+ */
+ @TestExtension
+ public static final CapturingChecksPublisher.Factory PUBLISHER_FACTORY = new CapturingChecksPublisher.Factory();
+
+ /**
+ * Clear captured checks on the {@link WithChecksStepITest#PUBLISHER_FACTORY} after each test.
+ */
+ @After
+ public void clearPublisher() {
+ PUBLISHER_FACTORY.getPublishedChecks().clear();
+ }
+
+ /**
+ * Test that the publishChecks step picks up names from the withChecks context.
+ */
+ @Test
+ public void publishChecksShouldTakeNameFromWithChecks() {
+ WorkflowJob job = createPipeline();
+ job.setDefinition(asStage("withChecks('test injection') { publishChecks() }"));
+
+ buildSuccessfully(job);
+
+ assertThat(PUBLISHER_FACTORY.getPublishedChecks().size()).isEqualTo(2);
+ ChecksDetails autoChecks = PUBLISHER_FACTORY.getPublishedChecks().get(0);
+ ChecksDetails manualChecks = PUBLISHER_FACTORY.getPublishedChecks().get(1);
+
+ assertThat(autoChecks.getName()).isPresent().get().isEqualTo("test injection");
+ assertThat(autoChecks.getStatus()).isEqualTo(ChecksStatus.IN_PROGRESS);
+ assertThat(autoChecks.getConclusion()).isEqualTo(ChecksConclusion.NONE);
+
+ assertThat(manualChecks.getName()).isPresent().get().isEqualTo("test injection");
+ assertThat(manualChecks.getStatus()).isEqualTo(ChecksStatus.COMPLETED);
+ assertThat(manualChecks.getConclusion()).isEqualTo(ChecksConclusion.SUCCESS);
+ }
+
+ /**
+ * Tests that withChecks step ignores names from the withChecks context if one has been explicitly set.
+ */
+ @Test
+ public void publishChecksShouldTakeNameFromWithChecksUnlessOverridden() {
+ WorkflowJob job = createPipeline();
+ job.setDefinition(asStage("withChecks('test injection') { publishChecks name: 'test override' }"));
+
+ buildSuccessfully(job);
+
+ assertThat(PUBLISHER_FACTORY.getPublishedChecks().size()).isEqualTo(2);
+ ChecksDetails autoChecks = PUBLISHER_FACTORY.getPublishedChecks().get(0);
+ ChecksDetails manualChecks = PUBLISHER_FACTORY.getPublishedChecks().get(1);
+
+ assertThat(autoChecks.getName()).isPresent().get().isEqualTo("test injection");
+ assertThat(autoChecks.getStatus()).isEqualTo(ChecksStatus.IN_PROGRESS);
+ assertThat(autoChecks.getConclusion()).isEqualTo(ChecksConclusion.NONE);
+
+ assertThat(manualChecks.getName()).isPresent().get().isEqualTo("test override");
+ assertThat(manualChecks.getStatus()).isEqualTo(ChecksStatus.COMPLETED);
+ assertThat(manualChecks.getConclusion()).isEqualTo(ChecksConclusion.SUCCESS);
+ }
+
/**
* Assert that the injected {@link ChecksInfo} is as expected.
*/