下面列出了怎么用android.app.Instrumentation的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void testCameraFlow() {
Bitmap icon = BitmapFactory.decodeResource(
InstrumentationRegistry.getTargetContext().getResources(),
R.mipmap.ic_launcher);
Intent resultData = new Intent();
resultData.putExtra("data", icon);
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
intending(hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result);
Espresso.onView(withId(R.id.camera_button)).perform(click());
intended(hasAction(MediaStore.ACTION_IMAGE_CAPTURE));
}
private void reportFailure(Failure failure) {
String trace = failure.getTrace();
if (trace.length() > MAX_TRACE_SIZE) {
// Since AJUR needs to report failures back to AM via a binder IPC, we need to make sure that
// we don't exceed the Binder transaction limit - which is 1MB per process.
Log.w(
TAG,
String.format("Stack trace too long, trimmed to first %s characters.", MAX_TRACE_SIZE));
trace = trace.substring(0, MAX_TRACE_SIZE) + "\n";
}
testResult.putString(REPORT_KEY_STACK, trace);
// pretty printing
testResult.putString(
Instrumentation.REPORT_KEY_STREAMRESULT,
String.format(
"\nError in %s:\n%s", failure.getDescription().getDisplayName(), failure.getTrace()));
}
public static void dispatchMotionEvents(final Instrumentation instrumentation, final Iterable<MotionEvent> motionEvents, final boolean wait) throws InterruptedException {
for (final MotionEvent event : motionEvents) {
int i = 0;
boolean success = false;
do {
try {
instrumentation.sendPointerSync(event);
success = true;
} catch (SecurityException e) {
i++;
if (i > 3) {
throw e;
}
}
} while (i < 3 && !success);
Thread.sleep(100);
}
if (wait) {
/* We need to wait for the fling animation to complete */
Thread.sleep(1500);
}
}
@Before
public void setUp() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
Intent intent = SessionDetailActivity.createIntent(context, SESSION);
// The third argument of the constructor for ActivityTestRule needs to be false as explained
// in the Javadoc for ActivityTestRule#launchActivity
// http://developer.android.com/reference/android/support/test/rule/ActivityTestRule.html#launchActivity(android.content.Intent)
activityRule.launchActivity(intent);
// By default Espresso Intents does not stub any Intents. Stubbing needs to be setup before
// every test run. In this case all external Intents will be blocked.
intending(not(isInternal()))
.respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));
}
/**
* 反射获取ActivityThread中的Instrumentation对象
* 从而拦截Activity跳转
*/
@Deprecated
private void hookInstrumentation() {
try {
Context contextImpl = ((ContextWrapper) mHostContext).getBaseContext();
Object activityThread = ReflectionUtils.getFieldValue(contextImpl, "mMainThread");
Field instrumentationF = activityThread.getClass().getDeclaredField("mInstrumentation");
instrumentationF.setAccessible(true);
Instrumentation hostInstr = (Instrumentation) instrumentationF.get(activityThread);
mPluginInstrument = new PluginInstrument(hostInstr, mPluginPackageName);
} catch (Exception e) {
ErrorUtil.throwErrorIfNeed(e);
PluginManager.deliver(mHostContext, false, mPluginPackageName,
ErrorType.ERROR_PLUGIN_HOOK_INSTRUMENTATION, "hookInstrumentation failed");
}
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doReturn("/apps/foo.apk").when(mockContext).getPackageCodePath();
androidJUnitRunner =
new AndroidJUnitRunner() {
@Override
public Context getContext() {
return mockContext;
}
@Override
InstrumentationResultPrinter getInstrumentationResultPrinter() {
return instrumentationResultPrinter;
}
@Override
TestRequestBuilder createTestRequestBuilder(Instrumentation instr, Bundle arguments) {
return testRequestBuilder;
}
};
}
/**
* Produce a more meaningful crash report including stack trace and report it back to
* Instrumentation results.
*/
public void reportProcessCrash(Throwable t) {
try {
testResultCode = REPORT_VALUE_RESULT_FAILURE;
ParcelableFailure failure = new ParcelableFailure(description, t);
testResult.putString(REPORT_KEY_STACK, failure.getTrace());
// pretty printing
testResult.putString(
Instrumentation.REPORT_KEY_STREAMRESULT,
String.format(
"\nProcess crashed while executing %s:\n%s",
description.getDisplayName(), failure.getTrace()));
testFinished(description);
} catch (Exception e) {
if (null == description) {
Log.e(LOG_TAG, "Failed to initialize test before process crash");
} else {
Log.e(
LOG_TAG,
"Failed to mark test "
+ description.getDisplayName()
+ " as finished after process crash");
}
}
}
private static void hookInstrumentation() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
Class<?> c = Class.forName("android.app.ActivityThread");
Method currentActivityThread = c.getDeclaredMethod("currentActivityThread");
boolean acc = currentActivityThread.isAccessible();
if (!acc) {
currentActivityThread.setAccessible(true);
}
Object o = currentActivityThread.invoke(null);
if (!acc) {
currentActivityThread.setAccessible(acc);
}
Field f = c.getDeclaredField("mInstrumentation");
acc = f.isAccessible();
if (!acc) {
f.setAccessible(true);
}
Instrumentation currentInstrumentation = (Instrumentation) f.get(o);
Instrumentation ins = new ApmInstrumentation(currentInstrumentation);
f.set(o, ins);
if (!acc) {
f.setAccessible(acc);
}
}
public static void dispatchDragScrollDownMotionEvents(final Instrumentation instrumentation, final DynamicListView dynamicListView,
final int fromPosition) throws InterruptedException {
int[] location = new int[2];
dynamicListView.getLocationOnScreen(location);
View view = dynamicListView.getChildAt(fromPosition);
float fromY = (int) (view.getY()) + location[1];
View toView = dynamicListView.getChildAt(dynamicListView.getLastVisiblePosition());
float toY = (int) (toView.getY() + toView.getHeight()) + location[1] + 2;
List<MotionEvent> motionEvents = createMotionEvents(dynamicListView, fromY, toY);
MotionEvent upEvent = motionEvents.remove(motionEvents.size() - 1);
dispatchMotionEvents(instrumentation, motionEvents, true);
Thread.sleep(10000);
dispatchMotionEvents(instrumentation, Arrays.asList(upEvent), true);
}
private static void waitInner(ReactBridgeIdleSignaler idleSignaler, long timeToWait) {
// TODO gets broken in gradle, do we need it?
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
long startTime = SystemClock.uptimeMillis();
boolean bridgeWasIdle = false;
while (SystemClock.uptimeMillis() - startTime < timeToWait) {
boolean bridgeIsIdle = idleSignaler.isBridgeIdle();
if (bridgeIsIdle && bridgeWasIdle) {
return;
}
bridgeWasIdle = bridgeIsIdle;
long newTimeToWait = Math.max(1, timeToWait - (SystemClock.uptimeMillis() - startTime));
idleSignaler.waitForIdle(newTimeToWait);
instrumentation.waitForIdleSync();
}
throw new RuntimeException("Timed out waiting for bridge and UI idle!");
}
@Test
public void testStateDestroy() {
//final String TEST_SOMETHING = "test123456789";
//TODO: mActivity.setSomething();
mActivity.finish();
// Based on this:
// http://stackoverflow.com/a/33213279/1123654
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.runOnMainSync(new Runnable() {
@Override
public void run() {
mActivity.recreate();
}
});
//TODOassertEquals(TEST_SOMETHING, mActivity.getSomething());
//TODO: Do something like this too:
//onView(withText("a string depending on XXX value")).check(doesNotExist())
}
@Override
public void onStart() {
super.onStart();
try {
registerUserTracker();
grantRuntimePermissions(RUNTIME_PERMISSIONS);
connectOrchestratorService();
} catch (RuntimeException e) {
final String msg = "Fatal exception when setting up.";
Log.e(TAG, msg, e);
// Report the startup exception to instrumentation out.
Bundle failureBundle = createResultBundle();
failureBundle.putString(
Instrumentation.REPORT_KEY_STREAMRESULT, msg + "\n" + Log.getStackTraceString(e));
finish(Activity.RESULT_OK, failureBundle);
}
}
@Test
public void testClickEmptySpaceOnListUnselectItem() throws InterruptedException {
accountDb.add(
"first", "7777777777777777", OtpType.HOTP, null, null, AccountDb.GOOGLE_ISSUER_NAME);
AuthenticatorActivity activity = activityTestRule.launchActivity(null);
EmptySpaceClickableDragSortListView userList = activity.findViewById(R.id.user_list);
assertThat(activity.actionMode).isNull();
onView(equalTo(userList.getChildAt(0))).perform(longClick());
assertThat(activity.actionMode).isNotNull();
Point size = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(size);
int height = size.y;
int width = size.x;
Instrumentation instr = InstrumentationRegistry.getInstrumentation();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
instr.sendPointerSync(
MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, height / 2, width / 2, 0));
instr.sendPointerSync(
MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, height / 2, width / 2, 0));
// We need to delay to wait for the contextual action bar is completely removed.
Thread.sleep(CLICK_DELAY_INTERVAL);
assertThat(activity.actionMode).isNull();
}
public static Instrumentation.ActivityResult execStartActivity(
Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token,
Activity target, Intent intent, int requestCode) {
if (sInstrumentation_execStartActivityV20_method == null) {
Class[] types = new Class[] {Context.class, IBinder.class, IBinder.class,
Activity.class, Intent.class, int.class};
sInstrumentation_execStartActivityV20_method = getMethod(Instrumentation.class,
"execStartActivity", types);
}
if (sInstrumentation_execStartActivityV20_method == null) return null;
return invoke(sInstrumentation_execStartActivityV20_method, instrumentation,
who, contextThread, token, target, intent, requestCode);
}
/***
* get Instrumentation,should be hacked Instrumentation
*/
public static Instrumentation getInstrumentation() throws Exception {
Object activityThread = getActivityThread();
if (activityThread != null) {
return OpenAtlasHacks.ActivityThread_mInstrumentation
.get(activityThread);
}
throw new Exception(
"Failed to get ActivityThread.sCurrentActivityThread");
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public Instrumentation.ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options, UserHandle user) {
Object result = RefInvoker.invokeMethod(instance, Instrumentation.class.getName(),
Method_execStartActivity, new Class[] { Context.class, IBinder.class, IBinder.class, Activity.class,
Intent.class, int.class, Bundle.class, UserHandle.class }, new Object[] { who, contextThread,
token, target, intent, requestCode, options, user });
return (Instrumentation.ActivityResult) result;
}
/**
* Private constructor.
*
* @param config the {@link Config} instance. If {@code null} one will be created.
* @param instrumentation the {@link Instrumentation} instance
* @param activity the start {@link Activity} or {@code null}
* if no Activity is specified
*/
private Solo(Config config, Instrumentation instrumentation, Activity activity) {
if(config.commandLogging){
Log.d(config.commandLoggingTag, "Solo("+config+", "+instrumentation+", "+activity+")");
}
this.config = (config == null) ? new Config(): config;
this.instrumentation = instrumentation;
this.sleeper = new Sleeper(config.sleepDuration, config.sleepMiniDuration);
this.sender = new Sender(instrumentation, sleeper);
this.activityUtils = new ActivityUtils(config, instrumentation, activity, sleeper);
this.viewFetcher = new ViewFetcher(instrumentation, sleeper);
this.screenshotTaker = new ScreenshotTaker(config, instrumentation, activityUtils, viewFetcher, sleeper);
this.dialogUtils = new DialogUtils(instrumentation, activityUtils, viewFetcher, sleeper);
this.webUtils = new WebUtils(config, instrumentation,viewFetcher, sleeper);
this.scroller = new Scroller(config, instrumentation, viewFetcher, sleeper);
this.searcher = new Searcher(viewFetcher, webUtils, scroller, sleeper);
this.waiter = new Waiter(instrumentation, activityUtils, viewFetcher, searcher,scroller, sleeper);
this.getter = new Getter(instrumentation, activityUtils, waiter);
this.clicker = new Clicker(activityUtils, viewFetcher,sender, instrumentation, sleeper, waiter, webUtils, dialogUtils);
this.setter = new Setter(activityUtils, getter, clicker, waiter);
this.asserter = new Asserter(activityUtils, waiter);
this.checker = new Checker(viewFetcher, waiter);
this.zoomer = new Zoomer(instrumentation);
this.swiper = new Swiper(instrumentation);
this.tapper = new Tapper(instrumentation);
this.illustrator = new Illustrator(instrumentation);
this.rotator = new Rotator(instrumentation);
this.presser = new Presser(viewFetcher, clicker, instrumentation, sleeper, waiter, dialogUtils);
this.textEnterer = new TextEnterer(instrumentation, clicker, dialogUtils);
this.systemUtils = new SystemUtils(instrumentation);
initialize();
}
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Fragment target,
Intent intent, int requestCode) {
PluginIntentResolver.resolveActivity(intent);
Object result = RefInvoker.invokeMethod(realInstrumention, android.app.Instrumentation.class.getName(),
"execStartActivity", new Class[] { Context.class, IBinder.class, IBinder.class, Fragment.class,
Intent.class, int.class }, new Object[] { who, contextThread,
token, target, intent, requestCode });
return (ActivityResult) result;
}
private void startActivity() {
if (launched)
return;
Instrumentation instrumentation = getInstrumentation();
Intent intent = new Intent(getInstrumentation()
.getTargetContext(), AndroidNativeActivity.class);
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity = instrumentation.startActivitySync(intent);
launched = true;
instrumentation.waitForIdleSync();
sleep(5000);
}
@Before
public void setUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
MockFyberApplication app = (MockFyberApplication) instrumentation.getTargetContext().getApplicationContext();
TestApplicationComponent component = (TestApplicationComponent) app.getComponent();
component.inject(this);
// Set up the stub we want to return in the mock
Offer offer = new Offer();
offer.setTitle(TEST_OFFER_TITLE);
offer.setTeaser(TEST_OFFER_TEASER);
offer.setPayout(TEST_OFFER_PAYLOAD);
expectedOffers = new Offer[1];
expectedOffers[0] = offer;
// put the test offer in a test api result
expectedResult = new OfferResponse();
expectedResult.setOffers(expectedOffers);
expectedResult.setPages(1);
expectedResult.setCode(Constants.CODE_OK);
// Set up the mock
when(api.getOffers(any(String.class), any(Integer.class), any(String.class), any(String.class), any(String.class), any(Long.class), any(String.class), any(String.class), any(Boolean.class), any(String.class), any(String.class), any(Integer.class), any(Integer.class), any(String.class)))
.thenReturn(Observable.just(expectedResult));
when(valueManager.isConnected()).thenReturn(true);
when(valueManager.getAdId()).thenReturn("adId");
when(valueManager.getAdIdEnabled()).thenReturn(false);
when(valueManager.getApplicationId()).thenReturn(123);
when(valueManager.getApiKey()).thenReturn("apiKey");
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Instrumentation instrumentation = getInstrumentation();
final Context testContext = instrumentation.getContext();
final Resources testRes = testContext.getResources();
final String testPackageName = testRes.getResourcePackageName(R.string.empty_string);
mTextsSet.setLocale(TEST_LOCALE, testRes, testPackageName);
}
public static void injectInstrumentationHook(Instrumentation instrumentation) throws Exception {
Object activityThread = getActivityThread();
if (activityThread == null) {
throw new Exception("Failed to get ActivityThread.sCurrentActivityThread");
}
//AtlasHacks.ActivityThread_mInstrumentation.on(activityThread).set(instrumentation);
AtlasHacks.ActivityThread_mInstrumentation.set(activityThread,instrumentation);
}
@Test
public void testNavigateInOnResume() throws Throwable {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Intent intent = new Intent(instrumentation.getContext(),
ImmediateNavigationActivity.class);
final ImmediateNavigationActivity activity = mActivityRule.launchActivity(intent);
instrumentation.waitForIdleSync();
NavController navController = activity.getNavController();
assertThat(navController.getCurrentDestination().getId(), is(R.id.deep_link_test));
}
private BufferedReader openFile(Instrumentation instr, String filePath) throws IOException {
// If we are running as an instant app, then read the file through the shell
// since the APK is in the targetSandboxVersion="2" with restrictive SELinux
// policy which prevents reading from /data/local.
final boolean isInstantApp =
Build.VERSION.SDK_INT >= 26 && instr.getContext().getPackageManager().isInstantApp();
return new BufferedReader(
isInstantApp
? new InputStreamReader(
new AutoCloseInputStream(
instr.getUiAutomation().executeShellCommand("cat " + filePath)))
: new FileReader(new File(filePath)));
}
/**
* Constructs this object.
*
* @param activityUtils the {@code ActivityUtils} instance
* @param viewFetcher the {@code ViewFetcher} instance
* @param sleeper the {@code Sleeper} instance
*/
public DialogUtils(Instrumentation instrumentation, ActivityUtils activityUtils, ViewFetcher viewFetcher, Sleeper sleeper) {
this.instrumentation = instrumentation;
this.activityUtils = activityUtils;
this.viewFetcher = viewFetcher;
this.sleeper = sleeper;
}
public static Instrumentation getInstrumentation() throws Exception {
Object activityThread = getActivityThread();
if (activityThread == null) {
throw new Exception("Failed to get ActivityThread.sCurrentActivityThread");
}
//return (Instrumentation)AtlasHacks.ActivityThread_mInstrumentation.on(activityThread).get();
return (Instrumentation)AtlasHacks.ActivityThread_mInstrumentation.get(activityThread);
}
private static AppInstrumentation create() {
Instrumentation instrumentation = ActivityThread.mInstrumentation.get(VirtualCore.mainThread());
if (instrumentation instanceof AppInstrumentation) {
return (AppInstrumentation) instrumentation;
}
return new AppInstrumentation(instrumentation);
}
public void captureImages(String reportTag, Instrumentation inst)
{
int total_num_of_images = CameraStressTestRunner.mImageIterations;
Log.v(TAG, "no of images = " + total_num_of_images);
//TODO(yslau): Need to integrate the outoput with the central dashboard,
//write to a txt file as a temp solution
boolean memoryResult = false;
KeyEvent focusEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS);
try
{
testUtil.writeReportHeader(reportTag, total_num_of_images);
for (int i = 0; i < total_num_of_images; i++)
{
Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
inst.sendKeySync(focusEvent);
inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
testUtil.writeResult(i);
}
} catch (Exception e)
{
Log.v(TAG, "Got exception: " + e.toString());
assertTrue("testImageCapture", false);
}
}
/** Sets the text of the provided {@link TextView} widget on the UI thread. */
public static void setText(Instrumentation instr, final TextView view, final String text) {
runOnMainSyncWithTimeout(
new Callable<Void>() {
@Override
public Void call() {
view.setText(text);
return null;
}
});
instr.waitForIdleSync();
Assert.assertEquals(text, view.getText().toString());
}
private void applyActivityResult(Instrumentation.ActivityResult result) {
String[] permissions = result.getResultData().getStringArrayExtra(EXTRA_REQUEST_PERMISSIONS_NAMES);
int[] resultPermissions = result.getResultData().getIntArrayExtra(EXTRA_REQUEST_PERMISSIONS_RESULTS);
for (int i = 0; i < permissions.length; ++i) {
if (resultPermissions[i] == PackageManager.PERMISSION_GRANTED) {
grantFakePermission(permissions[i]);
} else {
revokeFakePermission(permissions[i]);
}
}
}