aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/junitrunner
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-09-22 04:16:39 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2016-09-22 09:57:49 +0000
commit36395c417899bd4009efc3a6cda5ea838f3d98ef (patch)
treee8a5cfed427981772b70628a76995f0a2308e4b4 /src/java_tools/junitrunner
parentba80dfd9bb2aee3f45201f3d4e6c7a1b6dc4f228 (diff)
Bazel to support external links integration. This is so that the tests can inject custom extra data (link, icons, etc) so that a test method can be associated with an external tool.
-- MOS_MIGRATED_REVID=133912980
Diffstat (limited to 'src/java_tools/junitrunner')
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestCaseNode.java19
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestResult.java24
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java4
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteNode.java5
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/BUILD1
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegration.java110
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsExporter.java70
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsRunnerIntegration.java57
8 files changed, 279 insertions, 11 deletions
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestCaseNode.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestCaseNode.java
index 075f7f0b60..7c2567434f 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestCaseNode.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestCaseNode.java
@@ -17,6 +17,8 @@ package com.google.testing.junit.runner.model;
import static com.google.testing.junit.runner.util.TestPropertyExporter.INITIAL_INDEX_FOR_REPEATED_PROPERTY;
import com.google.testing.junit.runner.model.TestResult.Status;
+import com.google.testing.junit.runner.util.TestIntegration;
+import com.google.testing.junit.runner.util.TestIntegrationsExporter;
import com.google.testing.junit.runner.util.TestPropertyExporter;
import java.util.ArrayList;
import java.util.Collections;
@@ -24,22 +26,24 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nullable;
import org.junit.runner.Description;
-/**
- * A leaf in the test suite model.
- */
-class TestCaseNode extends TestNode implements TestPropertyExporter.Callback {
+/** A leaf in the test suite model. */
+class TestCaseNode extends TestNode
+ implements TestPropertyExporter.Callback, TestIntegrationsExporter.Callback {
private final TestSuiteNode parent;
private final Map<String, String> properties = new ConcurrentHashMap<>();
private final Map<String, Integer> repeatedPropertyNamesToRepetitions = new HashMap<>();
private final Queue<Throwable> globalFailures = new ConcurrentLinkedQueue<>();
private final ConcurrentMap<Description, List<Throwable>> dynamicTestToFailures =
new ConcurrentHashMap<>();
+ private final Set<TestIntegration> integrations =
+ Collections.newSetFromMap(new ConcurrentHashMap<TestIntegration, Boolean>());
@Nullable private volatile TestInterval runTimeInterval = null;
private volatile State state = State.INITIAL;
@@ -86,6 +90,11 @@ class TestCaseNode extends TestNode implements TestPropertyExporter.Callback {
}
@Override
+ public void exportTestIntegration(TestIntegration testIntegration) {
+ integrations.add(testIntegration);
+ }
+
+ @Override
public void testSkipped(long now) {
compareAndSetState(State.STARTED, State.SKIPPED, now);
}
@@ -207,6 +216,7 @@ class TestCaseNode extends TestNode implements TestPropertyExporter.Callback {
.numTests(numTests)
.numFailures(numFailures)
.childResults(childResults)
+ .integrations(integrations)
.build();
}
@@ -229,6 +239,7 @@ class TestCaseNode extends TestNode implements TestPropertyExporter.Callback {
.numTests(1)
.numFailures(failed ? 1 : 0)
.childResults(Collections.<TestResult>emptyList())
+ .integrations(Collections.<TestIntegration>emptySet())
.build();
}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestResult.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestResult.java
index 047b769766..e931eb423b 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestResult.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestResult.java
@@ -14,13 +14,13 @@
package com.google.testing.junit.runner.model;
+import com.google.testing.junit.runner.util.TestIntegration;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.annotation.Nullable;
-/**
- * Result of executing a test suite or test case.
- */
+/** Result of executing a test suite or test case. */
final class TestResult {
/**
@@ -78,12 +78,15 @@ final class TestResult {
}
}
- private final String name, className;
+ private final String name;
+ private final String className;
private final Map<String, String> properties;
private final List<Throwable> failures;
@Nullable private final TestInterval runTime;
+ private final Set<TestIntegration> integrations;
private final Status status;
- private final int numTests, numFailures;
+ private final int numTests;
+ private final int numFailures;
private final List<TestResult> childResults;
private TestResult(Builder builder) {
@@ -96,6 +99,7 @@ final class TestResult {
numTests = checkNotNull(builder.numTests, "numTests not set");
numFailures = checkNotNull(builder.numFailures, "numFailures not set");
childResults = checkNotNull(builder.childResults, "childResults not set");
+ integrations = checkNotNull(builder.integrations, "integrations not set");
}
String getName() {
@@ -114,6 +118,10 @@ final class TestResult {
return failures;
}
+ Set<TestIntegration> getIntegrations() {
+ return integrations;
+ }
+
@Nullable
TestInterval getRunTimeInterval() {
return runTime;
@@ -152,6 +160,7 @@ final class TestResult {
private Map<String, String> properties = null;
private List<Throwable> failures = null;
@Nullable private TestInterval runTime = null;
+ private Set<TestIntegration> integrations = null;
private Status status = null;
private Integer numTests = null;
private Integer numFailures = null;
@@ -174,6 +183,11 @@ final class TestResult {
return this;
}
+ Builder integrations(Set<TestIntegration> integrations) {
+ this.integrations = checkNullToNotNull(this.integrations, integrations, "integrations");
+ return this;
+ }
+
Builder failures(List<Throwable> failures) {
this.failures = checkNullToNotNull(this.failures, failures, "failures");
return this;
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java
index 350dbbf42c..92193460ad 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java
@@ -19,6 +19,7 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
import com.google.testing.junit.junit4.runner.DynamicTestException;
import com.google.testing.junit.runner.sharding.ShardingEnvironment;
import com.google.testing.junit.runner.sharding.ShardingFilters;
+import com.google.testing.junit.runner.util.TestIntegrationsRunnerIntegration;
import com.google.testing.junit.runner.util.TestPropertyRunnerIntegration;
import com.google.testing.junit.runner.util.Ticker;
import java.io.IOException;
@@ -106,6 +107,7 @@ public class TestSuiteModel {
if (testCase != null) {
testCase.started(currentMillis());
TestPropertyRunnerIntegration.setTestCaseForThread(testCase);
+ TestIntegrationsRunnerIntegration.setTestCaseForThread(testCase);
}
}
@@ -341,4 +343,4 @@ public class TestSuiteModel {
}
return filteredAndConvertedTests;
}
-} \ No newline at end of file
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteNode.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteNode.java
index 2ebf6ae6e1..73996b15dd 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteNode.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteNode.java
@@ -15,6 +15,7 @@
package com.google.testing.junit.runner.model;
import com.google.testing.junit.runner.model.TestResult.Status;
+import com.google.testing.junit.runner.util.TestIntegration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
@@ -88,7 +89,8 @@ class TestSuiteNode extends TestNode {
@Override
protected TestResult buildResult() {
TestInterval runTime = null;
- int numTests = 0, numFailures = 0;
+ int numTests = 0;
+ int numFailures = 0;
LinkedList<TestResult> childResults = new LinkedList<>();
for (TestNode child : children) {
@@ -118,6 +120,7 @@ class TestSuiteNode extends TestNode {
.numTests(numTests)
.numFailures(numFailures)
.childResults(childResults)
+ .integrations(Collections.<TestIntegration>emptySet())
.build();
}
}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/BUILD b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/BUILD
index a1a28b5406..ab65e19f9c 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/BUILD
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/BUILD
@@ -11,6 +11,7 @@ java_library(
name = "util",
srcs = glob(["*.java"]),
deps = [
+ "//third_party:auto_value",
"//third_party:jsr305",
"//third_party:junit4",
],
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegration.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegration.java
new file mode 100644
index 0000000000..18dfc05414
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegration.java
@@ -0,0 +1,110 @@
+// Copyright 2009 The Bazel Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.testing.junit.runner.util;
+
+import com.google.auto.value.AutoValue;
+import java.util.EnumMap;
+import java.util.Map;
+
+/** TestIntegration represents an external link that is integrated with the test results. */
+@AutoValue
+public abstract class TestIntegration {
+
+ /** Represents each available field for TestIntegration. */
+ public enum ExternalLinkAttribute {
+ NAME,
+ URL,
+ CONTACT_EMAIL,
+ COMPONENT_ID,
+ DESCRIPTION,
+ ICON_NAME,
+ ICON_URL,
+ BACKGROUND_COLOR,
+ FOREGROUND_COLOR;
+
+ /** Gets the string representation of the current enum. */
+ public String getXmlAttributeName() {
+ return name().toLowerCase();
+ }
+ }
+
+ // Group or user name responsible for this external integration.
+ abstract String contactEmail();
+ // Component id (numeric) for this external integration.
+ abstract String componentId();
+ // Display name of this external integration.
+ abstract String name();
+ // URL that will display more data about this test result or integration.
+ abstract String url();
+ // Optional: URL or name of the icon to be displayed.
+ abstract String iconUrl();
+
+ abstract String iconName();
+ // Optional: Textual description that shows up as tooltip.
+ abstract String description();
+ // Optional: Foreground color.
+ abstract String foregroundColor();
+ // Optional: Background color.
+ abstract String backgroundColor();
+
+ static Builder builder() {
+ return new AutoValue_TestIntegration.Builder()
+ .setIconName("")
+ .setIconUrl("")
+ .setDescription("")
+ .setForegroundColor("")
+ .setBackgroundColor("");
+ }
+
+ @AutoValue.Builder
+ abstract static class Builder {
+ public abstract Builder setContactEmail(String email);
+
+ public abstract Builder setComponentId(String id);
+
+ public abstract Builder setName(String name);
+
+ public abstract Builder setUrl(String url);
+
+ public abstract Builder setIconUrl(String iconUrl);
+
+ public abstract Builder setIconName(String iconName);
+
+ public abstract Builder setDescription(String description);
+
+ public abstract Builder setForegroundColor(String foregroundColor);
+
+ public abstract Builder setBackgroundColor(String backgroundColor);
+
+ abstract TestIntegration build();
+ }
+
+ /*
+ * getAttributeValueMap returns all of this TestIntegration's values in a Map.
+ */
+ public Map<ExternalLinkAttribute, String> getAttributeValueMap() {
+ Map<ExternalLinkAttribute, String> map = new EnumMap<>(ExternalLinkAttribute.class);
+ map.put(ExternalLinkAttribute.NAME, name());
+ map.put(ExternalLinkAttribute.URL, url());
+ map.put(ExternalLinkAttribute.CONTACT_EMAIL, contactEmail());
+ map.put(ExternalLinkAttribute.COMPONENT_ID, componentId());
+ map.put(ExternalLinkAttribute.DESCRIPTION, description());
+ map.put(ExternalLinkAttribute.ICON_NAME, iconName());
+ map.put(ExternalLinkAttribute.ICON_URL, iconUrl());
+ map.put(ExternalLinkAttribute.BACKGROUND_COLOR, backgroundColor());
+ map.put(ExternalLinkAttribute.FOREGROUND_COLOR, foregroundColor());
+ return map;
+ }
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsExporter.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsExporter.java
new file mode 100644
index 0000000000..486fba4242
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsExporter.java
@@ -0,0 +1,70 @@
+// Copyright 2016 The Bazel Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.testing.junit.runner.util;
+
+import static com.google.testing.junit.runner.util.TestIntegrationsRunnerIntegration.getCallbackForThread;
+
+/** Exports test TestIntegrations to the test XML. */
+public class TestIntegrationsExporter {
+ /*
+ * The global {@code TestIntegrationsExporter}, which writes the properties into
+ * the test XML if the test is running from the command line.
+ *
+ * <p>If you have test infrastructure that needs to export properties, consider
+ * injecting an instance of {@code TestIntegrationsExporter}. Your tests can
+ * use one of the static methods in this class to create a fake instance.
+ */
+ public static final TestIntegrationsExporter INSTANCE =
+ new TestIntegrationsExporter(new DefaultCallback());
+
+ private final Callback callback;
+
+ /**
+ * Creates a fake {@code TestIntegrationsExporter} instance, passing values to the passed-in
+ * callback.
+ *
+ * @param callback Callback to use when values are exported
+ * @return exporter instance
+ */
+ public static TestIntegrationsExporter createFake(final Callback callback) {
+ return new TestIntegrationsExporter(callback);
+ }
+
+ protected TestIntegrationsExporter(Callback callback) {
+ this.callback = callback;
+ }
+
+ public void newTestIntegration(TestIntegration testIntegration) {
+ callback.exportTestIntegration(testIntegration);
+ }
+
+ /** Callback that is used to store TestIntegration in the model. */
+ public interface Callback {
+ /** Export the TestIntegration. */
+ void exportTestIntegration(TestIntegration testIntegration);
+ }
+
+ /**
+ * Default callback implementation. Calls the test runner model to write the external integrations
+ * to the XML.
+ */
+ private static class DefaultCallback implements Callback {
+
+ @Override
+ public void exportTestIntegration(TestIntegration testIntegration) {
+ getCallbackForThread().exportTestIntegration(testIntegration);
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsRunnerIntegration.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsRunnerIntegration.java
new file mode 100644
index 0000000000..78a8894f9a
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/TestIntegrationsRunnerIntegration.java
@@ -0,0 +1,57 @@
+// Copyright 2011 The Bazel Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.testing.junit.runner.util;
+
+import com.google.testing.junit.runner.util.TestIntegrationsExporter.Callback;
+import javax.annotation.Nullable;
+
+/** JUnit runner integration code for TestIntegration. */
+public class TestIntegrationsRunnerIntegration {
+ private static final ThreadLocal<Callback> callbackForThread =
+ new ThreadLocal<Callback>() {
+ @Override
+ protected Callback initialValue() {
+ return NoOpCallback.INSTANCE;
+ }
+ };
+
+ /**
+ * Sets the per-thread callback.
+ *
+ * @param callback Callback
+ */
+ public static Callback setTestCaseForThread(@Nullable Callback callback) {
+ Callback previousCallback = callbackForThread.get();
+ if (callback == null) {
+ callbackForThread.remove();
+ } else {
+ callbackForThread.set(callback);
+ }
+ return previousCallback;
+ }
+
+ static Callback getCallbackForThread() {
+ // TODO(bazel-team): This won't work if the test is running in a different thread from the test
+ // runner.
+ return callbackForThread.get();
+ }
+
+ private static class NoOpCallback implements Callback {
+ private static final Callback INSTANCE = new NoOpCallback();
+
+ @Override
+ public void exportTestIntegration(TestIntegration testIntegration) {}
+ }
+}