【appium】通过图片查找元素

appium官网给我们提供了图像来查找元素的方法,下面我们来详细的来看看.

1.安装opencv4nodejs

        appium是使用opencv进行图像处理的,而appium又是js编写的,所以我们需要引入opencv4nodejs模块,否则appium在进行图像处理时会抛出异常,让我们去安装opencv4nodejs.
安装链接: https://npm.io/package/opencv4nodejs

npm i -g opencv4nodejs

注意: 我们在安装opencv4nodejs时,会自动帮助我们导入相关依赖,但有的时候还是会出现缺少依赖的情况,我们需要把它缺少的依赖下载好,也要注意自己的环境,我的环境信息:mac: 11.6.5, node: 15.11.0, npm: 6.14.11.我用nvm管理我的node,如果不明白的可以自行百度.

2.appium如何使用图像查找元素

        appium新增了一种-image的定位策略,可以向appium发送您想点击元素的图像元素,如果appium可以找到您的模版匹配的屏幕区域,它会将有关该区域的信息作为标准包装起来WebElement,并将其发送回您的appium客户端.
        此策略将针对每个appium客户端以不同的方式提供,例如python: driver.find_element_by_image()

2.1图像选择器

        结合任何定位器策略,您需要使用“选择器”时,就要传入所需的参数.在-image定位器策略,选择器所需参数必须是一个字符串,且是一个base64编码的图像文件,来表示你要匹配的模版.

2.2图像元素

        当我们匹配成功后,appium会缓存有关匹配的信息并创建标准响应以供我们客户端使用.我们可以在“图像元素”上调用少量的方法,就好像它是真正的WebElement,它所支持的方法如下:

  • click: 点击
  • isDisplayed: 判断元素时候显示
  • getSize: 获取元素尺寸(此方法要根据不同客户端的调用规则来定,如python: 就是getSize,Ruby: 就是size)
  • getLocation: 获取元素所在位置
  • getLocationInView: 获取视图中的位置(主要是内部命令,并非所有客户端都支持)
  • getElementRect: 获取元素矩形(获取元素的尺寸和坐标)
  • getAttribute
    • visual: 如何添加配置{“getMatchedImageResult”: true}则将匹配的图像作为 base64 数据返回true
    • score: 将相似度分数返回为[0.0, 1.0]正弦 Appium 1.18.0范围内的浮点数

        图像元素支持这些操作是因为这些操作是仅涉及使用屏幕位置来实现功能的操作.不支持其它操作(如sendKeys).因为 Appium 可以根据您的模板图像知道是否存在与其视觉匹配的屏幕区域——Appium 无法将该信息转换为特定于驱动程序的信息UI 元素对象,这是使用其他操作所必需的
记住这一点很重要:图像元素没有什么“魔法”——它们只是参考屏幕坐标,因此“点击”图像元素在内部只不过是 Appium 在Image Element 屏幕边界的中心(实际上您可以告诉 Appium 使用哪个 API 来执行该点击)

2.3相关设置

        因为通过图像查找元素依赖于图像分析软件以及 Appium 的屏幕截图功能和您自己提供的参考图像,所以我们提供了许多设置来帮助您调整此功能,在某些情况下可能会加快匹配速度或使其更准确.
要访问这些设置,您应该使用 Appium设置 API。这些是可用的设置:

设置名称描述可能的值默认值
imageMatchThresholdOpenCV 匹配阈值,低于该阈值认为查找失败。基本上,可能性范围在 0(这意味着不应使用阈值)和 1(这意味着参考图像必须是精确的像素对像素匹配)之间。两者之间的确切值没有绝对意义。例如,需要对参考图像进行大幅调整大小的匹配将显示为比其他情况更低的匹配强度。建议您尝试默认设置,然后在找不到匹配元素时逐步降低阈值。如果您匹配错误的元素,请尝试增加阈值。从 0 到 1 的数字0.4
fixImageFindScreenshotDimsAppium 知道屏幕尺寸,最终这些尺寸与决定在屏幕上点击的位置相关。如果检索到的屏幕截图(通过 Appium 的本机方法或外部来源)与屏幕尺寸不匹配,则此设置指示 Appium 将调整屏幕截图的大小以匹配,确保在正确的坐标处找到匹配的元素。如果您知道没有必要,请关闭此设置,Appium 将放弃检查,可能会加快速度。true或者falsetrue
fixImageTemplateSize如果该图像大于要匹配的基本图像,OpenCV 将不允许匹配参考图像/模板。您发送的参考图像的尺寸可能大于 Appium 检索到的屏幕截图。在这种情况下,匹配将自动失败。如果您将此设置设置为true,Appium 将调整模板的大小以确保它至少小于屏幕截图的大小。true或者falsefalse
fixImageTemplateScaleAppium 在与 OpenCV 匹配之前调整基础图像的大小以适合其窗口大小。如果您将此设置设置为true,则 Appium 会缩放您发送的参考图像,因为 Appium 会缩放基础图像以适应窗口大小。例如,iOS 屏幕截图是750 × 1334像素基础图像。窗口大小为375 x 667。Appium 将基础图像重新缩放为窗口大小,使用0.5. 参考图像基于屏幕截图大小,绝不会与窗口大小比例匹配。此设置允许 Appium 使用0.5. appium-base-driver#306true或者falsefalse
defaultImageTemplateScale默认情况下,Appium 不会调整模板图像的大小(值为 1.0)。虽然,存储缩放的模板图像可能有助于节省存储空间。例如,一个可以用 270 × 32 像素的模板图像表示 1080 × 126 像素的区域(defaultImageTemplateScale 的值预计设置为 4.0)。查看appium-base-driver#307了解更多详情。例如, 0.5, 10.0,1001.0
checkForImageElementStaleness在您匹配图像元素和您选择点击它的时间之间,可能会发生该元素不再存在的情况。Appium 确定这一点的唯一方法是在点击之前尝试重新匹配模板。如果重新匹配失败,您将得到一个StaleElementException,正如您所期望的。将其false转为跳过检查,可能会加快速度,但可能会遇到陈旧的元素问题,而没有例外的好处让你知道你做了。true或者falsetrue
autoUpdateImageElementPosition在找到匹配的图像和点击它的时间之间,匹配的图像可能会改变位置。与之前的设置一样,如果 Appium 在重新匹配中确定位置发生变化,则可以自动调整其位置。true或者falsefalse
imageElementTapStrategy为了点击找到的图像元素,Appium 必须使用它的一种触摸动作策略。可用的策略是 W3C Actions API 或旧的 MJSONWP TouchActions API。除非您使用的驱动程序由于某种原因不支持 W3C Actions API,否则请坚持默认设置。“w3cActions"或者"touchActions”“w3cActions”
getMatchedImageResultAppium 不存储匹配的图像结果。虽然,将结果存储在内存中可能有助于调试通过图像查找是否匹配了哪个区域。Appium 根据属性API 将图像返回为visual.true或者falsefalse
imageMatchMethod自 Appium 1.22.0 以来逐图查找元素的模板匹配方法的名称。有关每个值的含义的更多详细信息,请阅读py_template_matchingTM_CCOEFF, TM_CCOEFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_SQDIFF,TM_SQDIFF_NORMEDTM_CCOEFF_NORMED

请注意,每个特定语言的 Appium 客户端都可以通过特殊常量使这些设置可用,这些常量可能与上面提到的确切设置名称略有不同。

3.示例

  • python:
self.driver.update_settings({"getMatchedImageResult": True})
el = self.driver.find_element_by_image('path/to/img.ong')
el.get_attribute('visual') # returns base64 encoded string
  • ruby:
# Ruby core
@driver.update_settings({ getMatchedImageResult: true })
el = @driver.find_element_by_image 'path/to/img.ong'
img_el.visual # returns base64 encoded string
  • java:
private String getReferenceImageB64() throws URISyntaxException, IOException {
    URL refImgUrl = getClass().getClassLoader().getResource("Edition031_Reference_Image.png");
    File refImgFile = Paths.get(refImgUrl.toURI()).toFile();
    return Base64.getEncoder().encodeToString(Files.readAllBytes(refImgFile.toPath()));
}

public void actualTest(AppiumDriver driver) throws URISyntaxException, IOException {
    WebDriverWait wait = new WebDriverWait(driver, 10);

    try {
        // get to the photo view
        wait.until(ExpectedConditions.presenceOfElementLocated(photos)).click();

        // wait for and click the correct image using a reference image template
        By sunriseImage = MobileBy.image(getReferenceImageB64());
        wait.until(ExpectedConditions.presenceOfElementLocated(sunriseImage)).click();

        // verify that the resulting alert proves we clicked the right image
        wait.until(ExpectedConditions.alertIsPresent());
        String alertText = driver.switchTo().alert().getText();
        Assert.assertThat(alertText, Matchers.containsString("sunrise"));
    } finally {
        driver.quit();
    }
}

其它语言就不一一列举了.

  • 调试:
    我们在调试的时候我们可以打开设置{getMatchedImageResult: true},返回查找到的路线,我们通过@driver.visual获取图像的bash64格式,将其保存到本地文件中,查看定位的时候准确.
    参考:https://github.com/appium/appium-base-driver/pull/327
  • 注意:
    我们在使用图像定位时,如果发现元素找不到,我们先看看自己的截图是否正确如果这些都没问题,再看看截图的尺寸和被测设备的分辨率,如果不同咱们可以设置{fixImageTemplateScale: true}

4.参考文档

appium官网: http://appium.io/docs/en/advanced-concepts/image-elements/
appiumPro:https://appiumpro.com/editions/32-finding-elements-by-image-part-1

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值