I am writing my test cases for my app however have come into some minor problems. Many of my test cases have SystemClock.Sleep calls in them, in order for the view to load all the data and display it on the screen. However the number of sleeps to do this has increasingly grown causing the time of these tests to be even longer.
Here is an example of one of these tests
#Test
public void testSearch() {
ExtensionForExpresso.signUp();
SystemClock.sleep(17000);
onView(withId(R.id.menu_offer_search)).check(matches(isDisplayed())).perform(click());
SystemClock.sleep(5000);
onView(withId(R.id.menu_search)).check(matches(isDisplayed())).perform(typeText("Pizza"));
SystemClock.sleep(17000);
onView(withId(R.id.searchSectionSeeAllButton)).check(matches(isDisplayed())).perform(click());
SystemClock.sleep(15000);
onView(withId(R.id.searchResultsRecyclerView)).check(matches(isDisplayed())).perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
}
Is there an alternative to sleep that will wait for view to appear? Or are there any methods or functions I can add in to reduce the amount of SystemClock.sleep calls?
First, try to disable animation on your device/emulator using adb shell or implement the Espresso Idling Resource in your Android project: http://matgom.com/tutorial/2016/02/21/IdlingResource.html
I would recommend you to implement an IdlingResource and Disable the system animations first. The easiest way to disable system animations is this.
There is no need to use the SystemClock.sleep() method. Instead you could implement a custom sleep method like this:
public void waitFor(int seconds) {
seconds = seconds < 0 ? 0 : seconds;
while (--seconds >= 0) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Then you could call it in your test like: waitFor(2); // 2 second wait
Related
I know Android UI is not really meant for executing functions and waiting for them to finish, however, I think there are use cases were it is required, like networking.
My problem is, I want to run a series of network operations that rely on each other and take a bit more time than the split second it takes to the next execution, so some waiting is in order:
Start hotspot
Get network interfaces and IP
Start socket
Initially I tested that all is working using buttons, then it waited between my button presses. But now I'd like to automatize it. I googled but all I found are solutions with Async task, which is deprecated. I tried with threads and join, but that usually causes weird crashes in the runnable, and it is not very elegant. I wonder if there is another solution?
The best thing you can do with SDK it's use Executors to run your work in background sequentially
val newSingleThreadExecutor = Executors.newSingleThreadExecutor()
newSingleThreadExecutor.execute {
// 1...
}
newSingleThreadExecutor.execute {
// 2...
}
But if you want to touch the UI from background should create handler check if view's not null
val handler = Handler(Looper.myLooper()!!)
newSingleThreadExecutor.execute {
handler.post {
view?.visibility = View.GONE
}
}
How about something like this?
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startHotspot();
getNetworkInterfaceAndIP();
startSocket();
}
}, 300);
Note: The app I am working on is for PERSONAL use only. I am trying to collect data for my master thesis.
I am trying to start more than 128 AsyncTasks at once, which fails because of the ThreadPoolExecutor. I've seen some answers why it is not working, but no real answer of how to implement it correctly.
As I have a lot of time for uploading my stuff I was considering to just put my MainActivity to sleep before starting the next upload, which does not seem to work as well.
for (IrisResult s : results) {
try {
Thread.sleep(1000);
mAzureTableManager.addIrisResult(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The method addirisResult() actually starts the AsyncTask by protected Void doInBackground(Void... params) {
I am looking for the SIMPLEST solution, not for the best approach!
yourAsyncTask.executeOnExecutor(yourThreadPoolExecutor, params);
And increase your pool size:
yourThreadPoolExecutor.setMaximumPoolSize(size);
Sets the maximum allowed number of threads. This overrides any value set in the constructor. If the new value is smaller than the current value, excess existing threads will be terminated when they next become idle.
android.developer.com - ThreadPoolExecutor#setMaximumPoolSize(int)
android.developer.com - AsyncTask#executeOnExecutor(Executor, Params...)
as an example:
yourThreadPoolExecutor = Executors.newCachedThreadPool();
yourThreadPoolExecutor.setMaximumPoolSize(256);
yourAsyncTask.executeOnExecutor(yourThreadPoolExecutor, params);
I am using an AsynchTask to host a simulator that runs indefinelly and posts the results after each simulation step.
Limiting the simulation loop in background at a maximum of 25Hz, and only calling a javascript function with the results, it works "fine".
Apart from updating a webgl model in a browser, what looks fast enough, I have two more things to update from the Android UI: the FPS indicator and the panel with TextViews representing some of the values. If we forget about the FPS:
The onProgressUpdate() function is already limited to be called at 25Hz, to refresh the model. Now I use another time variable to limit, inside this method, the call to another method that updates the UI panel textViews. It is limited to 1Hz, less than what I actually wanted but fast enough for the kind of information. The method is as clean as possible, all the views are previously loaded to a variable that I keep to not load them every time.
What is the effect: looks like updating 5 textViews takes like one second where all the UI freezes, the touch moves are very very laggy...
I decreased the priority of the background task with:
#Override
protected Boolean doInBackground(ModelSimulation... params) {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
...
And used Thread.yield() at the end of the doInBackground method. This improves the behavior to what I explained, without these commands, the behavior is even worst.
My questions are:
-Can I reduce even more the priority if instead of using a background task I use a handler and my own Thread?
-Will a service improve the behavior of the UI?
-Why updating 5 textViews takes so long compared with calling a javascript function that finally will have to use the gpu to change the webgl model?
-Is Android not prepared in any sens to do dynamic applications? How applications like the ones to test sensors update so fast the UI? because there are not standar components like the textViews? (like browser going faster than a textView)
Note: even reducing the refreshing limitations, it produce a laggy effect every time the HUD is updated. In fact I talk about 5 textViews but only updating the FPS indicator produces the same pause. Looks like the only fact of having to switch to the UI thread already consumes this time.
Edit 1:
#Override
protected Boolean doInBackground(ModelSimulation... params) {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
if(simulator.getSimulatorStatus().equals(SimulatorStatus.Connected)){
try {
while (true){
//TODO Propagate
long dur = (System.nanoTime()-time_tmp_data);
if(dur<Parameters.Simulator.min_hud_model_refreshing_interval_ns){
try {
long sleep_dur = (Parameters.Simulator.min_hud_model_refreshing_interval_ns-(System.nanoTime()-time_tmp_data))/1000000;
if(sleep_dur>0){
Thread.sleep(sleep_dur);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
time_tmp_data = System.nanoTime();
SpacecraftState sstate = propagate();
int progress = (int)((extrapDate.durationFrom(finalDate)/mission.sim_duration)*100);
if(sstate!=null){
SimResults results = new SimResults(sstate, progress);
simulator.getSimulationResults().updateSimulation(results.spacecraftState, results.sim_progress);
publishProgress();
}
if(isCancelled())
break;
Thread.yield();
}
} catch (OrekitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
simulator.showMessage(simulator.getContext().getString(R.string.sim_orekit_prop_error)+": "+e.getMessage());
}
}
return true;
}
#Override
protected void onProgressUpdate(Void... values) {
//Update model by push
simulator.getSimulationResults().pushSimulationModel();
//Update GUI HUD
if(time_tmp_gui==0 || (System.nanoTime()-time_tmp_gui)>Parameters.Simulator.min_hud_panel_refreshing_interval_ns){
time_tmp_gui = System.nanoTime();
simulator.getSimulationResults().updateHUD();
}
}
If I comment the line simulator.getSimulationResults().updateHUD(); or directly the contents of the method, it works "fine". And this method is only changing some textviews text:
public synchronized void updateHUD(){
//Log.d("Sim",System.currentTimeMillis()+": "+"pre update gui 1");
activity.runOnUiThread( new Runnable() {
#SuppressLint("ResourceAsColor")
public void run() {
if(view != null){
if(panel_time != null)
panel_time.setText(info.time.replace("T", " "));
if(panel_progress != null)
panel_progress.setProgress(info.progress);
if(panel_vel != null){
panel_vel.setText("Vel. "+String.format("%.2f", info.velocity)+" Km/s");
if(info.velocity>config.limit_velocity)
panel_vel.setTextColor(activity.getResources().getColor(R.color.panel_limit));
else
panel_vel.setTextColor(activity.getResources().getColor(R.color.panel_value));
}
if(panel_accel != null){
panel_accel.setText("Accel. "+String.format("%.2f", info.acceleration)+" Km/s2");
if(info.acceleration>config.limit_acceleration)
panel_accel.setTextColor(activity.getResources().getColor(R.color.panel_limit));
else
panel_accel.setTextColor(activity.getResources().getColor(R.color.panel_value));
}
if(panel_radium != null)
panel_radium.setText("Orbit radium: "+String.format("%.1f", info.orbit_radium)+" Km");
if(panel_mass != null)
panel_mass.setText("Mass: "+String.format("%.1f", info.mass)+" Kg");
if(panel_roll != null)
panel_roll.setText("Rol: "+String.format("%.1f", (180*info.roll/Math.PI))+"º");
if(panel_pitch != null)
panel_pitch.setText("Pitch: "+String.format("%.1f", (180*info.pitch/Math.PI))+"º");
if(panel_yaw != null)
panel_yaw.setText("Yaw: "+String.format("%.1f", (180*info.yaw/Math.PI))+"º");
}
}
});
//Log.d("Sim",System.currentTimeMillis()+": "+"post update gui 1");
}
Edit 2: I can actually remove the runOnUiThread since it is already at that thread, but the effect is the same, this is not the problem.
Edit 3: I tried to comment all the lines of the method updateHUD() and leave only these two:
if(panel_time != null)
panel_time.setText(info.time.replace("T", " "));
The effect is almost the same, if I touch any textView, the animation goes by steps like periodically freezing
Edit 4:
I noticed that the process inside the AsyncTask was taking longer than the available step time so it was never sleeping. I established a safe guard time of 10ms that is slept even if the simulation step is longer than the available time. So, I have minimum 10ms free of each 100ms. The efect stills the same. I am updating at 25Hz the browser and 1Hz a single textview text. If I disable the textview update, the webgl model animates smoothly. On the other hand, if I enable the textview update too, every time the text is updated, there are some miliseconds where the browser animation and its response to touches are blocked. This effect gets worst if I increase the task priority. I tried setting a huge guard of 500ms but the freezing effect stills appearing. I am using XWalkView, can it be something blocking the interaction of this view when UI Thread is acting?
I can't understand why a 4 core 2 RAMgb device needs way more time to compute the same simulation than in Linux or windows desktop PC. I have 25Hz-->40ms of available time and the steps take almost 70ms. In a PC I could keep the simulation at 25Hz in real time. Is there so much shit running in background in Android compared to other OS?
There must be another issue with your code. Try posting your AsyncTask in here.
You could also try something very basic like:
Create a new Thread that loops every 25Hz and update your UI by using the post() method of your UI elements or the runInUiThread() of your Activity. See if there's any code still running inside the UI Thread, that could do heavy work, that can be done outside the UI Thread.
I tried literally everything except for the most logic thing, trying the application without the debugger connected.
The reason to have slower simulation than in a PC, to freese UI events... all because the debugger takes a lot of resources from the device. So, I guess that from this point and avobe I will have to test the application without debugger, what forces me to reboot the phone each time to avoid the "waiting for debugger to connect".
Thank to all who tried.
I could be wrong, but I think that yours problem in synchronization on simulator.getSimulationResults() object. I can't see the realization of the simulator class and realization of the object returned by getSimulationResults(), but I suppose that getSimulationResults() returns the same object every time? If so, then it can be looks like this:
In the AsyncTaks call simulator.getSimulationResults().updateSimulation(...). If this method is synchronized, then this call will be lock the SimulationResults object for AsyncTaks thread.
updateSimulation(...) returns, and publishProgress() is called, but publishProgress() is only schedule the onProgressUpdate(Void... values) in the UI thread.
The new iteration in the AsyncTaks thread can be started befor the UI thread gets the control and executes onProgressUpdate(Void... values). So, AsyncTaks thread goes to the first step.
The UI thread gets the control and executes the onProgressUpdate(Void... values) and synchronized void updateHUD() methods, but updateHUD() can't be executed, because SimulationResults object is locked by the AsyncTaks thread in the updateSimulation(...) method. So the UI thread returns the control to the OS. This may occur many times.
So, onProgressUpdate(Void... values) method and all events in the UI thread can be executed only if the UI thread gets the control in the right moment when updateSimulation(...) method is not called in the AsyncTask thread.
You can check this idea by replacing the public synchronized void update HUD() on the public void update HUD(), and write something randomly in the TextView.
In any case, the use of AsyncTask in this case is not the best idea. AsyncTask's are executed in the TheadPool, but in the Android system this pool can consist from only one thread. So, all AsyncTask's will be executed one by one in the one thread.
after each test execution junit goes to the next test. And activity closes automatically after each test execution.
Its OK when I test functions, but NOT OK when I test views. I want to see execution results on the screen before junit will execute next test.
So, I want to make small delay between tests.
There is one way I can do it:
public void testMyView() throws InterruptedException {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// viewOperations...
}
});
Thread.sleep(3000);
}
But I dont like this way because this code is dirty (especially when I have a lot of such tests).
Another way seems much better:
#UiThreadTest
public void testHandleEmptyAlphabetList() throws InterruptedException {
// view operations
Thread.sleep(3000);
}
BUT: It will block UI thread but NOT test thread. I need to block a test thread.
Is there any way to run Thread.sleep(3000); from this code separately in a test thread?
So, what is the best way to make thread delays between tests?
p.s. Please don't recommend me additional test frameworks, I want to solve my problem using embed tools. Thank you.
I suggest ditching this cumbersome way of unit testing and using Robolectric, so your tests run in the JVM and you don't have to deal with all this nasty setup. You'll be pleasantly surprised on how quickly your View testing runs, and that you don't need to run an emulator!
Try to use Robotium for the tests that need a real android running.
solo = new Solo(getInstrumentation(), getActivity());
[...]
if (failure) {
solo.takeScreenshot();
}
This will save a screenshot to your SD card (needs WRITE_EXTERNAL_STORAGE permission)
Or if you prefer not to use another testing framework (though I would recommend you take a look at it), just steal the code that is used there for taking screenshots
I need to write a helper method which I can use in various places in the app to essentially make it 'sleep' for N milliseconds.It looks like Handler.postAtTime may be one way to do it, but I'd like any code snippets if available.
You did not say why you need your app to "sleep".
Assuming you need to run a task after some time:
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
// do something here
}
}, 1000); // 1000 ms delay
If you don't mind blocking the thread, an alternative to Thread.sleep() is SystemClock.sleep().
Benefit is that it's a one-liner, as it ignores the
InterruptedException so you don't need to handle it.
More info on http://developer.android.com/reference/android/os/SystemClock.html.
As already stated, you should avoid calling this on the main UI thread as it will cause your app to become unresponsive and potentially show the dreaded dialog we all hate to see (please wait or force close.)
Are you looking for something like this?
try {
//Put the thread to sleep for the desired amount of time (milliseconds)
Thread.currentThread().sleep(1000);
}
catch(InterruptedException ie){
}
This will put the thread you are calling it from to sleep for the amount of time you specify.