Touch, hold, swipe, release gesture simulation in Android Unit test

 There are a lot of various frameworks which are provide you with a very useful methods for writing unit tests for Android applications. But when you need something specific almost everything you have to do it yourself.

For example, simple actions sequence: touch screen, hold finger few seconds and slide it slowly to the random side of screen, release. Such simple gesture can’t be reproduced by any testing framework, including cool Robotium so far.

I have simulated this gesture using a simple approach – sending touch events to the Android OS manually:

package your.package.here

import android.app.Instrumentation;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.view.MotionEvent;

public class YourTestClass extends
ActivityInstrumentationTestCase2 {

protected static String TAG = “#########” + YourTestClass.class.getName();

public YourTestClass() throws Exception{

super(“com.testpackage.activities”, Activity_you_want_to_test.class);

// INITIALIZATION
}

public void setUp() throws Exception {
// SETUP
}

public void testHoldSwipe() {
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
Instrumentation inst = getInstrumentation();

// Just init your variables, or create your own coords logic 🙂
float xStart = 200;
float yStart = 200;
// simulating thick finger touch
float x0 = 205;
float y0 = 205;
float x1 = 205;
float y1 = 208;
float x2 = 235;
float y2 = 215;
// move finger to bottom and right
// increment previous coords
float x3 = 245;
float y3 = 255;
float x4 = 247;
float y4 = 275;
float x5 = 252;
float y5 = 300;
// proceed one more movement to bottom and left
float x6 = 230;
float y6 = 320;
float x7 = 200;
float y7 = 357;
float x8 = 180;
float y8 = 380;
float x9 = 160;
float y9 = 400;
// release finger, logically to use coords from last movent
float x10 = 160;
float y10 = 400;

try {
// sending event – finger touched the screen
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, xStart, yStart, 0);
inst.sendPointerSync(event);
// sending events – finger is moving over the screen
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x0, y0, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x1, y1, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x2, y2, 0);
inst.sendPointerSync(event);
// simulating pause by incrementing eventTime with 1 second
// finger is still touching the screen
eventTime = SystemClock.uptimeMillis() + 1000;
// moving finger across the screen
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x3, y3, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x4, y4, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x5, y5, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x6, y6, 0);
// simulating one more pause
eventTime = SystemClock.uptimeMillis() + 1000;
// moving finger again
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x7, y7, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x8, y8, 0);
inst.sendPointerSync(event);
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x9, y9, 0);
inst.sendPointerSync(event);
// release finger, gesture is finished
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x10, y10, 0);
inst.sendPointerSync(event);

} catch (Exception ignored) {
// Handle exceptions if necessary
}
}

@Override
public void tearDown() throws Exception {

getActivity().finish();
super.tearDown();
}

}

Off course you are welcome to remove hard coded coords with you own coords logic. The main trick here is to simulate ‘hold’ by simple string:

eventTime = SystemClock.uptimeMillis() + 1000;And pay attention that only one ACTION_DOWN is used.

You are able to combine pauses and moves to reproduce any single touch gesture! 🙂

Best regards,
Yahor