九、重塑你的“测试习惯”——避开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) // 临时改超时时间
相关推荐
遇到困难睡大觉哈哈15 分钟前
CSS中的Element语法
前端·css
Real_man22 分钟前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小彭努力中22 分钟前
147.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
前端·javascript·vue.js·ecmascript·echarts
老马聊技术24 分钟前
日历插件-FullCalendar的详细使用
前端·javascript
咔咔一顿操作27 分钟前
Cesium实战:交互式多边形绘制与编辑功能完全指南(最终修复版)
前端·javascript·3d·vue
LuckyLay2 小时前
使用 Docker 搭建 Rust Web 应用开发环境——AI教你学Docker
前端·docker·rust
pobu1682 小时前
aksk前端签名实现
java·前端·javascript
烛阴2 小时前
带参数的Python装饰器原来这么简单,5分钟彻底掌握!
前端·python
0wioiw02 小时前
Flutter基础(前端教程⑤-组件重叠)
开发语言·前端·javascript
冰天糖葫芦2 小时前
VUE实现数字翻牌效果
前端·javascript·vue.js