uiautomatorでボット作ってみた
TRANSCRIPT
Atsuto Yamada
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); UiObject2 button = uiDevice.findObject(By.res("info.akkuma.example:id/submit")); button.click();
@Beforepublic void startApp() { mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); mDevice.pressHome(); String launcherPackage = getLauncherPackageName(); mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), TIMEOUT); Context context = InstrumentationRegistry.getContext(); final Intent intent = context.getPackageManager().getLaunchIntentForPackage(APP_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); mDevice.wait(Until.hasObject(By.pkg(APP_PACKAGE).depth(0)), TIMEOUT); }
ホームアプリへの遷移を待つ
LaunchIntentで起動する
@Testpublic void testLogin() { UiObject2 emailForm = mDevice.findObject( By.res("info.akkuma.spoonwithuiautomator:id/email")); emailForm.setText("[email protected]"); UiObject2 passwordForm = mDevice.findObject( By.res("info.akkuma.spoonwithuiautomator:id/password")); passwordForm.setText("dragon"); UiObject2 submitButton = mDevice.findObject( By.res("info.akkuma.spoonwithuiautomator:id/submit")); submitButton.click(); mDevice.wait(Until.hasObject(By.text("ホーム")), TIMEOUT); UiObject2 loginSuccessText = mDevice.findObject(By.text("ログイン完了")); Assert.assertNotNull(loginSuccessText); }
R.idリソースが利用できない
Activityを特定できる文字列でActivityの遷移を待つ
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package=“com.example.hoge.test”> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="22" tools:overrideLibrary="android.support.test.uiautomator.v18"/> <application> <uses-library android:name="android.test.runner" /> </application> <instrumentation tools:replace="android:label" android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="com.example.hoge" android:handleProfiling="false" android:functionalTest="false" android:label="@string/instrumentation_label"/> </manifest>
ライブラリ側のuses-sdkをoverride
@RunWith(AndroidJUnit4.class) @SdkSuppress(minSdkVersion = 18) public class MainActivityUiTest { private static final String APP_PACKAGE = "info.akkuma.spoonwithuiautomator"; private static final int TIMEOUT = 5000; private UiDevice mDevice; @Before public void startApp() { mDevice = UiDevice.getInstance( InstrumentationRegistry.getInstrumentation()); mDevice.pressHome(); String launcherPackage = getLauncherPackageName();
SdkSuppressでテスト毎に 動作するAPI Levelを指定できる
UiObject obj1 = mDevice.findObject( new UiSelector().resourceId("com.example.hoge:id/form"));
UiObject2 obj2 = mDevice.findObject(By.res("com.example.hoge:id/form"));
無印UiObjectはつぶせ!
1.3sec
0.2sec
public static File screenshot(Activity activity, String tag, String testClassName, String testMethodName) {
public static File screenshot(UiDevice uiDevice, String tag, String testClassName, String testMethodName) {
private static void takeScreenshot(File file, final Activity activity) throws IOException { View view = activity.getWindow().getDecorView(); final Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), ARGB_8888); if (Looper.myLooper() == Looper.getMainLooper()) { // On main thread already, Just Do It™. drawDecorViewToBitmap(activity, bitmap); } else { // On a background thread, post to main. final CountDownLatch latch = new CountDownLatch(1); activity.runOnUiThread(new Runnable() { @Override public void run() { try { drawDecorViewToBitmap(activity, bitmap); } finally { latch.countDown(); } } }); try { latch.await(); } catch (InterruptedException e) { String msg = "Unable to get screenshot " + file.getAbsolutePath(); Log.e(TAG, msg, e); throw new RuntimeException(msg, e); } (略)
private static void takeScreenshot(File file, UiDevice uiDevice) throws IOException { uiDevice.takeScreenshot(file); }
最上位のViewをBitmap出力 Fileに保存
スクリーンショットを Fileに保存