在 iOS 真机上运行 Appium

Appium 已支持真机的测试。

使用 Appium 运行你的测试

把设备的 udid 传给 udid 这个 capability。把应用的 bundle ID 传给 app 这个 capability,如果你的应用已经在手机上安装好了。如果应用未安装,那么需要将 .ipa 或者 .app 文件的路径传给 app 这个 capability。一旦你的设备和应用已经配置好,你就可以在那个设备上运行测试了。

Desired Capabilities

通过在测试里使用以下的 capability,你可以在某个设备加载这个应用:

更多的细节参考 Appium server capabilities

必备的软件

Appium iOS 真机支持依赖一个重要的第三方软件套件 libimobiledevice,使用 Homebrew 可以轻易地安装好。

brew install libimobiledevice

在 Xcode 7 和 iOS 9.3 或者以下,配置 iOS 真机设备测试

在 iOS 9.3 或者以下,使用 Xcode 7.3 或者以下对真机进行自动化 (比如,基于 Instruments 的测试) 需要相对较少的配置。主要就是需要你的应用是使用开发者证书签名的。 不幸的是,苹果移除了所有使用老版本 Xcode 的文档,不过你可以从这里这里找到如何操作。

更详细地说, 在真机上开始测试, 你需要如下步骤:

Appium 使用 ideviceinstaller (libimobiledevice 套件的一部分)来处理应用安装问题。但是有时候使用 Xcode 提前安装好应用确保没有问题更加容易。(更多参考 iOS deploy)。

排障思路

  1. 确保 UDID 是无误的,可以通过 Xcode Organizer 或者 iTunew 查看。留意 UDID 是很长的字符串(20+ 字符)。
  2. 确保你可以在模拟器运行你的测试。
  3. 重复确认通过 Instrumens 是否可以启动你的自动化。
  4. 确保 Instruments 不在运行状态中。
  5. 确保 UI Automation 在你的设备已经打开。设置 -> 开发者 -> 使用 UI Automation。

在 Xcode 8 和 iOS 9.3 以上配置 iOS 真机设备测试

作为对 libimobiledevice 依赖的补充,Appium 对 iOS 9.3 及以上和 Xcode 8 及以上的支持依赖 ios-deploy, 通过 npm 可以方便地安装:

npm install -g ios-deploy

不幸地是,苹果改变了以往的测试方法。新的方法需要安装一个帮助应用到设备上去,通过这个应用,自动化测试才能进行。说起来挺简单,但是代码签名和生成供开发和测试的应用,让人有一点头疼。

Appium 安装的应用叫 WebDriverAgent-Runner (可以在这里)找到,要想安装这个应用,Appium需要能配置这个构建。

基本 (自动化) 配置

在 iOS 真机上设置和运行 Appium XCUItest,最方便的方法是使用自动化配置策略。有两种方式:

    {
      "xcodeOrgId": "<Team ID>",
      "xcodeSigningId": "iPhone Developer"
    }
    DEVELOPMENT_TEAM = <Team ID>
    CODE_SIGN_IDENTITY = iPhone Developer

以上任何一个方式,Team ID 是一个 10 个字符长的字符串,苹果生成这个字符串,分配给你的团队。你可以在你的开发者账号里找到你的 Team ID。登录 developer.apple.com/account,然后点击边栏上的 Membership。你的 Team ID 在 Membership Information 部分的团队名字下面。你也可以在 keychain 里的 iPhone 开发者证书里的 "Organizational Unit" 属性找到你的 Team ID。

注意这是互斥的策略;要么用 xcodeConfigFile capability, 要么用 xcodeOrgId and xcodeSigningId 的组合。

当以上的配置搞定后,只需再指定 udid capability 就可以在真机上开始测试了。

如果还是不工作的话,通常会在 Appium server 的日志里显示一些错误如:info XCUITest xcodebuild exited with code '65' and signal 'null'。这通常表示必要的代码签名没配置正确。 去看下 Basic (manual) configuration 这个文档,参试修复下。

如果 WebDriverAgentRunner 成功的在设备上安装好,但是在 Appium server 日志里还是有如下错误信息:

2017-01-24 09:02:18.358 xcodebuild[30385:339674] Error Domain=com.apple.platform.iphoneos Code=-12 "Unable to launch com.apple.test.WebDriverAgentRunner-Runner" UserInfo={NSLocalizedDescription=Unable to launch com.apple.test.WebDriverAgentRunner-Runner, NSUnderlyingError=0x7fa839cadc60 {Error Domain=DTXMessage Code=1 "(null)" UserInfo={DTXExceptionKey=The operation couldn’t be completed. Unable to launch com.apple.test.WebDriverAgentRunner-Runner because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user. : Failed to launch process with bundle identifier 'com.apple.test.WebDriverAgentRunner-Runner'}}}
2017-01-24 09:02:18.358 xcodebuild[30385:339674] Error Domain=IDETestOperationsObserverErrorDomain Code=5 "Early unexpected exit, operation never finished bootstrapping - no restart will be attempted" UserInfo={NSLocalizedDescription=Early unexpected exit, operation never finished bootstrapping - no restart will be attempted}

Testing failed:
    Test target WebDriverAgentRunner encountered an error (Early unexpected exit, operation never finished bootstrapping - no restart will be attempted)

这个问题是因为开发者在这台设备上不被信任。如果你在设备上手动运行 WebDriverAgentRunner,你会看到一个错误页面弹出来:

Untrusted developer

你可以去设备中的 Settings => General => Device Management 信任这个开发者,允许 WebDriverAgentRunner 运行 (参考 Apple documentation for more information).

基本 (手动) 配置

很多情况,基本的自动配置满足不了需求。这通常和真机运行上的代码签名和项目配置有关。这常常发生在免费的开发者账号上,免费的开发者账号不能创建 wildcard provisioning profile,也不能为应用创建默认的配置文件。

Xcode 创建 provisioning profile 失败 的错误如下:

No provisioning profile

最容易的解决方案就是打开 Xcode创建一个新工程:

Create new project

类型不重要,只要是 "iOS"。用最简单的 "Single View Application" 即可:

Create single page

重要的地方是要用唯一的 "Product Name" 和 "Organization Name". 然后,在这里,指定你的 "Team"。

Setup bundle

你可以在 "Project" tab 确认 provisioning profile 是否创建成功。

Project pane

或者去你的账号首选项里看看 provisioning profile:

Check provisioning profile

现在你就有了一个有效的 provisioning profile。 记住你关联这个 profile 的 bundle id,然后放到 updatedWDABundleId 这个 desired capability 里。然后跟着前面的自动配置教程操作即可。

全部手动配置

另外,可以手动把 provisioning profile 和项目关联在一起。 (记住如果使用这个方法,每次 WebDriverAgent 更新,都要做一次。所以我们不推荐这个方法):

    $ which appium
    /path/where/installed/bin/appium
    mkdir -p Resources/WebDriverAgent.bundle
    ./Scripts/bootstrap.sh -d
    xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=<udid>' test

如果成果了,最后的输出会像下面这样:

    Test Suite 'All tests' started at 2017-01-23 15:49:12.585
    Test Suite 'WebDriverAgentRunner.xctest' started at 2017-01-23 15:49:12.586
    Test Suite 'UITestingUITests' started at 2017-01-23 15:49:12.587
    Test Case '-[UITestingUITests testRunner]' started.
        t =     0.00s     Start Test at 2017-01-23 15:49:12.588
        t =     0.00s     Set Up
    export DEVICE_URL='http://<device IP>:8100'
    export JSON_HEADER='-H "Content-Type: application/json;charset=UTF-8, accept: application/json"'
    curl -X GET $JSON_HEADER $DEVICE_URL/status
你会得到如下输出:
    {
      "value" : {
        "state" : "success",
        "os" : {
          "name" : "iOS",
          "version" : "10.2"
        },
        "ios" : {
          "simulatorVersion" : "10.2",
          "ip" : "192.168.0.7"
        },
        "build" : {
          "time" : "Jan 23 2017 14:59:57"
        }
      },
      "sessionId" : "8951A6DD-F3AD-410E-A5DB-D042F42F68A7",
      "status" : 0
    }