背景
白板是教育产品里的常见功能,类似于电子化的黑板,基础的业务逻辑是教师端(windows)老师在白板上写字或者画图,学生端(android)可以同步接收到该内容。
现在有两套基于不同技术的白板功能方案,需要对比他们的效果差异,由于底层代码无法放开,无法通过修改代码埋点的形式进行,因此需要通过ui层面进行对比。
基础测试流程
- 在pc教师端运行一次画图脚本,在Android学生端确认正确后,选取该图案作为基准图片
- 在pc教师端进行ui操作,在白板上再次画出该图案
- 在android学生端上,截取白板画面
- 对比截取的白板画面和基准图片,计算相似度,大于阈值(95%)则视为该次准确,否则认为该次失败,计入失败次数,并记录该失败图案供分析
- 清空pc教师端白板图案,再次重复2~4操作
自动化技术
airtest(pywinauto)& pynput完成对pc端ui操作
在pc端ui自动化中,首先选用的是比较经典的ui操作库pywinauto,airtest对其进行了封装,为减少二次开发量,这里直接选用了airtest。
基础的ui操作如元素定位、点击、滑动等,airtest都有较为成熟的api,但模拟老师在白板上画图,只靠自己定义滑动坐标使用鼠标事件执行的话,太过生硬不符合实际情形,因此,最后决定采用实际录制操作坐标再回放的形式进行,这样基本可以模拟真实的笔迹。
airtest不具备录制鼠标轨迹功能,在调研后,选用pynput进行鼠标事件的录制。
pynput也是一个提供windows操作api的库,但其提供了对鼠标和键盘事件的监听功能;通过添加监听线程pynput.mouse.Listener,每发生一个鼠标事件,就使用预先定义的格式进行本地化存储,这样就完成了鼠标操作的事件收集;再通过解析存储的事件文本,就可以完成鼠标事件的回放。
需要说明的是,pynput本身也有操作windows鼠标事件的api,但实测下来,虽然通过pynput进行回放整体轨迹是对的,但在白板上的笔画平滑度和粗细每次都不太一致,因此不适合选用其作为回放手段,最终测试,还是通过airtest的mouse_move、mouse_up、mouse_down组合进行回放,效率较pynput低,但胜在一致性高,基本每次回放的轨迹都一致。
opencv2进行图像识别判断
在进行教师端的操作后,需要在学生端截图并进行对比,这里对比技术采用了opencv2的api,代码如下:
def img_similarity(img1_path,img2_path):
"""
:param img1_path: 图片1路径
:param img2_path: 图片2路径
:return: 图片相似度
"""
try:
# 读取图片
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
# 初始化ORB检测器
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 提取并计算特征点
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
# knn筛选结果
matches = bf.knnMatch(des1, trainDescriptors=des2, k=2)
# 查看最大匹配点数目
good = [m for (m, n) in matches if m.distance < 0.75 * n.distance]
#print(len(good))
#print(len(matches))
similary = len(good) / len(matches)
#print("两张图片相似度为:%s" % similary)
return similary
except:
print('无法计算两张图片相似度')
return 0
由于其中一个方案学生端界面上会有动态的时间显示,影响对比结果,因此,需要对该截图进行裁剪,只保留白板的内容部分,裁剪代码如下:
screen_path = "D:\PycharmProjects\omoboard\{filename}".format(filename=screen)
img = cv2.imread(screen_path)
cropped = img[100:1050, 0:1500]
cv2.imwrite(screen_path, cropped)
网友评论