Espresso doesn't perform click on a Dialog for enabling GPS generated on this code:
rae.startResolutionForResult(
context,
Constants.GPS_REQUEST
)
I haven't created this dialog so is not part of my "screen" nor "app", it's generated by the system or request to solve the gps resolution.
So I check if gps is enabled, if isn't then this is my line of code to press it:
onView(withText("OK")).perform(click())
But it doesn't work since it looks like Espresso keeps waiting for something to happen and then it crashes alone:
androidx.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
It doesn't matter if i set random words on the withText("Random words sjdj") it won't work because "it's waiting"
I thought about performing a click on coordinates but that looks like a flakky test because of the height and width and might not be accurate at all (I'm saying it from ignorance) and probably won't work because espresso is waiting.
Edit 1:
If I wait until test stops by itself it throws me the next error:
androidx.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
I guess Activity is onPause or something like that and is waiting for the dialog resolution?
But if i set the location good, test works as it should
What can I do to accept/cancel this dialog?
I don't want to be manually checking if location is on. I want to test that everything works as it should.
Here's an image of the actual screen
Found someone who had the same problem as me and the solution was to use an UiAutomator which use the UI of the Device! which Espresso can't reach!
Solution
Related
When a user signs into my application, an alert dialog appears if it is their first time.
Otherwise, it does not appear.
This makes it tricky when I am trying to write UI tests.
Since the alert dialog appears conditionally, I cannot close it using:
onView(withId(android.R.id.button1)).perform(click())
as I have seen suggested on other posts.
However, if it does appear and I do not close it within my test, the test is blocked from moving on (as it does not recognise any other view ids) and fails.
Does anyone have any recommendations about how I might handle this?
Thank you!
However, if it does appear and I do not close it within my test, the
test is blocked from moving on (as it does not recognise any other
view ids) and fails.
Does anyone have any recommendations about how I might handle this?
Whenever you write a test, you must ensure that the required conditions are in place to reliably and consistently run the test in question. This is the "arrange" portion of the Arrange, Act, Assert idiom.
Therefore, if you're testing a flow that involves the dialog, you must arrange the test to set up the condition under which that dialog shows.
If you're testing a flow that does not involve the dialog, you must arrange the test to set up the condition under which the dialog does not show.
You have not posted code so I have no idea what the "condition" for showing the dialog is, but basically you need to do something in your test that ensures that condition is false if you don't want the dialog or true if you do. Maybe this is setting a shared preference?
So for example, your test might look generally like this:
#Test
fun myAwesomeTest() {
// Arrange - do something to ensure dialog does not show
SomeHelperClass.setConditionToShowDialog(false)
// Act - do actions knowing the dialog will not show
onView(withId(R.id.awesomeId)).perform(click())
// Assert
onView(withId(R.id.duperId)).check(matches(isVisible()))
}
Again, without specifics of your code, it's hard to give more detail but hopefully that is enough to get you going.
Hope that helps!
It sounds like (but I have to guess since you didn't provide more details on this) you're controlling the showing of that "first time" dialog based on a value that you store locally, maybe with PersistentState.
If that is the case, you can control that value directly from your Espresso tests, and thereby make the state of your tests be as expected.
Also, just a side note -- I would strongly advise against having dependent Espresso tests, which it sounds like you have, based on "if it does appear and I do not close it within my test, the test is blocked from moving on".
Your tests must be able to be executed in random order and pass.
When using the intended(IntentMatcher) from the Android Espresso API, is it possible to do this twice in the same Activity?
So for example I click a button which starts an Activity for result. I check that this Activity has fired using intended(IntentMatcher). That works.
However, when I get the result, I want to fire off an Intent for a different Activity. In this case just a local Activity in the same app package with no result.
When I do this manually in the app it works fine, but Espresso can't seem to detect the second Intent in my test. What I am I missing or is this not possible? Alternatively, how should I be doing it? Maybe my design is bad.
When I do the check I'm trying this:
intended(toPackage(<packageName>));
intended(hasComponent(hasClassName(<className>)));
The first line matches but not the second one. And even if the second line is not completely correct it never seems to show anything in the error log about the second Activity I'm actually starting.
Another thing adding to the confusion is that two intents are definitely being fired as it shows that in the log. They both seem to be the same one but with slightly different details - one is a package, one is a component. Does it log the result from the first Intent as an Intent in itself? Sounds unlikely but where is this other intent coming from? I know it's not the second Activity I'm launching as it still fires even when that Activity isn't called (when the first Intent result is a fail).
I've also considered that maybe it's not getting detected because it's not waiting long enough for the second intent to fire. If that were the case, what would I do about that? I don't see much talk about handling time sensitive things in Espresso. Like checking if a progress bar is shown but then hidden again while not pressing anything. How do you do that? Maybe it's the same answer.
Any help appreciated!
Ok I found the problem. My IdlingResource wasn't working.
After fixing that it works like a charm :)
So this is the problem:
The activity starts - and in onResume() does some work in a background thread which populates a listview. This is being done whilst a progress dialog is shown as per the following images:
That work completes - and the progress dialog is told to .dismiss();
The dialog disappears - my listview can be seen , however the activity looses focus - and sort of dims into the background. This forces me to press home, and force close before reopening - as per this example:
This problem happens EVERY single time the application runs for the first time. Runs after the app locks are always successful and the problem is never evident again! As you can see in the picture - everything has been darkened - however after force closing, reopning the view responds as I would expect with everything working as normal. There is nothing in the logcat to help me diagnose the problem - and all code appears to function correctly.
Please help!
A code dump from the Replay List activity section is here : http://pastebin.com/YG59VFPu - it will probably be tough to follow - but on first run it will do a dropbox login, which works - then it will do findAllReplays() - which also works - eventually ending up in returnres runnable which results in the dialog being dismissed - which also works - which is where the issue seems to happen...
Ok So eventually I did the following.
I created an AsyncTask - which on pre execute created the dialog in the same way, on the end of doinbackground it closed the dialog because my onPostExecute never executes - however dismissing the dialog at the end of doinbackground works. And so that is what I am using, which has essentially solved my problem.
To keep your screen on you can set a flag in your activity
this.getWindow().
addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
It will keep your screen on until current activity is in foreground.Or you can use wake lock if you are doing some thing in background and want to keep your screen on before ,during or after background work.
Power Manager to keep screen on.Never forget to mention appropriate permission.
Although you solve your problem before my answer but hope it help you to clear concept to keep screen on.
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.
(Note that I've searched online for the warnings I'm describing below, and have come up with next to nothing about them.)
I'm working with API level 10. I have a preference screen (XML-based), and one of the options in there creates a custom ListActivity as follows:
PreferenceActivity contains an option that creates a...
ListActivity which is a dialog that employs...
setOnClickListener() which contains an onClick() method that (right before calling finish()) will startActivity() a new Intent...
sub-Activity which starts up an...
AsyncTask which does variable time work which when done calls...
onPostExecute() which calls finish()
The thing is, it works... but I'm getting a raft of warning starting with:
10-16 21:59:25.010: WARN/WindowManager(170): Rebuild removed 4 windows but added 3
10-16 21:59:25.010: WARN/WindowManager(170): This window was lost:.....
Curiously, this raft of warnings ONLY comes up when the task executes quickly! When I added a Thread.sleep() call to my AsyncTask to artificially inflate its runtime it worked and threw no warnings whatsoever. In fact, as long as it takes more than (roughly) 500 ms to run it works fine. (Note that I tried using startActivityForResult() to no greater effect - the same problem occurs.)
The goal is that the user selects a preference item, they change its setting, some processing takes place, and then the user is left back at the preference menu they started on.
I'm betting it's a race condition... the order in which the windows are destroyed varies depending on that run-time... and I get the impression that when the sub-Activity closes before its parent ListActivity the warnings get thrown. But sprinkling a 1s sleep() in isn't a reasonable solution unless this is some sort of Android bug (unlikely, but then again I've reproduced a couple of those today already).
So, what's the flaw in this my that leads to this stream of warnings? It'd be nice to say "on preference, do this, then do that, then finish" but I think what I'm doing is the equivalent. Maybe not... thoughts?
Edit: I decided to try doing this ListActivity as a custom Dialog... that was one of the more painful things I've tried to do lately (getApplication() doesn't work and lots of other things seem to go wrong... it may be inexperience to some extent, but dialogs really weren't meant for this either...
Try the following two things:
Dismiss your dialog before calling finish() on its parent activity (PreferenceActivity).
Make sure you are starting your AsyncTask later in the sub-activity's lifecycle. I'm specifically thinking you should launch it in onResume().
My best guess is that the AsyncTask is calling finish() on the sub-activity, before the sub-activity has had a chance to fully start up. Why that would matter? I'm not sure. Something to try though. Good luck!