You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于分支文件变更执行移动端自动化测试的可持续方案咨询

基于变更文件选择性运行移动应用测试的方案

针对你的场景(Android用Compose UI测试、iOS用XCUITest,配合CircleCI、Git、Fastlane),以下是可行的现成工具和自定义实现方案:

现成工具选项

  • CircleCI Path Filtering Orb + Fastlane:CircleCI官方的path-filtering orb可以直接检测PR/分支中变更的文件路径,根据路径匹配结果触发不同的测试任务。你可以在Fastlane里提前定义好对应不同测试集的lane(比如对应iOS不同测试计划、Android不同测试套件的lane),然后让CircleCI根据路径匹配结果调用对应的lane。
  • Danger:可以用danger-swift(iOS)和danger-kotlin(Android)在PR阶段分析变更文件,通过编写简单的Ruby脚本逻辑,动态决定要运行的测试集,再调用Fastlane执行测试。不过这个需要你写一些自定义逻辑,灵活性更高但有一定配置成本。

自定义实现方案(更贴合你的现有工具链)

如果现成工具满足不了你的细分需求,可以自己基于Git、Shell脚本、Fastlane和CircleCI来搭建,核心思路是:先获取变更文件列表,再根据预设的路径-测试集映射规则,决定要执行的测试任务,最后用Fastlane和CircleCI完成执行。

1. 定义路径-测试集映射规则

在项目根目录创建一个test-mapping.yml配置文件,把代码路径和对应的测试集关联起来,示例:

android:
  - paths: ["app/src/main/java/com/example/home/", "app/src/test/java/com/example/home/"]
    test_suite: "com.example.home.HomeScreenTests"
  - paths: ["app/src/main/java/com/example/checkout/", "app/src/test/java/com/example/checkout/"]
    test_suite: "com.example.checkout.CheckoutFlowTests"
ios:
  - paths: ["iOS/Modules/Home/", "iOS/Tests/HomeTests/"]
    test_plan: "HomeTestsPlan"
  - paths: ["iOS/Modules/Checkout/", "iOS/Tests/CheckoutTests/"]
    test_plan: "CheckoutFlowTestsPlan"
# 基础模块变更时跑全量测试
global:
  - paths: ["app/src/main/java/com/example/core/", "iOS/Shared/"]
    android_test_suite: "all"
    ios_test_plan: "FullTestPlan"

2. 编写Shell脚本检测变更并输出测试集

在项目里加一个determine-tests.sh脚本,用来对比当前分支和主分支的差异,匹配对应的测试集:

#!/bin/bash
set -e

# 获取主分支(这里假设是main)与当前分支的变更文件列表
CHANGED_FILES=$(git diff --name-only origin/main...HEAD)

# 安装yq用来解析YAML(CircleCI环境可以提前装)
if ! command -v yq &> /dev/null; then
  sudo apt-get update && sudo apt-get install -y yq
fi

# 处理Android测试集
ANDROID_TEST_SUITES=""
# 先检查全局规则
GLOBAL_ANDROID=$(yq e '.global[] | select(.paths[] | in(env.CHANGED_FILES)) | .android_test_suite' test-mapping.yml)
if [ -n "$GLOBAL_ANDROID" ] && [ "$GLOBAL_ANDROID" = "all" ]; then
  ANDROID_TEST_SUITES="all"
else
  # 匹配普通路径规则
  for entry in $(yq e '.android[]' test-mapping.yml); do
    PATHS=$(echo "$entry" | yq e '.paths[]' -)
    for path in $PATHS; do
      if echo "$CHANGED_FILES" | grep -q "$path"; then
        SUITE=$(echo "$entry" | yq e '.test_suite' -)
        ANDROID_TEST_SUITES+=" $SUITE"
        break
      fi
    done
  done
  # 去重
  ANDROID_TEST_SUITES=$(echo "$ANDROID_TEST_SUITES" | xargs | tr ' ' '\n' | sort -u | tr '\n' ' ')
fi

# 处理iOS测试集
IOS_TEST_PLANS=""
GLOBAL_IOS=$(yq e '.global[] | select(.paths[] | in(env.CHANGED_FILES)) | .ios_test_plan' test-mapping.yml)
if [ -n "$GLOBAL_IOS" ] && [ "$GLOBAL_IOS" = "FullTestPlan" ]; then
  IOS_TEST_PLANS="FullTestPlan"
else
  for entry in $(yq e '.ios[]' test-mapping.yml); do
    PATHS=$(echo "$entry" | yq e '.paths[]' -)
    for path in $PATHS; do
      if echo "$CHANGED_FILES" | grep -q "$path"; then
        PLAN=$(echo "$entry" | yq e '.test_plan' -)
        IOS_TEST_PLANS+=" $PLAN"
        break
      fi
    done
  done
  IOS_TEST_PLANS=$(echo "$IOS_TEST_PLANS" | xargs | tr ' ' '\n' | sort -u | tr '\n' ' ')
fi

# 把结果写入环境变量,供后续任务使用
echo "export ANDROID_TEST_SUITES=\"$ANDROID_TEST_SUITES\"" >> $BASH_ENV
echo "export IOS_TEST_PLANS=\"$IOS_TEST_PLANS\"" >> $BASH_ENV

3. Fastlane中定义测试执行Lane

Android Fastfile示例

lane :run_android_tests do |options|
  test_suites = options[:test_suites]
  if test_suites == "all"
    # 跑全量测试
    gradle(task: "connectedDebugAndroidTest")
  else
    # 跑指定测试套件
    test_suites.split(" ").each do |suite|
      gradle(
        task: "connectedDebugAndroidTest",
        flags: "--tests #{suite}"
      )
    end
  end
end

iOS Fastfile示例

lane :run_ios_tests do |options|
  test_plans = options[:test_plans]
  test_plans.split(" ").each do |plan|
    scan(
      scheme: "YourAppScheme",
      test_plan: plan,
      device: "iPhone 14",
      skip_build: false # 按需设置是否跳过构建
    )
  end
end

4. CircleCI配置文件(.circleci/config.yml)

version: 2.1

jobs:
  detect-test-sets:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run:
          name: Determine test suites/plans
          command: ./determine-tests.sh
      - persist_to_workspace:
          root: .
          paths:
            - $BASH_ENV

  run-android-tests:
    docker:
      - image: cimg/android:2023.04.1
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Run selected Android tests
          command: |
            if [ -n "$ANDROID_TEST_SUITES" ]; then
              fastlane run_android_tests test_suites:"$ANDROID_TEST_SUITES"
            else
              echo "No Android tests matched, skipping"
            fi

  run-ios-tests:
    macos:
      xcode: 14.3.1
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Run selected iOS tests
          command: |
            if [ -n "$IOS_TEST_PLANS" ]; then
              fastlane run_ios_tests test_plans:"$IOS_TEST_PLANS"
            else
              echo "No iOS tests matched, skipping"
            fi

workflows:
  pr-test-workflow:
    jobs:
      - detect-test-sets:
          filters:
            branches:
              only: /pull\/.*/
      - run-android-tests:
          requires:
            - detect-test-sets
          filters:
            branches:
              only: /pull\/.*/
      - run-ios-tests:
          requires:
            - detect-test-sets
          filters:
            branches:
              only: /pull\/.*/

额外优化建议

  • 如果没有匹配到任何测试集,可以设置默认跑核心的冒烟测试,避免完全跳过测试。
  • 可以把test-mapping.yml的规则拆分成Android和iOS各自的配置文件,方便维护。
  • 在CircleCI中可以给测试任务设置缓存,加快构建和测试速度。

内容的提问来源于stack exchange,提问作者Codr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:44:55