起因

因为要测试的 iOS app 用 appium 定位不了元素,所以就用网易的 aircv 开源库,通过图像识别找到需要查找的图片的坐标,然后通过 tap 的方法来点击该坐标。

def get_coordinate_by_image_identify(self, imgsch):
    """
    通过图像识别来查找待查找图片的坐标
    :param imgsch: 待查找图片
    :return: x, y轴坐标
    """
    try:
        time.sleep(0.5)
        self.driver.save_screenshot(CONST.Template_Img)
        imsrc = ac.imread(CONST.Template_Img)  # 原始图像
        imsch = ac.imread(CONST.Image_Dir.format(self.param['deviceName'], imgsch))  # 待查找的部分

        position = ac.find_template(imsrc, imsch)
        if position is not None:
            x, y = position['result']
        else:
            raise Exception("Cannot find the image that you provided.")
        return x, y
    except Exception as msg:
        raise Exception(msg)

self.driver.tap([(x, y)])方法死活点击不了,一度以为是 iOS 上不支持 tap 的方法。
后面尝试用 mobile:tap 的方法self.driver.execute_script("mobile:tap", {'x': x, 'y': y, 'duration': 500}),依然是点击不了

解决方法

后面通过搜索发现了,原来是因为 iPhone 所有图形的坐标都是以点为单位的,点与屏幕上的实际像素不对应导致的。

  1. 开始时,所有图形的坐标都是以点为单位指定的。点是抽象的单位,它们只在这个数学坐标空间中有意义。 在最初的 iPhone 中,点与屏幕上的实际像素完全对应,但现在已经不是这样了。
  2. 基于点的图形被渲染成像素。这个过程被称为光栅化。点坐标乘以比例因子得到像素坐标。比例因子越高,细节层次越高。典型的比例因子有 1 倍、2 倍和 3 倍。

举例说明:

  1. 6+, 6s+, 7+, 8+

    1. Points: 414 x 736 (points)
    2. Rendered Pixels: 1242 x 2208 (pixels)
    3. Downsampling / 1.15: 1080 x 1920 (device pixels): 屏幕像素分辨率比上一步渲染的图像要低。在图像可以显示在屏幕上之前,必须将其降采样(调整大小)以降低像素分辨率。只有这些设备才有 Downsampling。
    4. 这些设备的比例因子是 3,因此在 Appium 上用 aircv 获取的图片的坐标,需要除以比例因子 3,然后再点击坐标,才可以正确的点击到元素。
  2. 6, 6s, 7, 8

    1. Points: 375 x 667 (points)
    2. Rendered Pixels: 750 x 1334 (pixels)
    3. 这些设备的比例因子是 2,因此在 Appium 上用 aircv 获取的图片的坐标,需要除以比例因子 2,然后再点击坐标,才可以正确的点击到元素。

自己也可以通过这个网站:https://www.gsmarena.com/,查看手机设备的分辨率

参考链接:

  1. https://www.paintcodeapp.com/news/iphone-6-screens-demystified
  2. https://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
  3. https://developers.perfectomobile.com/display/TT/XCUITest%3A+Difference+in+screen+size+dimensions+between+Object+Spy+and+Exported+Page+Source


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