Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lkorth committed Nov 15, 2015
0 parents commit f260d24
Show file tree
Hide file tree
Showing 13 changed files with 788 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.idea
*.iml
.gradle
local.properties
.DS_Store
build
/captures
19 changes: 19 additions & 0 deletions DeviceAutomator/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 23
buildToolsVersion "23.0.1"

defaultConfig {
minSdkVersion 18
targetSdkVersion 23
versionCode 1
versionName "0.1.0"
}
}

dependencies {
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
compile 'com.android.support.test:runner:0.4.1'
compile 'com.android.support.test:rules:0.4.1'
}
2 changes: 2 additions & 0 deletions DeviceAutomator/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest package="com.lukekorth.deviceautomator">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.lukekorth.deviceautomator;

import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;import java.lang.Override;import java.lang.RuntimeException;import java.lang.String;

/**
* A collection of actions for use with {@link DeviceAutomator}.
*/
public abstract class AutomatorAction {

/**
* Performs a click on the ui element specified in
* {@link DeviceAutomator#onDevice(UiObjectMatcher)}.
*
* @return
*/
public static AutomatorAction click() {
return new AutomatorAction() {
@Override
void wrappedPerform(UiObject object) throws UiObjectNotFoundException {
object.click();
}
};
}

/**
* Sets the text on the ui element specified in
* {@link DeviceAutomator#onDevice(UiObjectMatcher)}.
*
* @return
*/
public static AutomatorAction setText(final String text) {
return new AutomatorAction() {
@Override
void wrappedPerform(UiObject object) throws UiObjectNotFoundException {
object.setText(text);
}
};
}

/**
* Clears the text field on the ui element specified in
* {@link DeviceAutomator#onDevice(UiObjectMatcher)}.
*
* @return
*/
public static AutomatorAction clearTextField() {
return new AutomatorAction() {
@Override
void wrappedPerform(UiObject object) throws UiObjectNotFoundException {
object.clearTextField();
}
};
}

void perform(UiObject object) {
try {
wrappedPerform(object);
} catch (UiObjectNotFoundException e) {
throw new RuntimeException(e);
}
}

abstract void wrappedPerform(UiObject object) throws UiObjectNotFoundException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.lukekorth.deviceautomator;

import android.graphics.Rect;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;

import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;

import java.lang.Override;import java.lang.RuntimeException;import static junit.framework.Assert.assertTrue;

/**
* A collection of assertions for use with {@link DeviceAutomator}.
*/
public abstract class AutomatorAssertion {

/**
* Asserts that the ui element specified in {@link DeviceAutomator#onDevice(UiObjectMatcher)}
* has text that matches the given matcher.
*
* @param matcher The <a href="http://hamcrest.org/JavaHamcrest/">Hamcrest</a> to match against.
* @return
*/
public static AutomatorAssertion text(final Matcher matcher) {
return new AutomatorAssertion() {
@Override
void wrappedCheck(UiObject object) throws UiObjectNotFoundException {
assertObjectVisible(object);
if (!matcher.matches(object.getText())) {
StringDescription description = new StringDescription();
description.appendText("Expected ");
matcher.describeTo(description);
description.appendText(" ");
matcher.describeMismatch(object.getText(), description);
assertTrue(description.toString(), false);
}
}
};
}

/**
* Asserts that the ui element specified in {@link DeviceAutomator#onDevice(UiObjectMatcher)}
* has a content description that matches the given matcher.
*
* @param matcher The <a href="http://hamcrest.org/JavaHamcrest/">Hamcrest</a> to match against.
* @return
*/
public static AutomatorAssertion contentDescription(final Matcher matcher) {
return new AutomatorAssertion() {
@Override
void wrappedCheck(UiObject object) throws UiObjectNotFoundException {
assertObjectVisible(object);
if (!matcher.matches(object.getContentDescription())) {
StringDescription description = new StringDescription();
description.appendText("Expected ");
matcher.describeTo(description);
description.appendText(" ");
matcher.describeMismatch(object.getText(), description);
assertTrue(description.toString(), false);
}
}
};
}

void check(UiObject object) {
try {
wrappedCheck(object);
} catch (UiObjectNotFoundException e) {
throw new RuntimeException(e);
}
}

abstract void wrappedCheck(UiObject object) throws UiObjectNotFoundException;

private static void assertObjectVisible(UiObject object) throws UiObjectNotFoundException {
Rect bounds = object.getVisibleBounds();
assertTrue("Matched view was not visible", bounds.width() > 0);
assertTrue("Matched view was not visible", bounds.height() > 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package com.lukekorth.deviceautomator;

import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.Until;

import java.lang.String;import static android.support.test.InstrumentationRegistry.getContext;
import static android.support.test.uiautomator.Until.hasObject;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNull.notNullValue;

/**
* The entry point for using the DeviceAutomator library.
*/
public class DeviceAutomator {

private UiDevice mDevice;
private UiObjectMatcher mMatcher;

public DeviceAutomator(UiDevice device, UiObjectMatcher matcher) {
mDevice = device;
mMatcher = matcher;
}

/**
* @return {@link DeviceAutomator} without a {@link UiObjectMatcher}. Suitable for performing
* global actions and launching apps.
*/
public static DeviceAutomator onDevice() {
return onDevice(null);
}

/**
* @param matcher {@link UiObjectMatcher} used to specify the ui element to interact with.
* @return {@link DeviceAutomator} for the supplied {@link UiObjectMatcher}. All further methods
* called on this instance of {@link DeviceAutomator} will interact with the supplied
* {@link UiObjectMatcher} only.
*/
public static DeviceAutomator onDevice(UiObjectMatcher matcher) {
return new DeviceAutomator(UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()),
matcher);
}

/**
* Presses the home button and waits for the launcher with a timeout of 5 seconds.
*
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator onHomeScreen() {
return onHomeScreen(5000);
}

/**
* Presses the home button and waits for the launcher with the given timeout.
*
* @param timeout length of time in milliseconds to wait for the launcher to appear before
* timing out.
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator onHomeScreen(long timeout) {
mDevice.pressHome();

String launcherPackage = mDevice.getLauncherPackageName();
assertThat(launcherPackage, notNullValue());
mDevice.wait(hasObject(By.pkg(launcherPackage).depth(0)), timeout);

return this;
}

/**
* Launches the app with the given package name and waits for it to start with a timeout of 5 seconds.
*
* @param packageName package name of the app to launch.
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator launchApp(String packageName) {
return launchApp(packageName, 5000);
}

/**
* Launches the app with the given package name and waits for it to start with the given timeout.
*
* @param packageName package name of the app to launch.
* @param timeout length of time in milliseconds to wait for the app to appear before timing out.
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator launchApp(String packageName, long timeout) {
return launchApp(getContext().getPackageManager().getLaunchIntentForPackage(packageName), timeout);
}

/**
* Launches the intent and waits for it to start with a timeout of 5 seconds.
*
* @param intent {@link Intent} to launch
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator launchApp(Intent intent) {
return launchApp(intent, 5000);
}

/**
* Launches the intent and waits for it to start with the given timeout.
*
* @param intent {@link Intent} to launch
* @param timeout length of time in milliseconds to wait for the app to appear before timing out.
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator launchApp(Intent intent, long timeout) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
getContext().startActivity(intent);

mDevice.wait(hasObject(By.pkg(intent.getPackage()).depth(0)), timeout);

return this;
}

/**
* Waits for the ui element specified in {@link #onDevice(UiObjectMatcher)} to be enabled with
* a timeout of 5 seconds.
*
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator waitForEnabled() {
return waitForEnabled(5000);
}

/**
* Waits for the ui element specified in {@link #onDevice(UiObjectMatcher)} to be enabled with
* the given timeout.
*
* @return {@link DeviceAutomator} for method chaining.
*/
public DeviceAutomator waitForEnabled(final long timeout) {
mDevice.findObject(mMatcher.getBySelector()).wait(Until.enabled(true), timeout);
return this;
}

/**
* @param action the {@link AutomatorAction} to perform on the ui element specified in
* {@link #onDevice(UiObjectMatcher)}.
*/
public void perform(AutomatorAction action) {
action.perform(getUiObject());
}

/**
* @param actions the {@link AutomatorAction}s to perform on the ui element specified in
* {@link #onDevice(UiObjectMatcher)}.
*/
public void perform(AutomatorAction... actions) {
for (AutomatorAction action : actions) {
action.perform(getUiObject());
}
}

/**
* @param assertion the {@link AutomatorAssertion} to assert on the ui element specified in
* {@link #onDevice(UiObjectMatcher)}.
*/
public void check(AutomatorAssertion assertion) {
assertion.check(getUiObject());
}

/**
* @param assertions the {@link AutomatorAssertion}s to assert on the ui element specified in
* {@link #onDevice(UiObjectMatcher)}.
*/
public void check(AutomatorAssertion... assertions) {
for (AutomatorAssertion assertion : assertions) {
assertion.check(getUiObject());
}
}

private UiObject getUiObject() {
return mMatcher.getUiObject(mDevice);
}
}
Loading

0 comments on commit f260d24

Please sign in to comment.