# nativescript-dev-appium 有什么新功能?

·

果您不熟悉此插件-如果您认真考虑了您的移动应用程序,则应该将其检查一下。Nativescript-dev-appium 是一个开放源代码插件,用于包装/提供对 Appium 的访问,它是测试 NativeScript 应用程序的合适方法。

nativescript-dev-appium 插件的主要优先级是:

  • 便于使用
  • 跨平台
  • 与第三方产品和服务的兼容性

考虑到这些,我们提供了一些新功能,这些功能将使您在 NativeScript 中使用 Appium 的体验更加出色。

# 我们有什么改进?

让我们从尝试在本地计算机上运行测试的点开始,这可能会很痛苦。Appium 需要一堆依赖关系,不仅需要安装这些依赖关系,而且还需要为我们使用的 JavaScript 测试框架提供功能以及可能的一些附加设置。因此,说实话-解决依赖关系并不那么舒适,但至少在大多数情况下,这是一项一次性的工作。不幸的是,我们这边也没有太多事情要做,因此我们专注于如何减轻测试的执行,尤其是在开发过程中。

# 测试执行

从那里开始,我们需要做的第一件事就是消除提供 Appium 功能的必要性。因此,让我们想象一下,您想在已经实时同步应用程序的模拟器上运行测试。以前,您被迫提供必需的 Appium 功能,但现在您只需要指定平台即可:

之前 npm run e2e -- --runType some-device-capabilities

现在 npm run e2e android/ios

就是这样!如果您有多个模拟器在运行,将会发生什么?'nativescript-dev-appium’目前无法执行同时测试,但是您可以提供--device.name (opens new window) =“ android-emulator-28”之类的其他参数,并且该测试仅在指定的设备上执行。

好吧,这似乎很好,但是随后我们必须处理以下事实:每次执行此命令时,Appium 需要先启动 appium-server,然后再启动 appium-driver,这总是需要一些时间。因此,我们提出了一个想法,即分别启动 Appium 流程并重用已经存在的会话。有了这个,不再需要等待 Appium 初始化。为此,您需要在测试执行之前再执行一条命令。

首先,./node_modules/.bin/ns-appium [android or ios] --startSession 在单独的终端中运行: ,直到sessionId显示。除非需要,请不要杀死该终端。

然后,您可以简单地执行像npm run e2e -- --attachToDebug 或那样的测试 , npm run e2e -- -a 或者简单地创建像这样的命令 npm run e2e-debug

当然,如果有多个会话开始,我们也需要提供--sessionId。另一个选择是使用 Appium 桌面应用程序启动该应用程序,并将其附加到 Appium 提供的会话中。请记住,如果您想测试一些动作/手势或找到最佳的本地化策略,这非常方便。

# 测试报告

与测试有关的下一个非常重要的事情是观察测试结果。从现在开始,您还可以使用 Mochawsome,它将显示图像比较的结果。请记住,如果您是第一次安装 nativescript-dev-appium,那么所有这些功能都将自动设置,并且您不需要这样做。在 setup.ts / js 中初始化报告上下文:

const addContext = require('mochawesome/addContext');
const testReporterContext = <ITestReporter>{};
testReporterContext.name = 'mochawesome';
testReporterContext.reportDir = 'mochawesome-report';
testReporterContext.log = addContext;
testReporterContext.logImageTypes = [LogImageType.screenshots];
nsCapabilities.testReporter = testReporterContext;

每个describe都应包含before应在其中提供报告上下文的挂钩:

describe("sample scenario", async function(){
    let driver: AppiumDriver;
    before("start server", async function () {
        nsCapabilities.testReporter.context = this;
        await startServer();
    });});

设置 mocha opt,使用 Mochawesome 报告程序的文件[TODO:哪个文件?]:

--timeout 999999
--recursive e2e
--reporter mochawesome
--reporter-options quiet=true,html=true,inline=true,autoOpen=true
--exit

# 图像比较

viewPortRect换言之其中部分显示选项或应包括在图像比较。幸运的是,Appium 提供了 viewPortRect 功能,可帮助我们了解图像比较中应包括显示的哪一部分。由于 Appium> = 1.10.0 并结合了 UIAutomator2(Android)和 XCUITests(iOS),因此可以使用此功能。如果需要覆盖此设置,可以在 appium 功能文件中提供 viewPortRect。但这还不是全部。您还可以为每个测试提供 ns-dev-appium 将在图像验证中考虑的不同矩形。

driver.imageHelper.options.cropRectangle = {x:150, y:150, width: 150, height: 150}

我们还提供了一些其他方法,这些方法可以帮助比较多次图像并在测试结束时确定结果。假设您在测试中有更多操作,并且在每个操作之后都需要比较图像。

beforeEach(async function() {
  // this property will be used to set image name in case it is omitted in test
  driver.imageHelper.testName = this.currentTest.title;
});
it(`sample-test`, async function() {
  const button = await driver.waitForElement(`sampleBtn`);
  await button.click();
  // This method will create image (if not exists) with the name as the test name.
  // In this case, the image name will be `sample-test.png`
  await driver.imageHelper.compareScreen();
  await button.click();
  // This method will create an image (if not exists) with the same name as the test                           // and will add a cpunter as a postfix. In this case, the image name will be `sample-test-2.png`
  await driver.imageHelper.compareScreen();
  // assert the results of image comparisson.
  assert.isTrue(driver.imageHelper.hasImageComparisonPassed());
});

每个 comare 方法还接受 IImageCompareOptions,它们可用于覆盖图像比较中使用的默认属性。

export interface IImageCompareOptions {
  imageName?: string;
  timeOutSeconds?: number;
  /**
   * pixel
   * percentage thresholds: 1 = 100%, 0.2 = 20%"
   */
  tolerance?: number;
  /**
   * pixel
   * percentage thresholds: 1 = 100%, 0.2 = 20%"
   */
  toleranceType?: ImageOptions;
  /**
   * Wait milliseconds before capture creating image
   * Default value is 2000
   */
  waitBeforeCreatingInitialImageCapture?: number;
  /**
   * This property will preserve not to add be added _actual postfix on initial image capture
   */
  donNotAppendActualSuffixOnIntialImageCapture?: boolean;
  /**
   * This property will ensure that the image name will not be manipulated with count postfix.
   * This is very convenient in order to reuses image.
   * Default value is false.
   */
  keepOriginalImageName?: boolean;
  /**
   * Clip image before compare. Default value excludes status bar(both android and ios) and software buttons(android).
   */
  cropRectangle?: IRectangle;
  /**
   * Default value is set to true which means that nativescript-dev-appium will save the image
   * in original size and compare only the part which cropRectangle specifies.
   * If false, the image size will be reduced and saved by the dimensions of cropRectangle.
   */
  keepOriginalImageSize?: boolean;
  /**
   * Default value is set to false. nativescript-dev-appium will recalculate view port for iOS
   * so that the top/y will start from the end of the status bar
   * So far appium calculates it even more and some part of safe areas are missed
   */
  keepAppiumViewportRect?: boolean;
  /**
   * Defines if an image is device-specific or only by the platform.
   * Default value is true and the image will be saved in device-specific directory.
   * If the value is set to false, the image will be saved under ios or android folder.
   */
  isDeviceSpecific?: boolean;
  /**
   * Overwrite actual image if doesn't match. Default value is false.
   */
  overwriteActualImage?: boolean;
}

# 搜索方式

waitForElement-此方法尝试通过 automationText 查找元素。

# CI

让我们讨论下一个逻辑步骤“应用程序的自动化测试”。这个主题非常广泛,但是我将尝试涵盖要点,这对 CI 尤为重要。ns-dev-appium应该能够在 Appium 支持的所有平台或服务上工作。通常对于本地运行,ns-dev-appium 依赖于移动设备控制器,但此插件不适用于其他供应商。这就是为什么应在这些运行中应用“ --ignoreMobileController”。对于 SauceLab,有一个附加选项--sauceLab可以提供 SauceLab 所需的一些附加设置,并且也将自动忽略移动设备控制器插件。已经有一些博客文章解释了如何在 SauceLabs 和其他产品上执行测试,因此我不会对此做更深入的介绍。我将尝试着重于对您可能有用的其他选项。

--imagesPath-相对于资源/图像的图像路径。由于所有 API 级别的仿真器名称都相同,因此在存储特定于设备的映像时需要区分它。

"isHeadless": true-使用无头模式。此设置应在 appium 功能中提供:

"android28": {
    "platformName": "Android",
    "platformVersion": "28",
    "deviceName": "Emulator-Api28-Google",
    "avd": "Emulator-Api28-Google",
    "lt": 60000,
    "newCommandTimeout": 720,
    "isHeadless": true,
    "noReset": false,
    "fullReset": false
},

# 下一步是什么?

我们的下一个目标之一是能够同时在多个设备上执行测试。这将帮助您扩展测试基础结构,减少等待时间,提高生产效率。

但是 Appium 集成的路线图主要由您决定。如果您有功能请求,或者只是想解决一些您不知道如何解决的问题,请在 nativescript-dev-appium 存储库中打开一个新问题。