在移动互联网时代,同一产品需覆盖Android、iOS和Web三端。由于不同平台的开发框架(如Android的Material Design与iOS的Cupertino风格)及渲染引擎差异,UI界面易出现以下问题:
传统人工测试效率低且易遗漏细节,因此需借助自动化工具实现高效精准的UI一致性校验。
本方案以 图像比对技术 为核心,结合 自动化测试框架 与 持续集成工具,覆盖从截图采集到差异分析的全流程:
# 安装OpenCV及图像处理库
pip install opencv-python-headless scikit-image
# 安装自动化测试框架
pip install Appium-Python-Client selenium
# 安装报告生成工具
pip install allure-pytest
工具类型 | 候选方案 | 优势 | 适用场景 |
---|---|---|---|
移动端自动化 | Appium | 支持Android/iOS,跨平台 | 原生应用/混合应用 |
Web端自动化 | Selenium + Puppeteer | 浏览器兼容性强,Headless模式高效 | 响应式网页测试 |
图像处理库 | OpenCV | 算法丰富,社区支持好 | 模板匹配/差异检测 |
使用Figma/Sketch定义通用组件库,约束以下属性:
建立Android/iOS/Web三端组件的等效关系:
功能 | Android | iOS | Web |
---|---|---|---|
底部导航栏 | BottomNavigationView | UITabBar | |
浮动按钮 | FloatingActionButton | UIButton(type: .custom) |
在设计中标记需忽略的区域(如广告位、时间戳),后续通过图像处理自动屏蔽。
Android/iOS端(Appium示例)
Python
from appium import webdriver
def capture_mobile_screenshot():
desired_caps = {
'platformName': 'Android',
'deviceName': 'Pixel_5',
'app': '/path/to/app.apk'
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
screenshot = driver.get_screenshot_as_base64()
driver.quit()
return screenshot
Web端(Selenium示例)
from selenium import webdriver
def capture_web_screenshot(url):
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
driver.get(url)
driver.save_screenshot('web_screenshot.png')
driver.quit()
gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray_img, (5, 5), 1.5)
resized = cv2.resize(blurred, (1080, 1920))
通过ROI(Region of Interest)标记并填充动态区域:
mask = np.zeros_like(image)
cv2.rectangle(mask, (x1, y1), (x2, y2), (255, 255, 255), -1)
masked_img = cv2.bitwise_and(image, mask)
def pixel_compare(img1, img2):
diff = cv2.absdiff(img1, img2)
_, thresh = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
return np.sum(thresh) / 255 # 差异像素总数
from skimage.metrics import structural_similarity
def ssim_compare(img1, img2):
score, diff = structural_similarity(img1, img2, full=True)
return score, diff
def template_match(base_img, template_img):
res = cv2.matchTemplate(base_img, template_img, cv2.TM_CCOEFF_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(res)
return max_loc, max_val
def generate_heatmap(base_img, diff_img):
heatmap = cv2.applyColorMap(diff_img, cv2.COLORMAP_JET)
overlay = cv2.addWeighted(base_img, 0.7, heatmap, 0.3, 0)
return overlay
import allure
@allure.title("三端登录按钮位置校验")
def test_login_button_alignment():
# ... 执行测试逻辑
allure.attach.file('diff_heatmap.png', name='差异热力图')
级别 | 判断条件 | 处理方式 |
---|---|---|
Critical | 核心功能区域差异>10% | 阻塞发布,邮件通知 |
Major | 次要区域差异>20% | 记录JIRA缺陷 |
Minor | 差异<5% | 记录日志,无需处理 |
整理格式如下:
pipeline {
agent any
stages {
stage('UI Test') {
steps {
sh 'python run_ui_tests.py --platform all'
}
}
stage('Report') {
steps {
allure includeProperties: false, jdk: '', results: [[path: 'allure-results']]
}
}
}
}
启用OpenCV CUDA支持:
cv2.cuda.setDevice(0)
gpu_img = cv2.cuda_GpuMat()
gpu_img.upload(img)
步骤:
注:本文为原创技术文章,转载请注明出处。遇到技术问题欢迎在评论区留言讨论!