diff options
Diffstat (limited to 'tests/src/cgeo/junit/CgeoTestRunner.java')
-rw-r--r-- | tests/src/cgeo/junit/CgeoTestRunner.java | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/tests/src/cgeo/junit/CgeoTestRunner.java b/tests/src/cgeo/junit/CgeoTestRunner.java new file mode 100644 index 0000000..94803cf --- /dev/null +++ b/tests/src/cgeo/junit/CgeoTestRunner.java @@ -0,0 +1,125 @@ +package cgeo.junit; + +import com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner; +import com.zutubi.android.junitreport.JUnitReportListener; +import com.zutubi.android.junitreport.JUnitReportTestRunner; + +import android.os.Bundle; +import android.test.AndroidTestRunner; +import android.util.Log; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Test runner which derives from the newer Google instrumentation test runner used by the Espresso test framework. It + * adds junit report functionality by cloning the behavior of the {@link JUnitReportTestRunner}. + * + */ +public class CgeoTestRunner extends GoogleInstrumentationTestRunner { + + /** + * Name of the report file(s) to write, may contain __suite__ in multiFile mode. + */ + private static final String ARG_REPORT_FILE = "reportFile"; + /** + * If specified, path of the directory to write report files to. May start with __external__. + * If not set files are written to the internal storage directory of the app under test. + */ + private static final String ARG_REPORT_DIR = "reportDir"; + /** + * If true, stack traces in the report will be filtered to remove common noise (e.g. framework + * methods). + */ + private static final String ARG_FILTER_TRACES = "filterTraces"; + /** + * If true, produce a separate file for each test suite. By default a single report is created + * for all suites. + */ + private static final String ARG_MULTI_FILE = "multiFile"; + /** + * Default name of the single report file. + */ + private static final String DEFAULT_SINGLE_REPORT_FILE = "junit-report.xml"; + /** + * Default name pattern for multiple report files. + */ + private static final String DEFAULT_MULTI_REPORT_FILE = "junit-report-" + JUnitReportListener.TOKEN_SUITE + ".xml"; + + private static final String LOG_TAG = CgeoTestRunner.class.getSimpleName(); + + private JUnitReportListener mListener; + private String mReportFile; + private String mReportDir; + private boolean mFilterTraces = true; + private boolean mMultiFile = false; + + @Override + public void onCreate(Bundle arguments) { + if (arguments != null) { + Log.i(LOG_TAG, "Created with arguments: " + arguments.keySet()); + mReportFile = arguments.getString(ARG_REPORT_FILE); + mReportDir = arguments.getString(ARG_REPORT_DIR); + mFilterTraces = getBooleanArgument(arguments, ARG_FILTER_TRACES, true); + mMultiFile = getBooleanArgument(arguments, ARG_MULTI_FILE, false); + } else { + Log.i(LOG_TAG, "No arguments provided"); + } + + if (mReportFile == null) { + mReportFile = mMultiFile ? DEFAULT_MULTI_REPORT_FILE : DEFAULT_SINGLE_REPORT_FILE; + } + Log.i(LOG_TAG, "report directory '" + mReportDir + "'"); + Log.i(LOG_TAG, "report file '" + mReportFile + "'"); + + super.onCreate(arguments); + } + + private static boolean getBooleanArgument(Bundle arguments, String name, boolean defaultValue) { + String value = arguments.getString(name); + if (value == null) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + @Override + public void start() { + makeAndroidTestRunnerAccessible(); + super.start(); + } + + private void makeAndroidTestRunnerAccessible() { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + mListener = new JUnitReportListener(getContext(), getTargetContext(), mReportFile, mReportDir, mFilterTraces, mMultiFile); + try { + Class<?> c = getClass(); + Field bridgeTestRunner = c.getSuperclass().getDeclaredField("bridgeTestRunner"); + bridgeTestRunner.setAccessible(true); + Object obj = bridgeTestRunner.get(this); + Method m = obj.getClass().getDeclaredMethod("getAndroidTestRunner", (Class[]) null); + AndroidTestRunner androidTestRunner = (AndroidTestRunner) m.invoke(obj); + androidTestRunner.addTestListener(mListener); + } catch (NoSuchFieldException | InvocationTargetException | IllegalAccessException + | NoSuchMethodException | SecurityException x) { + Log.e(LOG_TAG, x.toString()); + } + return null; + } + }); + } + + @Override + public void finish(int resultCode, Bundle results) { + if (mListener != null) { + mListener.close(); + } + + super.finish(resultCode, results); + } +} |