Android unit-testing when activity has animation - android

I'm writing a unit tests for activity with animation. Animation is simple rotation of spinner drawable with infinite duration(splash screen).
When i start unit tests, every test seems to wait until animation is finished, so they stucks infinte, When i set duration to 1 it all passes, cause animation ends quickly.
How can I override that, so tests don't wait for animation ending?

I assume that you intend to test behavior other than the animation.
You will probably benefit the most from moving the animation off the path of the code you want to test. This means moving the other code--code that doesn't depend on the animation--out of the Activity. If not out of the Activity, then, at least out of the Activity lifecycle methods (onCreate(), ...). You can then check this behavior without running the behavior at all. Even better would be to run the behavior without starting the Activity at all (don't call onCreate()).
The problem you encountered is a special case of what happens when you put your code directly into a framework extension point: your code then becomes intermingled with the framework and you get stuck running something that you don't care about in order to run the part that you do care about. So don't do that. Put your code in classes that don't depend on the framework, then use the framework extension point (the Activity in this case) to connect Android to your code. The Activity knows that your code exists; your code remains blissfully ignorant of Android. Now things like your animation can't get in the way.

Related

Mocking presenter cause integration test to dump

Recently i've started covering my project with integration tests where mockito provides presenter instances to verify whether or not my views calling presenter methods properly during their events.
The issue was on the screen which has invisible ProgressBar and RecyclerView. Presenter of that screen have been loading data for that RecyclerView and controlling visibility of ProgressBar. When i replaced it with mock (used Mockito) it caused corresponding tests to totally stuck with error after a while:
Could not launch intent Intent { act=android.intent.action.MAIN flg=0x14000000
cmp=com.example.kinopoisk/com.example.mvp.view.activity.MainActivity } within 45 seconds.
Perhaps the main thread has not gone idle within a reasonable amount of time?
There could be an animation or something constantly repainting the screen.
Or the activity is doing network calls on creation? See the threaddump logs.
For your reference the last time the event queue was idle before your activity launch request
was 1476191336691 and now the last time the queue went idle was: 1476191336691.
If these numbers are the same your activity might be hogging the event queue
But activity was successfully running and was accessible for all user events like clicks etc.
How do you think, what cause a problem?
This is a question for community knowledge base only, i've found answer myself.
The explanation is in that line of error code: There could be an animation or something constantly repainting the screen.
When i had replaced presenter with mockito's one, it stopped controlling progress bar as well. The initial state of it was View.VISIBLE, so that was cause test to hadn't been able to connect.
The solution was just set initial state of ProgressBar to View.GONE, but found it was a bit of headache for me.

Structure App using Methods/threads

I know this is a fundamental java question, but i am relatively new to java.
How do i structure the code attached (monitoring) within a UI.
What the code does is just log values, and if certain conditions are activated, it does stuff. The loop () method does pretty much everything, but there are a few small things done by the preceding methods.
Let's say in the UI, I have a 'calibrate' button, which if pressed, runs a calibrate method/thread, and a 'monitoring' button which runs a different 'monitoring' method/thread. The problem is, these methods/threads are at the moment defined in their own project as classes. My ideas are along the lines that i need to construct these 2 classes and then call the methods i want from them in response to UI interaction. However, if i call just the method, for example:
if (monitoring button) {
monitoring.method1;
}
this means that i can't do anything in parallel to that, so I need to make what happens in those classes into thread somehow.
Cheers,
Rokky
Take a look at AsyncTask, this will allow you to run logic in a background thread, leaving your activity free to respond to the user.

ResourceNotFound on layout inflation

My app may launch a sub-activity for a specific purpose. When that activity finishes, I get the results in onActivityResult. These results are then processed in the subsequent onResume. This consists of a setContentView and also starting an AsyncTask that puts up a ProgressDialog.
This all works well when initiated the normal way, which is via a user request (i.e., menu selection) after the app is up and running. However, under some conditions I need to do this right as the app is starting up, so I initiate this sequence right from my onCreate. What then happens is that I get fatal ResourceNotFound errors within any o/s call that implicitly calls the layout inflater. I got around this with setContentView by pre-inflating the view in my onCreate method, but the AsyncTask's onPreExecute still fails on ProgressDialog.show() as it "fails to find" Android's own progress_dialog.xml!
Anyone know what's happening here?
I suspect it's something to do with the timing, where this is occurring before the main activity has even had a chance to display its screen. These calls are all being made on the main UI thread, but maybe something hasn't completed within the o/s under these conditions.
As a closeout, the problem turned out to be totally unrelated to what I described in my post. Turns out it was due to blindly using some code that had been posted in some online forum showing how to get and use AssetManager. Trouble is, at the end of the block of code he had put "assMan.close()". Well, this closes the asset manager for the entire activity and resources can no longer be accessed!
It took a while to find it since it was not something that I did via my own understanding.

How do you force an orientation change in an Android Instrumentation test?

I'm writing some acceptance tests for an application using the ActivityInstrumentationTestCase2 class. I want to cause an orientation change from within the test to ensure that a number of things happen. Among these things are ensuring that Activity state is preserved, but also I'd like to ensure that the appropriate layout for the orientation is used.
I know I can simply test the onSaveInstanceState/onRestoreInstanceState/onPause/onResume/etc. methods to make sure instance state is preserved. However, I was wondering if there is actually a mechanism for causing an orientation change event?
Would this involve injecting some kind of motion event to trick the device/emulator into thinking that it has been rotated, or is there an actual method for this provided by the Instrumentation?
Thanks & Cheers!
You do not actually have to use Robotium for this at all. In fact, if you view the source of Robotium all it is doing when you call
solo.setActivityOrientation(Solo.LANDSCAPE);
is
myActivity = this.getActivity(); // In your setUp method()
...
myActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
As AndrewKS wrote you can use
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
assertTrue(...);
to request an orientation change. But the rotation itself is executed asynchronous. To really test the state after the orientation change you need to wait a short time after the request:
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Thread.sleep(50); // depends on performance of the testing device/emulator
assertTrue(...);
Use Robotium for it.
There is a class called Solo, using which you can change orientation by just calling a method:
solo.setActivityOrientation(Solo.LANDSCAPE);
That's it! Your orientation would get changed.
You can google Robotium and obtain its jar and add it to your Test project. The Robotium site also gives an example Test project on Android's Notepad App (which is available as a sample project with Android SDK) which shows how powerful it is and how easily it could be used.

Same Activity called twice... Issue with Multiple AsyncTasks?

I have three simultaneous instances of an AsyncTask for download three files. When two particular ones finish, at the end of onPostExecute() I check a flag set by each, and if both are true, I call startActivity() for the next Activity.
I am currently seeing the activity called twice, or something that resembles this type of behavior. Since the screen does that 'swipe left' kind of transition to the next activity, it sometimes does it twice (and when I hit back, it goes back to the same activity). It's obvious two versions of the activity that SHOULD only get called once are being put on the Activity stack.
Could this be from both onPostExecute()s executing simultaneously and both checking the flags each other set at the exact same time? This seems extremely unlikely since two processes would have to be running line-by-line in parallel...
*****EDIT*** A lot removed from this question since I was way off in what I thought was wrong. Nonetheless I found the answer here quite useful, so I have edited the question to reflect the useful parts.
The only way I can find that this is
possible is if both AsyncTasks'
onPostExecute() executed SO
simultaneously that they were
virtually running the same lines at
the same time, since I set the
'itemXdownloaded' flag to true right
before I check for both and call
startActivity().
Since they are both called on the main application thread, that's not possible, unless you're doing something really strange.
I would introduce some Log calls to ensure that you are not misreading the symptoms.
Beyond that, it is difficult to see any problems from your pseudocode, unless there's a possibility of other downloadID values beyond the three shown. For example, if there is a DL4, and DL4 completed after DL1 and DL2, DL4 would trigger your activity.

Categories

Resources