1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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);
}
}
|