九、重塑你的“测试习惯”——避开Cypress的那些“坑”

重塑你的"测试习惯"------避开Cypress的那些"坑"

如果你用过Selenium这类传统测试工具,刚上手Cypress可能会觉得"不习惯":明明写对了代码,却拿不到元素值;想用async/await处理异步,结果报错......其实不是你写错了,而是Cypress的设计思路和传统工具不一样。这一章咱们就聊聊这些"特殊习惯",帮你少踩坑。

一、Cypress的"坑":这些操作千万别做

1. 别用"同步思维"写异步代码

Cypress的命令都是异步执行 的,和JavaScript的setTimeout类似,不会立刻执行,而是先"排队",再按顺序执行。比如下面这段代码,你以为会先打印id,实际却会打印undefined

javascript 复制代码
// 错误示例:以为能拿到元素id
let userId
cy.get('[data-cy=user-id]').then(($el) => {
  userId = $el.text() // 这里的赋值是异步的
})
console.log(userId) // 同步代码,会先执行,所以是undefined

正确做法 :用then回调处理异步结果,所有依赖这个结果的操作都要放在then里:

javascript 复制代码
cy.get('[data-cy=user-id]').then(($el) => {
  const userId = $el.text()
  console.log(userId) // 正确:在回调里处理
  // 后续操作也放这里
})

2. 别用箭头函数定义用例或钩子

如果用箭头函数(() => {})定义itbeforeEach,里面的this会指向全局,无法使用this.skip()等方法:

javascript 复制代码
// 错误示例:箭头函数里的this有问题
it('测试用例', () => {
  if (someCondition) {
    this.skip() // 报错:this.skip is not a function
  }
})

正确做法 :用function定义,this才会指向当前测试上下文:

javascript 复制代码
it('测试用例', function() {
  if (someCondition) {
    this.skip() // 正常工作:跳过用例
  }
})

3. 别用async/await处理Cypress命令

Cypress命令虽然是异步的,但它不返回Promise,所以async/await无效:

javascript 复制代码
// 错误示例:await对Cypress命令无效
async function test() {
  await cy.visit('/login') // 不会等待访问完成
  cy.get('input').type('username') // 可能在页面加载完之前执行
}

正确做法 :用Cypress的链式命令或then回调处理顺序:

javascript 复制代码
// 正确:链式执行,自动等待前一步完成
cy.visit('/login')
  .get('input[name=username]').type('jane')
  .get('input[name=password]').type('123')

4. 别在一次测试中访问多个域名

由于浏览器的同源策略限制,Cypress不允许在一个测试用例里访问不同域名(比如先访问http://a.com,再访问http://b.com),会直接报错。

解决办法 :如果必须跨域,拆分到多个测试用例;或者确保访问的是同一主域名下的子域(比如http://blog.a.comhttp://shop.a.com)。

二、Cypress的"独特技巧":这样用更顺手

1. 用闭包保存临时变量

想在测试中保存临时数据(比如接口返回的token),可以用闭包或then回调:

javascript 复制代码
describe('测试', function() {
  let token // 闭包变量
  
  it('获取token', function() {
    cy.request('/api/login').then((res) => {
      token = res.body.token // 保存到闭包
    })
  })
  
  it('使用token', function() {
    cy.visit('/profile', {
      headers: { Authorization: `Bearer ${token}` } // 直接使用
    })
  })
})

2. 用asget共享数据

通过cy.wrap().as('别名')给数据起别名,后续用cy.get('@别名')访问,适合跨步骤共享:

javascript 复制代码
// 第一步:保存数据到别名
cy.fixture('user.json').as('userData') // 从fixture取数据
// 或从接口取数据
cy.request('/api/user').then((res) => {
  cy.wrap(res.body).as('userInfo')
})

// 后续步骤:用@别名访问
it('使用用户数据', function() {
  cy.get('@userData').then((user) => {
    cy.get('input[name=username]').type(user.name)
  })
})

3. 用Cypress.env()设置全局变量

想在不同测试文件间共享配置(比如测试环境的域名),可以在cypress.json里定义环境变量,或运行时通过--env传入:

json 复制代码
// cypress.json
{
  "env": {
    "baseUrl": "http://test.com",
    "timeout": 10000
  }
}

代码里用Cypress.env('baseUrl')获取,也可以动态修改:

javascript 复制代码
Cypress.env('timeout', 15000) // 临时改超时时间
相关推荐
还有你Y4 小时前
Shell 脚本语法
前端·语法·sh
踩着两条虫6 小时前
如何评价VTJ.PRO?
前端·架构·ai编程
Mh7 小时前
鼠标跟随倾斜动效
前端·css·vue.js
小码哥_常8 小时前
Kotlin类型魔法:Any、Unit、Nothing 深度探秘
前端
Web极客码9 小时前
深入了解WordPress网站访客意图
服务器·前端·wordpress
幺风10 小时前
Claude Code 源码分析 — Tool/MCP/Skill 可扩展工具系统
前端·javascript·ai编程
vjmap10 小时前
唯杰地图CAD图层加高性能特效扩展包发布
前端·gis
ZC跨境爬虫10 小时前
3D 地球卫星轨道可视化平台开发 Day7(AI异步加速+卫星系列精简+AI Agent自动评论)
前端·人工智能·3d·html·json
ID_1800790547310 小时前
淘宝 API 上货 / 商品搬家 业务场景实现 + JSON 返回示例
前端·javascript·json
M ? A10 小时前
Vue 动态组件在 React 中,VuReact 会如何实现?
前端·javascript·vue.js·经验分享·react.js·面试·vureact