Playwright自动化测试实战踩坑记那些年我遇到的诡异问题

硕阳 移动 阅读 2,107
赞 22 收藏
二维码
手机扫码查看
反馈

移动端自动化测试的痛苦经历

之前做移动端项目的时候,每次发版前都要手动测试各种手机型号,iOS、Android各种系统版本,搞到人都快废了。UI稍微有点变动就要重新测试一轮,效率低得要死。后来老板看不下去了,说必须搞自动化测试。

Playwright自动化测试实战踩坑记那些年我遇到的诡异问题

一开始想用Selenium,但发现对移动端支持不够好,各种driver问题一大堆。后来看到Playwright官方说支持移动端模拟,就抱着试试的心态接入了。说实话,开始没想到能这么顺利,后面确实踩了不少坑。

基本配置就花了两天

官方文档看起来挺简单,实际配起来才发现一堆坑。首先是环境搭建,Node.js版本要求比较严格,老版本直接跑不起来。然后是移动端设备模拟,Chrome DevTools Protocol那套东西理解起来也有点绕。

const { chromium, devices } = require('playwright');

// 设备配置
const iPhoneConfig = {
  ...devices['iPhone 12'],
  viewport: { width: 390, height: 844 },
  deviceScaleFactor: 3,
  isMobile: true,
  hasTouch: true,
  defaultBrowserType: 'chromium'
};

async function runTest() {
  const browser = await chromium.launch({
    headless: false // 开发阶段先设为false便于调试
  });
  
  const context = await browser.newContext(iPhoneConfig);
  const page = await context.newPage();
  
  await page.goto('https://jztheme.com/test-page');
  
  // 这里开始各种移动端特有的操作
  await page.waitForLoadState('networkidle');
  
  await browser.close();
}

这里要注意的是,viewport和deviceScaleFactor的设置很关键,错了的话页面渲染会有偏差。刚开始我一直用默认的iPhone配置,结果某些页面的布局完全不对,折腾了半天才发现是这些参数的问题。

最大的坑:触摸事件处理

移动端最头疼的就是touch相关事件,click有时候不好使,需要模拟真实的touch操作。项目中有个轮播图组件,正常情况下需要滑动切换,但Playwright的默认click方法根本不管用。

// 最初的错误尝试
await page.click('.carousel-item'); // 完全无效

// 正确的触摸操作方式
await page.touchscreen.tap(100, 200); // 直接坐标点击

// 更复杂的滑动操作
await page.touchscreen.start(300, 500);
await page.touchscreen.move(100, 500); // 向左滑动
await page.touchscreen.end();

// 或者使用gesture方式
await page.gesture({
  start: { x: 300, y: 500 },
  end: { x: 100, y: 500 }
});

这里踩过好几次坑,开始用click模拟滑动,结果发现轮播图完全没反应。后来查文档才知道需要模拟真实的touch事件。还有个问题是,某些手机浏览器对touch事件的处理比较特殊,需要加上一定的延时。

性能优化是个大工程

刚跑起来发现一个问题,测试执行速度特别慢,一个简单的登录流程要跑半分钟。后来分析发现主要是页面加载等待和元素查找耗时太长。

// 优化前的写法
await page.waitForTimeout(3000); // 硬编码等待
await page.click('#submit-btn');

// 优化后的写法
await page.waitForSelector('#submit-btn', { 
  state: 'visible',
  timeout: 10000 
});

await page.locator('#submit-btn').click({ 
  timeout: 5000,
  force: true // 强制点击,忽略可见性检查
});

// 并行执行多个操作
const [response] = await Promise.all([
  page.waitForResponse('**/api/login'),
  page.click('#submit-btn')
]);

这里的timeout设置很重要,移动端网络不稳定,有时候请求会比较慢。force: true这个参数也很有用,某些元素可能被遮挡但仍然可以点击,普通click会失败。

还遇到个奇葩问题,某些低端安卓机模拟环境下,页面渲染特别慢,经常出现元素找到了但实际还没渲染完成的情况。最后加了个通用的等待机制:

async function waitForRender(page, selector) {
  await page.waitForSelector(selector, { state: 'attached' });
  await page.waitForTimeout(200); // 短暂等待渲染
  await page.evaluate((sel) => {
    const element = document.querySelector(sel);
    if (element) {
      const style = window.getComputedStyle(element);
      return style.display !== 'none' && style.visibility !== 'hidden';
    }
    return false;
  }, selector);
}

兼容性测试的真实感受

真正开始大规模测试才发现,不同设备的差异比想象中大。iOS和Android的字体渲染就不一样,某些元素在iPhone上位置正常,在Android上就偏移了。还有软键盘弹出的问题,会导致页面布局发生变化。

为了处理这些问题,写了大量的设备特异性代码:

async function handleKeyboard(page, inputSelector) {
  const userAgent = await page.evaluate(() => navigator.userAgent);
  
  if (userAgent.includes('iPhone')) {
    // iOS特殊处理
    await page.focus(inputSelector);
    await page.waitForTimeout(500); // iOS键盘弹出需要时间
  } else {
    // Android处理
    await page.click(inputSelector);
    await page.keyboard.type('test input');
  }
}

// 屏幕方向切换测试
await page.setViewportSize({ width: 844, height: 390 }); // 横屏
await page.waitForTimeout(1000);
await page.setViewportSize({ width: 390, height: 844 }); // 竖屏

这里其实有很多细节问题,比如某些Android机型输入框聚焦后页面会自动缩放,导致其他元素位置变化。这些都需要在测试中考虑到。

CI/CD集成的曲折路

最后要把测试集成到CI/CD流水线,这又是一堆问题。服务器环境没有图形界面,需要headless模式运行,但某些移动端特性在headless模式下表现不一致。

// CI环境配置
const launchOptions = process.env.CI ? {
  headless: true,
  args: [
    '--disable-dev-shm-usage',
    '--no-sandbox',
    '--disable-setuid-sandbox',
    '--disable-gpu'
  ]
} : {
  headless: false
};

const browser = await chromium.launch(launchOptions);

还有并发执行的问题,同时跑多个设备测试容易内存爆掉。最后用了jest-puppeteer的方式,控制并发数量,避免资源冲突。

效果评估与遗留问题

经过一个月的折腾,自动化测试覆盖率达到了70%,确实大大减少了人工测试的工作量。回归测试时间从原来的2小时缩短到20分钟,这个提升还是很明显的。

不过还是有些问题没完全解决,比如某些H5游戏类功能还是需要手动测试,触控精度要求高的场景自动化也很难覆盖。还有就是测试数据的清理,移动端页面缓存比较复杂,有时候会影响测试结果。

整体来说,这次技术选型还是成功的。虽然前期踩坑比较多,但稳定运行后确实提升了效率。后续还会继续优化,主要是增加更多的断言检查和错误日志记录。

一点小心得

Playwright对移动端的支持确实是越来越好,但要想用好还是要花不少功夫。特别是要考虑到各种设备的差异,不能指望一套代码跑所有机型。建议从核心功能开始测试,逐步扩展覆盖范围,别一开始就想着全覆盖。

以上是我踩坑后的总结,希望对你有帮助。这个工具确实不错,但用起来还是有不少细节需要注意的地方。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论