如果您不熟悉这个插件,那么如果您认真考虑您的移动应用程序,您一定要尝试一下。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="android-emulator-28",测试将仅在指定设备上执行。
嗯,这看起来不错,但我们必须处理这样一个事实,即每次执行此命令时,Appium 都需要启动 appium-server,然后启动 appium-driver,这总是需要一些时间。所以,我们想出了一个想法,单独启动 Appium 进程,并重用已经存在的会话。得益于此,不再需要等待 Appium 初始化。为此,您需要在测试执行之前执行另一个命令。
首先,在单独的终端中运行:./node_modules/.bin/ns-appium [android 或 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 选项,使用 Mochawesome 报告程序的文件 [待办:哪个文件?]
--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 - 此方法尝试通过自动化文本查找元素。
让我们来谈谈下一个合乎逻辑的步骤:“自动化应用程序的测试”。这个主题非常广泛,但我将尝试涵盖主要要点,这些要点对于 CI 尤其重要。ns-dev-appium
应该能够在 Appium 支持的所有平台或服务上工作。通常,对于本地运行,ns-dev-appium 依赖于 mobile-devices-controller,但此插件并非旨在与不同的供应商合作。这就是为什么在这些运行中应该应用“--ignoreMobileController”。对于 SauceLab,有一个额外的选项 --sauceLab
可以提供 SauceLab 所需的一些额外设置,并且还会自动忽略 mobile-devices-controller 插件。已经有 一些博客文章 解释了如何在 SauceLabs 和其他平台上执行测试,所以我不会深入研究这个方向。我将尝试关注可能对您有用的其他选项。
--imagesPath
- 相对于 resources/images 的图像路径。由于模拟器名称对于所有 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 存储库 中创建一个新问题。