Sauce Labs自动化测试平台的核心技术与实战经验分享

迷人的燕伟 移动 阅读 2,109
赞 18 收藏
二维码
手机扫码查看
反馈

先跑起来再说

上周项目要上线,测试组说 iOS 15 上有个按钮点不动,Android 12 上表单提交后页面卡死。本地模拟器都正常,真机又没那么多型号。折腾半天,想起之前注册过 Sauce Labs 账号一直没用。干脆直接上云测,亲测有效,半小时定位到是 Safari 的 pointer-events 兼容问题。

Sauce Labs自动化测试平台的核心技术与实战经验分享

别一上来就看文档,我建议直接写个最简脚本能跑就行。Sauce Labs 支持 WebDriver 协议,所以用 WebdriverIO 写测试脚本最顺手。先装依赖:

npm install @wdio/cli
npx wdio config

配置时选 “On Sauce Labs”,然后填上你的用户名和 access key(在用户设置里能拿到)。生成的 wdio.conf.js 会自动带上 sauce:options,但注意:默认配置只跑一个浏览器,你得手动改 capabilities 才能覆盖多设备。

核心代码就这几行

下面这个脚本是我现在项目里每天跑的简化版,重点看注释里的坑:

// wdio.conf.js
export const config = {
  user: process.env.SAUCE_USERNAME,
  key: process.env.SAUCE_ACCESS_KEY,
  region: 'us', // 注意!欧盟区要改成 'eu',否则连不上
  capabilities: [{
    browserName: 'safari',
    platformName: 'iOS',
    platformVersion: '15.0',
    deviceName: 'iPhone 12 Pro', // 设备名必须严格匹配 Sauce 官方列表
    appiumVersion: '2.0.0', // 这个不写默认用旧版 Appium,新 iOS 版本可能跑不动
    'sauce:options': {
      name: 'Login flow test',
      build: build-${Date.now()}, // 每次构建用不同 build 名,方便回溯
      screenResolution: '1170x2532' // iPhone 12 Pro 的分辨率,不写可能默认用低分屏
    }
  }],
  // ... 其他配置
}

测试文件本身反而简单:

// test/login.spec.js
describe('Login page', () => {
  it('should submit form successfully', async () => {
    await browser.url('https://jztheme.com/login');
    const email = await $('#email');
    const password = await $('#password');
    const submit = await $('button[type="submit"]');
    
    await email.setValue('test@example.com');
    await password.setValue('123456');
    await submit.click();
    
    // 等待跳转,这里必须用 waitForExist 而不是 pause
    await expect($('#dashboard')).toBeExisting({ timeout: 10000 });
  });
});

这里注意下,我踩过好几次坑:别用 browser.pause(5000) 等待页面加载,网络波动时要么超时失败,要么浪费时间。Sauce Labs 的机器资源紧张,超时直接扣分钟数。

踩坑提醒:这三点一定注意

  • 设备名称必须精确匹配:比如你想测 Galaxy S22,不能写 “Samsung S22″,得去 Sauce Labs 的平台矩阵查官方名称 “Samsung Galaxy S22 GoogleAPI Emulator”。我之前因为少写了 “GoogleAPI Emulator”,任务直接进队列卡住不动。
  • 视频和日志默认不保存:免费账户跑完测试视频自动删,付费账户也要在 sauce:options 里显式开启:
    'sauce:options': {
          recordVideo: true,
          recordLogs: true
        }

    不开的话出问题只能干瞪眼。

  • iOS 真机和模拟器行为差异大:模拟器跑通不代表真机行。比如 iOS 真机上 WebKit 对 viewport-fit=cover 处理更严格,Safe Area 计算经常出错。建议关键路径一定要勾选 “Real Device”(虽然贵一倍,但省下 debug 时间更值)。

这个场景最好用

我最近用 Sauce Labs 解决了个棘手问题:客户反馈 PWA 在华为手机上安装后图标显示异常。本地根本没法复现,因为华为 EMUI 的 Webview 版本太碎。直接在 Sauce 上跑以下组合:

capabilities: [
  { deviceName: 'HUAWEI P40', platformVersion: '10.0', ... },
  { deviceName: 'HUAWEI Mate 30', platformVersion: '10.0', ... },
  { deviceName: 'HUAWEI Nova 7', platformVersion: '10.1', ... }
]

结果发现只有 P40 出问题,进一步查日志发现是它的 Webview 版本低于 89,不支持 maskable-icon。立马在 manifest.json 里加了 fallback 图标,搞定。这种碎片化兼容问题,不用云测真的很难搞。

另外,他们新出的 Visual UI Inspector 工具挺好用——跑完测试能直接在网页上圈出元素位置、尺寸、层级。有次发现 Android 上某个弹窗偏移了 2px,肉眼几乎看不出,但 Inspector 一眼就定位到是 transform: translate 的 sub-pixel 渲染问题。

高级技巧:动态切换设备参数

别把设备配置写死在文件里。我现在的做法是通过环境变量动态注入:

// wdio.conf.js
const DEVICE_MATRIX = {
  ios_latest: {
    platformName: 'iOS',
    platformVersion: '16.4',
    deviceName: 'iPhone 14'
  },
  android_old: {
    platformName: 'Android',
    platformVersion: '9.0',
    deviceName: 'Google Pixel 2'
  }
};

export const config = {
  // ...
  capabilities: [{
    ...DEVICE_MATRIX[process.env.TEST_DEVICE || 'ios_latest'],
    'sauce:options': {
      // ...
    }
  }]
};

这样跑命令时就能灵活指定:

TEST_DEVICE=android_old npm run test

配合 GitHub Actions 做矩阵测试也方便:

strategy:
  matrix:
    device: [ios_latest, android_old, samsung_s22]
env:
  TEST_DEVICE: ${{ matrix.device }}

不过注意:Sauce Labs 的并发数有限制(免费账户只有 1 个),矩阵跑太多会排队。建议关键路径用高配设备,边缘场景用低配或合并测试。

最后说点实在的

Sauce Labs 不是银弹。它的优势在于快速覆盖海量设备,但启动一次测试要 30 秒到 2 分钟(真机更久),不适合 TDD 那种高频调试。我的经验是:本地用 Chrome + iOS Simulator 覆盖 80% 场景,剩下 20% 疑难杂症再扔给 Sauce。

费用方面,免费账户每月 100 分钟,够小团队日常验证。但一旦用真机或视频录制,分钟数烧得飞快。建议在非关键测试里关掉视频:recordVideo: false,能省不少钱。

以上是我踩坑后的总结,希望对你有帮助。这个技术的拓展用法还有很多(比如结合 Percy 做视觉回归),后续会继续分享这类博客。有更优的实现方式欢迎评论区交流——特别是怎么优化测试速度,我现在还在折腾中。

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

暂无评论