AndroidAutomation TestingQA

Android Automation Testing for Beginners: Run Your First UI Test Case on a Phone

A complete guide to Android automation testing: use a real Android phone in place of manual regression, compare it with a traditional Appium setup, and write your first automation test script step by step.

4 min read

How to choose among three testing setups

When a version ships every week, login, search, checkout, payment, and the profile screen get tapped by hand again and again. One wrong tap and the whole flow starts over. Automation testing writes those fixed steps as a script and lets a real phone repeat them. The same script can also be reused for regression, comparison, and compatibility checks.

Emulator Single real device Real-device cluster
Hardware cost Zero ¥1000–3000 per device ¥N×1000
How real the behavior is Medium (differs from a real device) High High
Model coverage Low (you install several emulators) Limited Large and parallel
Fits Checking during development Daily regression Compatibility and stress testing

Use an emulator in development to see the problem first. Use a real device for regression in the test stage. Before release, if you have several real phones, run the suite again in parallel. The table already lists how emulators and real devices differ.

Hands on: record a script, prepare templates, pick a tool

Take an e-commerce purchase flow. The steps are: open the app, search for “phone case”, tap the first result, pick black, add to cart, open the cart, check out, fill in the address, submit the order, and see “order placed”.

On EasyClick, connect the phone and switch to record mode, then walk the flow on the phone. Each button tap and each typed string shows up as code in the editor. After recording, it looks like this:

launchApp("com.example.shop");       // open the app
sleep(2000);
swipe(500, 1500, 500, 800, 500);    // swipe up
findAndTap("搜索", 3000);           // find the search box
typeText("手机壳");                    // type the keyword
clickByText("搜索");                  // tap search
scrollToByText("iPhone 13 透明壳");   // scroll to the product
tapByIndex(0);                       // tap the first one
selectColor("黑色");                 // pick the color
addToCart();                         // add to cart
checkout();                          // check out
fillAddress("北京市朝阳区...");        // fill the address
submitOrder();                       // submit
waitForResult("下单成功");            // wait for the success page

After the flow finishes, you still have to judge the result. Assertions go after the steps:

test("电商购买流程", () => {
    
    launchApp("com.example.shop");
    assert(title().contains("首页"));  // confirm the correct page
    
    search("手机壳");
    sleep(2000);
    var results = getSearchResults();
    assert(results.length > 0, "搜索结果不应为空");  // results exist
    
    clickOnProduct(0);
    selectColor("黑色");
    addToCart();
    
    navigateToCart();
    var cartItems = getCartItems();
    assert(cartItems.length === 1);      // only one item
    assert(cartItems[0].color === "黑色"); // color matches
    
    checkout();
    fillAddress(address);
    submitOrder();
    
    waitForPage("success-page", 10000);
    assert(currentUrl().includes("order-success"));
    
    print("购买流程测试通过!");
});

This script both runs the flow and judges pass or fail. Other scenes can follow the same structure. In a login test, the correct password reaches the home screen, and the wrong password must show “wrong password”:

test("用户登录", () => {
    enterCredentials("user@example.com", "password123");
    clickButton("登录");
    waitForPage("home");
    assert(findText("欢迎回来"));
    
    backToLogin();
    enterCredentials("user@example.com", "wrong_password");
    clickButton("登录");
    assert(findText("密码错误"));
});

Registration clears the cache first, then uses a random phone number and a generated password:

test("新用户注册", () => {
    clearCache();
    visitRegistrationPage();
    fillForm({
        phone: getRandomPhone(),
        password: generateStrongPassword(),
    });
    clickButton("注册");
    assert(findText("注册成功") || findText("验证邮箱"));
});

Multi-model compatibility can loop across devices, run the core flow, and compare screenshots to a baseline:

var devices = ["Samsung-Galaxy-S21", "Xiaomi-13", "Huawei-P60"];

devices.forEach(device => {
    connectDevice(device);
    test(`兼容测试: ${device}`, () => {
        runCoreFlows();
        assertScreenshot("baseline.png");
    });
});

Choose EasyClick or Appium from the environment you already have. For a small team or one person, EasyClick does not start with JDK, SDK, and Appium Server setup. Install the APK and run on a real phone. If the company already has a Java or Kotlin test infrastructure, keep using Appium.

Pick the manual flow that repeats the most at release time, write it as a script, get it running, and then add assertions on top.

More references

Android automation scripts for beginners, the mechanism underneath First project tutorial, starting from zero How the accessibility service works, the technical layer

About EasyClick: A mobile automation script development platform covering three phone ecosystems: Android without root, iOS without jailbreak, and HarmonyOS. It also offers Apple script writing, Apple cluster control, Android cluster control, remote cloud control, and AI phone cluster control. → Explore all products

Ready to build it for real?

Every approach in this article can be built with EasyClick capabilities on iEasyClick — full documentation, developer tools and automation products, free to try.

Visit iEasyClick →