在 iOS 真机执行 Macaca 用例时,碰到一个概率性的问题,有很大的概率出现错误:

xctest client proxy error with: Error: connect ECONNREFUSED 172.18.156.69:8100

而同样的代码重新执行几次有时候又是没问题了。issue 链接:https://github.com/macacajs/macaca-cli/issues/51

根据 Macaca 在 iOS9 上的运行原理结合 LOG,大概可以知道,用例执行的具体步骤大概如下:

  1. Macaca 启动 server 监听
  2. 收到 Client 的 POST 请求后,开始新建 session
  3. 编译 xctest-client/node_modules/webdriveragent/WebDriverAgent 下的 WDA 项目 (真机的话需要用自己的 apple id 重签名好替换) 并安装到设备中
  4. 在设备上启动 WDA,在 8100 端口监听具体的用例请求
  5. 用例执行开始通过 8100 端口 post 各种命令并得到反馈。

而从 LOG 的具体报错来看:

Error: >> proxy.js:58:18 [master] pid:6048 xctest client proxy error with: Error: connect ECONNREFUSED 172.18.156.69:8100
    at Logger.error (/usr/local/lib/node_modules/macaca-ios/node_modules/xlogger/lib/xlogger.js:169:9)
    at Request._callback (/usr/local/lib/node_modules/macaca-ios/node_modules/xctest-client/lib/proxy.js:58:18)

结合 BUG 现象:用例执行失败后,WDA 过了一段时间才在设备上启动,此时访问 8100 端口是正常的。

那么查看具体的错误部分代码可以看到在 xctest-client 中:

*start(caps) {
    this.capabilities = caps;
    const xcodeVersion = yield iOSUtils.getXcodeVersion();

    logger.debug(’xcode version: ${xcodeVersion}’);

    if (this.isRealDevice(this.device.deviceId)) {
      yield this.startDeviceLog();
    } else {
      yield this.startSimLog();
    }
    this.initProxy();

    if (caps.desiredCapabilities.browserName === 'Safari') {
      var promise = this.proxy.send('/session', 'POST', {
        desiredCapabilities: {
          bundleId: 'com.apple.mobilesafari'
        }
      });
      return Promise.all([this.device.openURL(TEST_URL), promise]);
    } else {
      yield _.sleep(10000);  //这里可以看到POST caps参数给8100/session之前的等待时间为10000毫秒
      return this.proxy.send('/session', 'POST', caps);
    }
  }

那么就可以得知,问题的原因是 xctest-client.js 里设置的 sleep 时间太短了导致 WDA 还没启动 macaca 就已经开始去访问 8100 了,此时 8100 端口还是未启动的状态,而概率性出现的原因,在于 WDA 的启动时间在真机上不太确定,有可能小于 10S 有可能大于 10S。当超过 10S 时 BUG 就产生了。

那么解决的办法就很简单了:把yield _.sleep(10000);替换为yield _.sleep(20000); 或者更长的时间,重新启动测试,问题解决了。

虽然是个小问题,不过在 issue 中看到还是有一些朋友也碰到了类似的情况,写个帖子和大家分享下。


↙↙↙阅读原文可查看相关链接,并与作者交流