Android-PickerView UI自动化测试:使用UI Automator进行端到端测试

Android-PickerView UI自动化测试:使用UI Automator进行端到端测试

【免费下载链接】Android-PickerView This is a picker view for android , support linkage effect, timepicker and optionspicker.(时间选择器、省市区三级联动) 【免费下载链接】Android-PickerView 项目地址: https://gitcode.com/gh_mirrors/an/Android-PickerView

1. 测试环境搭建

1.1 依赖配置

app/build.gradle中添加UI Automator依赖:

android {
    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    // UI Automator测试框架
    androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
    // AndroidX测试支持库
    androidTestImplementation 'androidx.test:runner:1.5.2'
    androidTestImplementation 'androidx.test:rules:1.5.0'
}

1.2 测试工程结构

app/src/androidTest/java/com/bigkoo/pickerviewdemo/
├── TimePickerTest.java       // 时间选择器测试类
├── OptionsPickerTest.java    // 选项选择器测试类
└── BaseTest.java             // 测试基类(包含共用方法)

2. 核心测试场景设计

2.1 测试用例矩阵

模块名称测试类型关键操作点验证指标
时间选择器功能测试日期切换、时间调整、确认选择选择结果正确显示、回调正常触发
省市区选择器功能测试省市联动、三级选择、确认按钮选择结果匹配预期、联动效果正确
自定义选择器UI兼容性测试主题切换、字体大小调整、夜间模式界面元素无重叠、文字清晰可辨
农历选择器边界测试闰月切换、节气显示、公农历转换日期计算准确、切换无崩溃

2.2 测试流程图

mermaid

3. 测试代码实现

3.1 基础测试类封装

public class BaseTest {
    protected UiDevice mDevice;
    protected Context mContext;
    protected String PACKAGE_NAME = "com.bigkoo.pickerviewdemo";
    protected int LAUNCH_TIMEOUT = 5000;
    
    @Before
    public void setUp() throws Exception {
        // 初始化UI Automator设备对象
        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        
        // 启动应用
        mDevice.pressHome();
        String launcherPackage = mDevice.getLauncherPackageName();
        mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
        
        // 启动测试应用
        Intent intent = mContext.getPackageManager()
            .getLaunchIntentForPackage(PACKAGE_NAME);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        mContext.startActivity(intent);
        
        // 等待应用启动
        mDevice.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), LAUNCH_TIMEOUT);
    }
    
    // 截图辅助方法
    protected void takeScreenshot(String name) {
        File path = new File(Environment.getExternalStorageDirectory(), "PickerViewTest");
        if (!path.exists()) path.mkdirs();
        
        String fileName = name + "_" + System.currentTimeMillis() + ".png";
        File file = new File(path, fileName);
        
        mDevice.takeScreenshot(file);
        Log.d("TestScreenshot", "Saved to: " + file.getAbsolutePath());
    }
}

3.2 时间选择器测试用例

@RunWith(AndroidJUnit4.class)
public class TimePickerTest extends BaseTest {
    private UiObject timeButton;
    private UiObject confirmButton;
    
    @Before
    public void initElements() throws UiObjectNotFoundException {
        // 获取时间选择器按钮
        timeButton = mDevice.findObject(new UiSelector()
            .text("时间选择器")
            .className("android.widget.Button"));
            
        // 预定义确认按钮(在弹窗中)
        confirmButton = mDevice.findObject(new UiSelector()
            .resourceId("com.bigkoo.pickerviewdemo:id/tv_finish")
            .className("android.widget.TextView"));
    }
    
    @Test
    public void testTimePickerSelection() throws UiObjectNotFoundException {
        // 点击时间选择器按钮
        timeButton.click();
        
        // 等待弹窗出现
        mDevice.wait(Until.hasObject(By.res("com.bigkoo.pickerviewdemo:id/timepicker")), 2000);
        
        // 获取时间选择器滚轮
        UiScrollable hourScroll = new UiScrollable(new UiSelector()
            .resourceId("com.bigkoo.pickerviewdemo:id/wheelview_h")
            .className("android.widget.ScrollView"));
            
        // 滑动选择小时(从当前位置向后滑动2个单位)
        hourScroll.flingForward();
        hourScroll.flingForward();
        
        // 点击确认按钮
        confirmButton.click();
        
        // 验证结果显示
        UiObject resultText = mDevice.findObject(new UiSelector()
            .resourceId("com.bigkoo.pickerviewdemo:id/btn_Time")
            .className("android.widget.Button"));
            
        // 断言结果不为空
        assertTrue("时间选择结果为空", resultText.getText().length() > 0);
        
        // 截图保存
        takeScreenshot("time_picker_result");
    }
    
    @Test
    public void testLunarCalendarSwitch() throws UiObjectNotFoundException {
        // 点击农历选择器按钮
        mDevice.findObject(new UiSelector().text("农历时间选择")).click();
        
        // 等待弹窗出现
        mDevice.wait(Until.hasObject(By.res("com.bigkoo.pickerviewdemo:id/cb_lunar")), 2000);
        
        // 切换到农历模式
        UiObject lunarCheckBox = mDevice.findObject(new UiSelector()
            .resourceId("com.bigkoo.pickerviewdemo:id/cb_lunar")
            .className("android.widget.CheckBox"));
        lunarCheckBox.click();
        
        // 验证农历元素是否显示
        UiObject lunarText = mDevice.findObject(new UiSelector()
            .textContains("农历")
            .className("android.widget.TextView"));
            
        assertTrue("农历模式切换失败", lunarText.exists());
        
        takeScreenshot("lunar_calendar_mode");
    }
}

3.3 省市区选择器测试用例

@RunWith(AndroidJUnit4.class)
public class OptionsPickerTest extends BaseTest {
    @Test
    public void testProvinceCityLinkage() throws UiObjectNotFoundException {
        // 点击省市区选择器按钮
        mDevice.findObject(new UiSelector().text("省市区选择")).click();
        
        // 等待弹窗加载完成
        mDevice.wait(Until.hasObject(By.res("com.bigkoo.pickerviewdemo:id/optionspicker")), 3000);
        
        // 获取省、市、区三个滚轮
        UiScrollable provinceScroll = new UiScrollable(new UiSelector()
            .index(0)
            .className("android.widget.ScrollView"));
            
        UiScrollable cityScroll = new UiScrollable(new UiSelector()
            .index(1)
            .className("android.widget.ScrollView"));
            
        // 选择广东省(向下滑动3次)
        for (int i = 0; i < 3; i++) {
            provinceScroll.flingForward();
        }
        
        // 等待市级数据加载
        Thread.sleep(500);
        
        // 选择深圳市(向下滑动2次)
        for (int i = 0; i < 2; i++) {
            cityScroll.flingForward();
        }
        
        // 点击确认按钮
        mDevice.findObject(new UiSelector().text("确认")).click();
        
        // 验证结果
        UiObject resultButton = mDevice.findObject(new UiSelector()
            .resourceId("com.bigkoo.pickerviewdemo:id/btn_Options"));
            
        String resultText = resultButton.getText();
        assertTrue("选择结果不匹配", resultText.contains("广东") && resultText.contains("深圳"));
        
        takeScreenshot("province_city_result");
    }
}

4. 测试执行与报告

4.1 命令行执行测试

# 克隆项目
git clone https://gitcode.com/gh_mirrors/an/Android-PickerView

# 进入项目目录
cd Android-PickerView

# 执行所有测试用例
./gradlew connectedAndroidTest

# 执行指定测试类
./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.bigkoo.pickerviewdemo.TimePickerTest

4.2 测试报告解析

测试报告默认生成路径:
app/build/reports/androidTests/connected/index.html

报告包含以下关键信息:

  • 测试用例执行总数
  • 通过/失败/跳过的测试数
  • 每个测试用例的执行时间
  • 失败用例的详细堆栈跟踪
  • 截图附件链接

4.3 持续集成配置

在项目根目录创建.github/workflows/android-test.yml

name: Android UI Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - name: Run UI Tests
      uses: reactivecircus/android-emulator-runner@v2
      with:
        api-level: 29
        script: ./gradlew connectedAndroidTest
        
    - name: Upload Test Report
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: test-report
        path: app/build/reports/androidTests/connected/

5. 常见问题与解决方案

5.1 测试稳定性问题

问题描述解决方案实施代码
弹窗加载超时增加显式等待mDevice.wait(Until.hasObject(...), 5000);
滑动操作不稳定使用精准滚动代替快速滑动scrollToBeginning(10); scrollForward(3);
元素识别失败优先使用resourceId定位By.res("com.bigkoo.pickerviewdemo:id/btn_Time")

5.2 复杂场景处理

处理日期范围选择的示例代码:

public void testDateRangeSelection() throws UiObjectNotFoundException {
    // 启动日期范围选择器
    mDevice.findObject(new UiSelector().text("日期范围选择")).click();
    
    // 选择开始日期(今天)
    selectDate(0, 0, 0);  // 年偏移,月偏移,日偏移
    
    // 选择结束日期(今天+7天)
    mDevice.findObject(new UiSelector().text("结束日期")).click();
    selectDate(0, 0, 7);
    
    // 验证日期范围
    UiObject resultText = mDevice.findObject(new UiSelector().resourceId("com.bigkoo.pickerviewdemo:id/tv_date_range"));
    String[] dates = resultText.getText().split(" - ");
    
    // 验证日期格式
    assertTrue("日期格式不正确", dates[0].matches("\\d{4}-\\d{2}-\\d{2}"));
    assertTrue("日期格式不正确", dates[1].matches("\\d{4}-\\d{2}-\\d{2}"));
}

// 日期选择辅助方法
private void selectDate(int yearOffset, int monthOffset, int dayOffset) throws UiObjectNotFoundException {
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.YEAR, yearOffset);
    calendar.add(Calendar.MONTH, monthOffset);
    calendar.add(Calendar.DAY_OF_MONTH, dayOffset);
    
    // 选择年
    mDevice.findObject(new UiSelector().text(String.valueOf(calendar.get(Calendar.YEAR)))).click();
    // 选择月
    mDevice.findObject(new UiSelector().text(String.valueOf(calendar.get(Calendar.MONTH) + 1))).click();
    // 选择日
    mDevice.findObject(new UiSelector().text(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)))).click();
}

6. 测试优化策略

6.1 测试效率提升

  1. 测试用例并行执行
android {
    testOptions {
        execution 'ANDROIDX_TEST_ORCHESTRATOR'
        animationsDisabled true  // 禁用动画加速测试
    }
}
  1. 关键路径优先测试
// 使用@FixMethodOrder指定测试顺序
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class PriorityTest {
    @Test
    public void test01_BasicFunction() {}  // 基础功能优先测试
    @Test
    public void test02_AdvancedFunction() {}  // 高级功能随后测试
}

6.2 测试覆盖率提升

测试类型覆盖目标实施方法
功能覆盖100%核心功能基于功能点矩阵设计用例
界面覆盖100%可见UI元素使用Hierarchy Viewer分析界面
场景覆盖80%用户场景基于用户行为分析设计场景

7. 总结与展望

Android-PickerView作为一款功能丰富的选择器控件,其UI自动化测试需要覆盖时间选择、选项联动、自定义样式等核心场景。通过UI Automator框架,我们可以实现对这些场景的自动化验证,确保控件在不同设备和系统版本上的稳定性和一致性。

未来测试优化方向:

  1. 引入视觉回归测试(Visual Regression Testing)
  2. 实现AI驱动的智能测试用例生成
  3. 构建测试数据工厂,支持动态测试数据生成

完整测试代码可在项目的androidTest目录下找到,建议结合持续集成系统定期执行,确保控件功能的长期稳定。

【免费下载链接】Android-PickerView This is a picker view for android , support linkage effect, timepicker and optionspicker.(时间选择器、省市区三级联动) 【免费下载链接】Android-PickerView 项目地址: https://gitcode.com/gh_mirrors/an/Android-PickerView

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值