Skip to content

基于视觉模型的目标检测技术在自动化测试中的应用

基于视觉模型的目标检测技术在自动化测试中的应用

简介

在进行 UI 自动化测试时,测试工程师经常会遇到一些涉及到图片的场景,比如购物车中的商品图片信息、搜索结果中的图片信息等。传统的 Selenium 或者 Playwright 等 UI 自动化工具通常无法直接处理这些场景,因为它们主要是基于 DOM 元素的定位和操作,而无法直接识别或验证图像内容。

针对这种情况,可以采用的一种解决方案是利用图像识别技术来辅助自动化测试,进一步验证页面中的图片信息。

uml diagram

图像识别技术可以通过分析图像内容来识别其中的特征或者进行相似度比较,从而判断页面上的图片是否正确显示,图像识别效果如下:

实践演练

需求说明

通过一个实战练习来实现上述流程,将 UI 自动化和图像识别进行结合使用。需要完成的测试步骤为:

  1. 打开必应搜索
  2. 搜索一个关键词
  3. 进入图片的搜索结果页面
  4. 点击第一个图片
  5. 断言图片内容符合搜索的关键词

实现思路

传统 UI 自动化测试可以断言 Dom 当中的元素信息,但是无法实现断言图片是否符合预期,如下图所示,如果需要确认搜索结果成功,对于传统的 UI 自动化测试来讲,能做到的也只是断言标题或者其他文字内容:

为了解决断言图片信息的问题,可以使用以下的实现步骤:

uml diagram

完整代码

通过目标检测技术实现获取图片信息的操作:

  1. 对图片进行标记。

  2. 获取图片中的标签名。

源码如下:

class ImageUtils:
    # 初始化一个 pipeline 对象
    object_detector = pipeline(task='object-detection', revision='main')

    @classmethod
    def draw_image(cls, image, width, height, predictions):
        # 给出标志
        draw = ImageDraw.Draw(image)
        for i, prediction in enumerate(predictions[:10]):
            box = prediction["box"]
            label = prediction["label"]
            score = prediction["score"]
            xmin, ymin, xmax, ymax = box.values()
            # 修正坐标
            width_ratio = 1
            height_ratio = 1
            if width > height:
                height_ratio = height / width
            elif height > width:
                width_ratio = width / height
            xmin = xmin / width_ratio
            ymin = ymin / height_ratio
            xmax = xmax / width_ratio
            ymax = ymax / height_ratio
            if i == 0:
                color = 'green'
                bold = 2
            else:
                color = 'red'
                bold = 1

            draw.rectangle((xmin, ymin, xmax, ymax), outline=color, width=bold)
            draw.text((xmin, ymin), f"{label}: {round(score, 2)}", fill="red",
                      font=ImageFont.truetype('arial.ttf', size=16))
        return image
    @classmethod
    def get_img_info(cls, img_path):
        '''
        获取图片标签
        :return:
        '''
        with open(img_path, 'rb') as f:
            # 打开照片
            image = Image.open(f)
            predictions = cls.object_detector(image)
        print(json.dumps(predictions, indent=2, ensure_ascii=False))
        # 处理图片
        image_new = cls.draw_image(image, image.width, image.height, predictions)
        labels = [predictions[i]['label'] for i in range(0, len(predictions))]
        # 展示图片
        image_new.show()
        return labels

在测试用例中,测试步骤仍旧使用传统 UI 自动化的写法去完成,最终的断言则可以使用图像识别来优化,源码如下:

class TestBing:
    def setup_class(self):
        # 初始化浏览器
        self.driver = webdriver.Chrome()
        # 最大化窗口
        self.driver.maximize_window()
        # 设置隐式等待
        self.driver.implicitly_wait(15)

    def teardown_class(self):
        # 退出浏览器
        self.driver.quit()

    def test_bing_search(self):
        # 进入必应搜索首页
        self.driver.get('https://cn.bing.com/?mkt=zh-CN')
        # 输入关键词
        self.driver.find_element(By.CSS_SELECTOR, 'input.sb_form_q').send_keys("小猫")
        # 点击搜索按钮
        self.driver.find_element(By.CSS_SELECTOR, '#search_icon').click()
        # 进入图片搜索结果页面
        self.driver.find_element(By.XPATH, "//*[text()='图片']").click()
        # 点开第一个图片
        WebDriverWait(self.driver, 10).until(
            expected_conditions.presence_of_element_located((By.CSS_SELECTOR, '[role="main"] li')))
        self.driver.find_element(By.CSS_SELECTOR, '[role="main"] li').click()
        # 切换 frame
        self.driver.switch_to.frame("OverlayIFrame")
        # 查看第一个图片
        self.driver.find_element(By.CSS_SELECTOR, '[aria-label="查看图片"]>span>:nth-child(2)').click()
        # 断言结果包含搜索的关键词
        window_handles = self.driver.window_handles
        self.driver.switch_to.window(window_handles[-1])

        # 获取图片 URL 存储图片
        img_url = self.driver.current_url
        image_response = requests.get(img_url)
        with open('./result.png', 'wb') as f:
            f.write(image_response.content)
        res = ImageUtils.get_img_info('./result.png')
        assert 'cat' in res

最终的实现效果如下图所示:

总结

  • 了解图像识别结合 UI 自动化的场景。
  • 掌握借助图像识别技术进行断言的方法。