Automating Multi‑Channel Login Tests with UiAutomator and Java

This article explains how to automate the login process for multiple Android channel packages by packaging a Java UiAutomator script into a JAR, pushing it to the device, iterating over each APK, executing ADB commands, and logging success or failure for each login method.

FunTester
FunTester
FunTester
Automating Multi‑Channel Login Tests with UiAutomator and Java

During automated testing the author encountered a situation where two different channel packages failed to log in via Weibo, prompting the creation of a reusable script that can iterate through all channel APKs and test each login method automatically.

The overall workflow is:

Collect all channel APKs in a single /apk directory on the host machine.

Compile a Java program into a JAR, push the JAR to the Android device.

From the device, execute the JAR which runs a UiAutomator test for each APK, uninstalling the previous app, installing the new one, and invoking the test method with different parameters.

Capture the output and store logs in the current directory.

The entry point of the JAR is the Script class:

package happyjuzi;

import java.io.File;
import source.Common;

public class Script extends Common {
    public static void main(String[] args) {
        Script script = new Script();
        script.testDemo();
    }

    public static Script getInstance() {
        return new Script();
    }

    public void testDemo() {
        String home = getWorkSpase(); // get current path
        output(home);
        File file = new File(home + "/apk");
        File[] file2 = file.listFiles();
        for (int i = 0; i < file2.length; i++) {
            File apk = file2[i];
            String path = apk.getAbsolutePath();
            for (int k = 0; k < 4; k++) {
                output(apk.getName(), i + 1);
                execCmd(ADB_PATH + "adb uninstall com.happyjuzi.apps.juzi");
                execCmd(ADB_PATH + "adb install " + path);
                execCmd(ADB_PATH + "adb shell uiautomator runtest demo.jar --nohup -c happyjuzi.AppTest#testTest" + k);
            }
        }
    }
}

The test logic resides in AppTest, which extends a base AppCase class and defines four test methods ( testTest0testTest3) that each invoke login(int key) with a different login channel (WeChat, QQ, Weibo, phone).

package happyjuzi;

import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import com.android.uiautomator.core.UiObjectNotFoundException;
import android.os.RemoteException;
import source.UiAutomatorHelper;

@SuppressWarnings("deprecation")
public class AppTest extends AppCase {
    public static String jarName, testClass, testName, androidId;

    public static void main(String[] args) throws ClassNotFoundException, SQLException, InterruptedException, IOException, ParseException {
        jarName = "demo";
        testClass = "happyjuzi.AppTest";
        testName = "testTest0";
        new UiAutomatorHelper(jarName, testClass, testName);
    }

    public void testTest0() throws InterruptedException, IOException, UiObjectNotFoundException, RemoteException {
        startJuziApp();
        skipGuideage();
        login(0);
        checkIsLogin();
    }
    // testTest1, testTest2, testTest3 are similar, only the key argument changes
}

Three helper methods encapsulate common actions:

/**
 * Skip the guide pages.
 */
public void skipGuideage() throws IOException, InterruptedException, UiObjectNotFoundException {
    startJuziApp();
    waitForUiObjectByResourceId("com.happyjuzi.apps.juzi:id/btn_skip");
    swipeLeft();
    swipeLeft();
    waitForResourceIdAndClick("com.happyjuzi.apps.juzi:id/btn_start");
    sleep(5000);
    if (getUiObjectByResourceId("com.happyjuzi.apps.juzi:id/close").exists()) {
        waitForResourceIdAndClick("com.happyjuzi.apps.juzi:id/close");
    }
}

/**
 * Perform login using the specified channel.
 * @param key 0=WeChat, 1=QQ, 2=Weibo, 3=Phone
 */
public void login(int key) throws UiObjectNotFoundException {
    switch (key) {
        case 0:
            waitForResourceIdAndClick("com.happyjuzi.apps.juzi:id/btn_profile");
            waitForResourceIdAndClick("com.happyjuzi.apps.juzi:id/avatar_default_view");
            waitForResourceIdAndClick("com.happyjuzi.apps.juzi:id/wx_view");
            waitForUiObjectByResourceId("com.happyjuzi.apps.juzi:id/protrait_item_main");
            break;
        case 1:
            // similar steps for QQ, with additional handling for QQ login UI
            break;
        case 2:
            // similar steps for Weibo, with additional handling for Weibo login UI
            break;
        case 3:
            // phone number login, entering credentials and confirming
            break;
        default:
            break;
    }
}

/**
 * Verify whether login succeeded.
 */
public void checkIsLogin() {
    if (getUiObjectByText("点击头像登录").exists()) {
        outpu("登录失败!");
    } else {
        output("登录成功!");
    }
}
When exporting the JAR on macOS, remember to modify the ADB_PATH constant inside the code; otherwise the script will fail because the default path is incorrect. The detailed steps for building the JAR are described in the author’s previous blog post.

By following this structure, developers can quickly add new channel packages, adjust login parameters, and obtain a clear log of which login method works for each APK, greatly simplifying regression testing of multi‑channel Android applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaAndroidmobile testingautomation testingADBUIAutomator
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.