Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1236)

Unified Diff: base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java

Issue 1219683014: Added Generic Parameterized Testing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed John's and Randy's Comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..d91ccc470bb744f018d4e808686abef68873c91e
--- /dev/null
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
@@ -0,0 +1,275 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.test;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+
+import org.chromium.base.Log;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.parameters.BaseParameter;
+import org.chromium.base.test.util.parameters.Parameter;
+import org.chromium.base.test.util.parameters.Parameterizable;
+import org.chromium.base.test.util.parameters.ParameterizedTest;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A test result that can skip tests.
+ */
+public class BaseTestResult extends TestResult {
+ private static final String TAG = "cr.base.test";
+
+ private static final int SLEEP_INTERVAL = 50; // milliseconds
+ private static final int WAIT_DURATION = 5000; // milliseconds
+
+
+ private List<BaseParameter> mAvailableParameters;
+ private Instrumentation mInstrumentation;
+ private final List<SkipCheck> mSkipChecks;
+
+ /**
+ * Creates an instance of BaseTestResult.
+ */
+ public BaseTestResult(Instrumentation instrumentation) {
+ mSkipChecks = new ArrayList<SkipCheck>();
+ mInstrumentation = instrumentation;
+ mAvailableParameters = new ArrayList<>();
+ }
+
+ /**
+ * An interface for classes that check whether a test case should be skipped.
+ */
+ public interface SkipCheck {
+ /**
+ *
+ * Checks whether the given test case should be skipped.
+ *
+ * @param testCase The test case to check.
+ * @return Whether the test case should be skipped.
+ */
+ public boolean shouldSkip(TestCase testCase);
+ }
+
+ /**
+ * Adds a check for whether a test should run.
+ *
+ * @param skipCheck The check to add.
+ */
+ public void addSkipCheck(SkipCheck skipCheck) {
+ mSkipChecks.add(skipCheck);
+ }
+
+ protected boolean shouldSkip(final TestCase test) {
+ for (SkipCheck s : mSkipChecks) {
+ if (s.shouldSkip(test)) return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void run(final TestCase test) {
+ if (shouldSkip(test)) {
+ startTest(test);
+
+ Bundle skipResult = new Bundle();
+ skipResult.putString("class", test.getClass().getName());
+ skipResult.putString("test", test.getName());
+ skipResult.putBoolean("test_skipped", true);
+ mInstrumentation.sendStatus(0, skipResult);
+
+ endTest(test);
+ } else {
+ try {
+ CommandLineFlags.setUp(
+ getTargetContext(),
+ test.getClass().getMethod(test.getName()));
+ } catch (NoSuchMethodException e) {
+ Log.e(TAG, "Unable to set up CommandLineFlags", e);
+ }
+
+ if (test instanceof Parameterizable) {
+ try {
+ runParameterized(test);
+ } catch (ThreadDeath e) {
+ Log.e(TAG, "Parameterized test run failed: %s", e);
+ }
+ } else {
+ super.run(test);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends TestCase & Parameterizable> void runParameterized(final TestCase test)
+ throws ThreadDeath {
+ final T testCase = (T) test;
+
+ Parameter.Reader parameterReader = new Parameter.Reader(test);
+ testCase.setParameterReader(parameterReader);
+ List<ParameterizedTest> parameterizedTests = parameterReader.getParameterizedTests();
+ if (!parameterizedTests.isEmpty()) {
+
+ // Start and prepare test.
+ startTest(testCase);
+ List<ParameterError> errors = new ArrayList<>();
+ List<ParameterError> failures = new ArrayList<>();
+ mAvailableParameters.addAll(testCase.getAvailableParameters());
jbudorick 2015/08/06 16:48:17 Make mAvailableParameters local to this function &
Sean Kirmani 2015/08/06 17:16:58 Done.
+
+ // Run the actual tests.
+ for (final ParameterizedTest parameterizedTest : parameterizedTests) {
+ parameterReader.setCurrentParameterizedTest(parameterizedTest);
+ try {
+ setUpParameters(testCase);
+ testCase.runBare();
+ tearDownParameters(testCase);
+ } catch (AssertionFailedError e) {
+ failures.add(new ParameterError(e, parameterizedTest));
+ } catch (ThreadDeath e) {
+ throw e;
+ } catch (Throwable e) {
+ errors.add(new ParameterError(e, parameterizedTest));
+ }
+ }
+
+ // Generate failures and errors.
+ if (!failures.isEmpty()) {
+ addFailure(test, new ParameterizedTestFailure(failures));
+ }
+ if (!errors.isEmpty()) {
+ addError(test, new ParameterizedTestError(errors));
+ }
+
+ // End test.
+ mAvailableParameters = new ArrayList<>();
+ endTest(testCase);
+ } else {
+ super.run(test);
+ }
+ }
+
+ private <T extends TestCase & Parameterizable> void setUpParameters(final T test)
+ throws Exception {
+ Parameter.Reader parameterReader = new Parameter.Reader(test);
+ for (BaseParameter parameter : mAvailableParameters) {
+ if (parameterReader.getParameter(parameter.getTag()) != null) {
+ parameter.setUp();
+ }
+ }
+ }
+
+ private <T extends TestCase & Parameterizable> void tearDownParameters(final T test)
+ throws Exception {
+ Parameter.Reader parameterReader = new Parameter.Reader(test);
+ for (BaseParameter parameter : mAvailableParameters) {
+ if (parameterReader.getParameter(parameter.getTag()) != null) {
+ parameter.tearDown();
+ }
+ }
+ }
+
+ private static class ParameterError {
+ private Throwable mThrowable;
+ private ParameterizedTest mParameterizedTest;
+
+ public ParameterError(Throwable throwable, ParameterizedTest parameterizedTest) {
+ mThrowable = throwable;
+ mParameterizedTest = parameterizedTest;
+ }
+
+ private Throwable getThrowable() {
+ return mThrowable;
+ }
+
+ private ParameterizedTest getParameterizedTest() {
+ return mParameterizedTest;
+ }
+ }
+
+ private static class ParameterizedTestFailure extends AssertionFailedError {
+ public ParameterizedTestFailure(List<ParameterError> failures) {
+ super(new ParameterizedTestError(failures).toString());
+ }
+ }
+
+ private static class ParameterizedTestError extends Exception {
+ public List<ParameterError> mErrors;
+
+ public ParameterizedTestError(List<ParameterError> errors) {
+ mErrors = errors;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('\n');
jbudorick 2015/08/06 16:48:17 nit: collapse this line into the ctor above
Sean Kirmani 2015/08/06 17:16:58 Done.
+ for (ParameterError error : mErrors) {
+ List<Parameter> parameters =
+ Arrays.asList(error.getParameterizedTest().parameters());
+ if (!parameters.isEmpty()) {
+ StringBuffer parametersString = new StringBuffer();
+ for (int i = 0; i < parameters.size(); i++) {
+ parametersString.append(parameters.get(i).tag());
+ if (i != parameters.size() - 1) {
+ parametersString.append(',');
+ }
+ }
+ buffer.append(String.format("%s (with parameters %s)%n",
+ error.getThrowable().toString(), parametersString.toString()));
+ } else {
+ buffer.append(String.format("%s (with no parameters)%n",
+ error.getThrowable().toString()));
+ }
+ buffer.append(trace(error) + '\n');
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * @return the trace without the error message
+ */
+ private String trace(ParameterError error) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = new PrintWriter(stringWriter);
+ error.getThrowable().printStackTrace(writer);
+ StringBuffer buffer = stringWriter.getBuffer();
+ return buffer.toString().substring(buffer.toString().indexOf('\n') + 1);
+ }
+ }
+
+ /**
+ * Gets the target context.
+ *
+ * On older versions of Android, getTargetContext() may initially return null, so we have to
+ * wait for it to become available.
+ *
+ * @return The target {@link android.content.Context} if available; null otherwise.
+ */
+ public Context getTargetContext() {
+ Context targetContext = mInstrumentation.getTargetContext();
+ try {
+ long startTime = SystemClock.uptimeMillis();
+ // TODO(jbudorick): Convert this to CriteriaHelper once that moves to base/.
+ while (targetContext == null
+ && SystemClock.uptimeMillis() - startTime < WAIT_DURATION) {
+ Thread.sleep(SLEEP_INTERVAL);
+ targetContext = mInstrumentation.getTargetContext();
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted while attempting to initialize the command line.");
+ }
+ return targetContext;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698