In my instrumentation/unit test, I'd like to verify that an Activity's method is called in onCreate (when app is launched AND while it is already open) and onNewIntent.
I've tried ActivityTestRule, but I ran into two problems:
I have to invoke onNewIntent on the ui thread, because it modifies the view. So I'm forced to do something like Thread.sleep to wait for the task to finish
It's impossible to spy the activity in the rule without hacking the library
I've also looked into Robolectric, but it seems like it has a reputation for being flaky and slow.
Any suggestions for possible approaches with Espresso or Mockito or a different testing framework?
Related
I have some very granular test methods and it would be a total waste of time to start the Activity under test each time. For this it would be very handy to just start it once. Unfortunately Espresso/JUnit finishes all Activities after each test method. Is there a simple way around this?
There is no way to do that. Espresso test cases start activity for test. Espresso is designed like that.
If you want to test specific scenarios you can have separate methods which you can used it in different tests.
For more info :
Why does Espresso leave the app after the test has finished? How to stop it from doing that
In the app I have an activity which has launch mode as singleTask. There are number of use cases which pass through this activity and hence it's called number of times. On stress testing the app by running monkeyrunner script and calling this activity every few seconds causes ANR's.
I guess, the way it's designed where most of the use cases pass through this activity is not correct but I am not in a position to change this design.
Is there anyway ANR's can be suppressed? I mean, adding UI operations to event queue so that it doesn't block main UI thread and doesn't give ANR.
It is unclear from the question what your activity is (or should be) doing. Probably you need a service instead.
It is common to perform time-consuming operations in background threads and deliver the results to the UI thread.
You may use the classes Handler/Looper (it it easir to send Runnables rather than messages), or use an AsyncTask. The AsyncTask is nevertheless tricky, this is discussed here: Is AsyncTask really conceptually flawed or am I just missing something? . AFAIK Google tried to fix the typical bugs and made the new behavior incompatible with the old one (namely, I have seen some misbehavior on the newer Androids that may be explained by the assumption that since some version threads doing asynctask jobs get killed after the activity that started them goes out of the screen).
I can guess that singleTask is your way to fight the fact that an activity dies when the screen turns, and a new one comes. I suggest you use singletons (they survive screen rotation but do not survive a process restart, one more thing that sometimes happens in Android). (The user switches to an app like Camera, takes a big photo, returns back -- and the activity is restarted because Camera needed memory. Have seen this in practice, but that time I did not try to find out if the whole process was restarted.)
Anyway, please add logging telling you when your activity in entered and left, including onNewIntent() and other lifecycle functions (to be on the safe side, I recommend to print the thread names as well). Then you will probably see what is going on.
Hiii i am testing a test method in which i want after a pressing a button my activity should alive so that i can see next test cases in that activity,but unfortunately my activity get killed after running the test case .is there any way to keep the activity alive.if there code line please let me inform.
I cannot be sure without seeing your code, but i am guessing either in the testcase, or the setup() and tearDown() methods you are going to have to been calling a method such as finishOpenedActivities() which closes all the activities you have open. removing this line will keep the activity open.
Having said that it is typically best practice to have your test cases start from a clean state because having test cases that rely on ordering means that if one fails all the others fail even if that functionality does work plus you have to do slightly hacky things in order to get them to all run in the order you want.
I dug into the source code a bit and found that the tearDown() method, as implemented in ActivityInstrumentationTestCase2, will make a call to finish() on your current activity. So even if you don't explicitly finish() you Activity in your implementation of this method, it will be done when calling super. However, per the source code documentation: removing the call to super in tearDown() can cause a memory leak if you have a non-static inner class, and, perhaps more importantly for your case, the running Activity seems to still be killed once the test is completed. Even if you have an empty implementation of tearDown(), it seems as though the Activity Under Test gets finished at the end of the run. As of right now, I don't know of a way to avoid this.
As an alternative based on your comment for #Paul Harris's answer, Robotium has many methods that allow you to wait for something to happen. You may want to look into waitForText() or waitForView(), which can take a timeout as a argument, to have Robotium pause while your button click is performing some action. Hope this helps!
My instrumentation is launching an activity to instrument it, but I can't seem to find an elegant way to tell when it's safe to start sending it my MotionEvent's. At the moment, I'm continually sending it MotionEvent's, and catching the SecurityException's that get thrown when the wrong application receives them.
The problem with this approach is that when the first event gets through, the application responds to it, so this method is not without side effects...
I was thinking of trying to do something with UID's, but I don't know where to look for that.
You might be able to leverage the standard Android lifecycle methods that get called on your Activity. You could set an 'infront' flag in onResume(), and clear it in onPause(). Then your instrumentation test just checks that flag to know when it's safe to send MotionEvents.
If you don't want to pollute your app by putting in code specifically for test purposes, create a subclass, override onResume/onPause, set the flags, and call super.
How do you create unit tests for an Android activity that starts async tasks in onCreate? I would like to test the result of these tasks.
It is hard to write tests for a lot of Android functionality, since you can't instantiate classes like Activity outside of Android.
You might be better off doing a true unit test...test the function whose behavior you care about in isolation. Don't try to test it in the context of async task, activity, etc.
You might need to refactor your code a little bit to be able to do that, but its worth it to have testable code!
Running true units tests as mentioned in Cheryl's answer would be ideal. However if you still find yourself wanting to test the result AsyncTasks or any long running asynchronous operation in an Activity Test, Espresso is the silver bullet.
Espresso automatically waits for AyscTasks to complete and the developer can manually tell Espresso to wait for custom background tasks running via the IdlingResource APIs.
Here's a tutorial to help you get started: http://blog.sqisland.com/2015/04/espresso-custom-idling-resource.html
IdlingResource documentation: http://developer.android.com/reference/android/support/test/espresso/IdlingResource.html