跳至内容

构建医生检查

Appium Doctor 的理念是帮助用户进行驱动程序或插件先决条件的设置。有时,这些先决条件可能非常复杂,需要非凡的技术知识。医生检查,是扩展作者编写的普通 Node.js 类实例,通过自动化诊断和可能对发现的问题进行修复来简化设置过程。这些检查也可能是交互式的,以确保更好的使用体验。

本教程旨在供希望帮助其用户处理复杂设置或配置步骤的插件或驱动程序作者使用。

添加医生检查

类型要求

术语“医生检查”实际上描述了一个实现 IDoctorCheck 接口 的单个 javascript 类实例。该接口定义了以下方法和属性

  • diagnose(): Promise<DoctorCheckResult>:包含诊断可能问题的代码
  • fix(): Promise<string|null>:如果 hasAutofix() 返回 true,则修复实际问题,或者返回一个字符串描述,用于可能的手动修复。如果此方法抛出名为 FixSkippedError 的异常,并且 hasAutofix() 返回 true,则将忽略该方法调用的结果。
  • hasAutofix(): boolean:调用 fix() 是否会解决发现的问题
  • isOptional(): boolean:发现的问题是否可以忽略,并且不是阻止程序运行的问题
  • log: AppiumLogger:可用于记录。此属性可以由实例本身分配,也可以由 Appium 服务器分配,如果它未分配。

diagnose() 方法返回的 DoctorCheckResult 对象必须包含以下属性

  • ok: boolean:诊断是否未发现任何问题
  • optional: boolean:诊断出的问题是否可以安全地忽略
  • message: string:描述诊断结果的文本消息

清单要求

单个扩展程序可以将多个医生检查导出到 Appium。为了使这些检查在安装了相应的扩展程序后由服务器 CLI 正确拾取,它们可能在包 .json 清单中的 appium.doctor.checks 部分中列出,类似于以下定义

  // ...
  "appium": {
    "driverName": "fake",
    "automationName": "Fake",
    "platformNames": [
      "Fake"
    ],
    "mainClass": "FakeDriver",
    "schema": "./build/lib/fake-driver-schema.js",
    "scripts": {
      "fake-error": "./build/lib/scripts/fake-error.js",
      "fake-success": "./build/lib/scripts/fake-success.js",
      "fake-stdin": "./build/lib/scripts/fake-stdin.js"
    },
    "doctor": {
      "checks": [
        "./doctor/fake1.js",
        "./doctor/fake2.js"
        // ...
      ]
    }
  },
  // ...

此外,将 @appium/types 导入到包开发依赖项中也是有意义的。

实现示例

以下示例是一个“原始”Node.JS 实现,它不使用任何转译

const {fs, doctor} = require('@appium/support');

/** @satisfies {import('@appium/types').IDoctorCheck} */
class EnvVarAndPathCheck {
  /**
   * @param {string} varName
   */
  constructor(varName) {
    this.varName = varName;
  }

  async diagnose() {
    const varValue = process.env[this.varName];
    if (typeof varValue === 'undefined') {
      return doctor.nok(`${this.varName} environment variable is NOT set!`);
    }

    if (await fs.exists(varValue)) {
      return doctor.ok(`${this.varName} is set to: ${varValue}`);
    }

    return doctor.nok(`${this.varName} is set to '${varValue}' but this is NOT a valid path!`);
  }

  async fix() {
    return (
      `Make sure the environment variable ${this.varName} is properly configured for the Appium server process`
    );
  }

  hasAutofix() {
    return false;
  }

  isOptional() {
    return false;
  }
}

const androidHomeCheck = new EnvVarAndPathCheck('ANDROID_HOME');

module.exports = {androidHomeCheck};

/**
 * @typedef {import('@appium/types').DoctorCheckResult} CheckResult
 */

此文件可以保存为 doctor/android-home-check.js,然后添加到 package.json 清单中,如下所示

  // ...
  "appium": {
    // ...
    "doctor": {
      "checks": [
        "./doctor/android-home-check.js",
      ]
    }
    // ...
  },
  // ...