Ui Automator 2.0 project in Android Studio
Solution 1
I am also using uiautomator 2.0 from AndroidStudio. Here are some answers to your questions.
How do I install this in the device? How do I run it in the device?
Make sure your device is connected using
adb devices
if not, you must connect it using
adb kill-server
adb connect xxx.xxx.xxx.xxx
Then from AndroidStudio, right click on your test class and click on "Run YourTestCase".
Do I need to do anything in the AndroidManifest?
I have nothing special in my manifest, but be sure you add
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
in your build.gradle
Am I editing in the right place? Should I do anything under src/main?
Yes, you are editing at the right place. But you can move your code to src/main
. To do so, you will need to change androidTestCompile
to compile
in your build.gradle file.
I did not try to run test from command line yet, but you can see AndroidStudio commands, maybe it can help.
I hope it helped you.
EDIT 1
I use this code
build.gradle (projectRoot)
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.0"
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'NOTICE'
exclude 'LICENSE.txt'
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 22
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.android.support.test:testing-support-lib:0.1'
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0'
compile project(':aiccore')
}
LoginTestCase (projectRoot/src/main/LoginTestCase.java)
public class LoginTestCase extends InstrumentationTestCase {
protected UiDevice device = null;
protected String appName;
public LoginTestCase() {
this("YourAppName")
}
public LoginTestCase(String appName) {
this.appName = appName;
}
public void runApp(String appName) throws UiObjectNotFoundException, RemoteException {
device = UiDevice.getInstance(getInstrumentation());
device.pressHome();
device.waitForWindowUpdate("", 2000);
UiObject2 allAppsButton = device.findObject(By.desc("Apps"));
allAppsButton.click();
device.waitForWindowUpdate("", 2000);
UiScrollable appViews = new UiScrollable(new UiSelector().scrollable(true));
appViews.setAsHorizontalList();
UiObject settingsApp = appViews.getChildByText(new UiSelector().className(TextView.class.getName()), appName);
settingsApp.clickAndWaitForNewWindow();
assertTrue("Unable to detect app", settingsApp != null);
}
@Override
public void setUp() throws RemoteException, UiObjectNotFoundException {
this.runApp(appName);
}
@Override
public void tearDown() throws RemoteException, UiObjectNotFoundException {
//Empty for the moment
}
public void testUS1() {
UiObject2 usernameLabel = device.findObject(By.clazz(TextView.class.getName()).text("Username"));
assertTrue("Username label not found", usernameLabel != null);
}
Solution 2
Well, actually, you should not write test code that way. Just keep your code under the src/androidTest folder, and write test code like this:
@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = 18)
public class ChangeTextBehaviorTest {
private static final String BASIC_SAMPLE_PACKAGE
= "com.example.android.testing.uiautomator.BasicSample";
private static final int LAUNCH_TIMEOUT = 5000;
private static final String STRING_TO_BE_TYPED = "UiAutomator";
private UiDevice mDevice;
@Before
public void startMainActivityFromHomeScreen() {
// Initialize UiDevice instance
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// Start from the home screen
mDevice.pressHome();
// Wait for launcher
final String launcherPackage = mDevice.getLauncherPackageName();
assertThat(launcherPackage, notNullValue());
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)),
LAUNCH_TIMEOUT);
// Launch the app
Context context = InstrumentationRegistry.getContext();
final Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
// Clear out any previous instances
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
// Wait for the app to appear
mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)),
LAUNCH_TIMEOUT);
}
@Test
public void checkPreconditions() {
assertThat(mDevice, notNullValue());
}
@Test
public void testChangeText_sameActivity() {
// Type text and then press the button.
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput"))
.setText(STRING_TO_BE_TYPED);
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "changeTextBt"))
.click();
// Verify the test is displayed in the Ui
UiObject2 changedText = mDevice
.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "textToBeChanged")),
500 /* wait 500ms */);
assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED)));
}
}
For detail please look out: UIAutomator Test sample
Comments
-
Inês almost 2 years
I want to set up a project in Android Studio. However, I don't want an Android App, just the test project.
Following the lastest release of UiAutomator, I was trying to set a class extending ActivityInstrumentationTestCase2 and start my tests from there.
However, I've stumbled in one thing: I can't figure out how to create the project without making it an app.
The options for creating a new project are:
- Start a new Android Studio Project
- Open existing projects
- Import projects
I did:
- Start a new project, give it a name, set minSDK and choose "No activity"
- Open build.gradle (under app) and add the dependencies and instrumentation information mentioned in the end of Testing Support Library
- Opened androidTest under src and changed the main file: changed to ActivityInstrumentationTestCase2, added setUp and tearDown; defined RunWith Junit4 (as indicated in Testing Support Library)
- I build the project (build successful) - Press the green arrow next to build in the "action bar"
My problems are:
- How do I install this in the device?
- How do I run it in the device?
- Do I need to do anything in the AndroidManifest?
- Am I editing in the right place? Should I do anything under src/main?
I'd appreciate that the install and run instructions would be both for how to do it through Android Studio and using the command line (if you only know one of them post it anyway please).
Note: this is the first time I'm using Android Studio
Thanks in advance.
EDIT:
Right now I can build and run but it tells me I have no tests to run (empty test suite). Here are my graddle and my code.
My build.graddle is as follows:
apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "21.1.2" defaultConfig { applicationId "androidexp.com.ceninhas" minSdkVersion 21 targetSdkVersion 22 versionCode 1 versionName "1.0" testInstrumentationRunner="android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } packagingOptions { exclude 'LICENSE.txt' } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile 'com.android.support.test:testing-support-lib:0.1' androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0' }
My source code (under src/androidTest/java/package) is:
@RunWith(AndroidJUnit4.class) public class ApplicationTest extends ActivityInstrumentationTestCase2<Activity> { public final static String ACTIVITY_NAME = "com.calculator.Main"; public final static Class<?> autActivityClass; static { try { autActivityClass = Class.forName(ACTIVITY_NAME); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public ApplicationTest(){ super((Class<Activity>)autActivityClass); } @Before public void setUp() throws Exception{ super.setUp(); injectInstrumentation(InstrumentationRegistry.getInstrumentation()); } @After public void tearDown() throws Exception{ super.tearDown(); } @Test public void cenas(){ assertTrue(true); } }
The run log on the console was:
Testing started at 18:06 ... Waiting for device. Target device: lge-nexus_5-08e506c10ddef123 Uploading file local path: C:\Users\Ines\workspace\Ceninhas\app\build\outputs\apk\app-debug.apk remote path: /data/local/tmp/androidexp.com.ceninhas No apk changes detected. Skipping file upload, force stopping package instead. DEVICE SHELL COMMAND: am force-stop androidexp.com.ceninhas Uploading file local path: C:\Users\Ines\workspace\Ceninhas\app\build\outputs\apk\app-debug-androidTest-unaligned.apk remote path: /data/local/tmp/androidexp.com.ceninhas.test No apk changes detected. Skipping file upload, force stopping package instead. DEVICE SHELL COMMAND: am force-stop androidexp.com.ceninhas.test Running tests Test running startedFinish Empty test suite.
What am I doing wrong?
-
Inês about 9 yearsAre you saying I should or I could do it under src/main? Currently I'm doing it under src/androidTest? I was able to build and run (following your instructions but it tells me there are no tests to run. I will edit my question with my build.graddle and my code
-
ThomasThiebaud about 9 yearsSorry, my answer is confused. You could move it. I will edit my answer with a working example tomorrow
-
Inês about 9 yearsBtw, my test is just an assert, I don't do anything UiAutomator specific yet, I just wanted to be able to run it and then I would do more specific tests.
-
ThomasThiebaud about 9 yearsSo you can try to move it to
src/main
and changeAndroidCompileTest
bycompile
. -
Inês about 9 yearsHow do you sent it the appName? Where do you define it?
-
Inês about 9 yearsBtw, is there any reason for you to be using InstrumentationTestCase instead of ActivityInstrumentationTestCase2? And why are you using Junit3 instead of JUnit4?
-
ThomasThiebaud about 9 yearsThere is a default constructor to send the appName. I am using Junit3 because I migrate this code from an older version of uiautomator which only support Junit3, Junit4 will also work. I am using InstrumentationTestCase because it is enougth for me, I just need the
getInstrumentation()
method. Check the deprecated note here -
Inês about 9 yearsIt works the way you do it, so I marked your answer as correct, thank you. I don't know why it doesn't work the way I had it, but what matters is that I found a way to make it work. Oh and btw, it works even in the androidTest folder, I didn't move the files :)
-
Tim Boland over 8 yearsCan you post your AndroidManifest file? I dont have one, yet it appears to be required...but I dont know what values belong in it, for a test-only project like this
-
Tim Boland over 8 years@Maloubobola - Thank you so much for this, do you have a working version of this project in Github?
-
ThomasThiebaud over 8 yearsI'm sorry but this project is private for the moment. It belongs to my company and I do not have the rights to share it for the moment.