前端自动化测试(2)cypress

这篇记录一下 cypress 的学习。

基础

Cypress 基于 JavaScript,不依赖外部依赖项,直接运行在浏览器中,并利用浏览器提供的原生 API 来模拟用户操作,提供了一套完整的端到端测试体验,可以对浏览器中运行的任何内容进行快速,简单和可靠的测试。
允许用户快速的创建、编写、运行、测试用例,并且针对每一步操作均支持回看。
cypress
下面一张图可以看出,cypress 相当于过去一些工具的整合。
cypress

Cypress 元素定位

1
2
3
4
5
6
7
8
9
// id选择器
cy.get('#account').click()
Cypress.$('#account') // Cypress.$定位器
// class类选择器
cy.get('.form-control').click()
// attributes属性选择器
cy.get('[input[id = "account"]]').click()
// :nth-child(n)选择器
cy.get('tbody > tr:nth-child(1) > th')

Cypress 页面元素基本操作方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 搜索定位元素
.get(selector) 
.contains(selector) 
.find(selector) 

// 获取DON元素的子元素
.children() 
// 获取DOM元素的所有父元素
.parents() 
// 获取DOM元素第一层元素
.parent() 
// 获取DOM元素的所有同级元素
.siblings() 

// 获取指定DOM对象的第一个元素
.first() 
// 获取指定DOM对象的最后一个元素
.last() 
// 用来匹配DOM对象紧跟着的下一个同级元素
.next() 
// 用来匹配给定的DOM对象的所有同级元素
.nextAll() 
// 用来匹配给定DOM对象之后的所有同级元素直到遇到Until里定义的元素为止
.nextUntil() 
// 用来匹配给定DOM对象紧跟着的上一个同级元素
.prev() 
// 用来匹配给定的DOM对象之前的所有同级元素
.prevAll() 
// 用来匹配给定DOM对象之后的所有同级元素直到遇到Until里定义的元素为止
.prevUntil() 

// 用来遍历数组及其类似结果
.each() 
// 用来在元素或者数组中的特定索引处获取DOM元素。类似于Jquery中nth:child()
.eq() 

Cypress 常见操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 访问某个 link
cy.visit('httpf://www.baidu.com')
// 获取当前页面 URL
cy.url()
cy.url().should("contain", "baidu")

// 刷新页面
cy.reaload() // 等同于 F5
cy.radload(true) // 等同于 ctrl+F5 强制刷新

// 设置窗口
{ //在 cypress.json 中添加
'viewportWidth':'1000',
'viewportHeight':'600'
}
cy.viewpoint(1024,768) //运行中设置

// 前进后退
cy.go('back')
cy.go(-1)
cy.go('forward')
cy.go(1)

// 判断元素是否存在
cy.get('.check-box').should('be.visible') // 是否可见
cy.get('.check-box').should('exist')
cy.get('.check-box').should('no exist')

// 条件判断
const btn = '#btn'
Cypress.$(btn).length>0{
cy.get(btn).click()
}

// 获取元素属性值
cy.get("#btn").then(function () {
const btnTxt = $btn.text()
cy.log(btnTxt)
})

// 清除文本
cy.get("div>a").clear();
cy.get("div>a").clear().type();

// 操作单选/多选按钮
cy.get("radio").check("us") // 选中
cy.get("radio").uncheck("us") // 取消选中

// 操作下拉菜单
cy.get("select").select("下拉选项的值")
cy.get("li").eq(0).click()

// 操作弹出框
cy.get("iframe").then(function ($iframe) {
  const $body = $iframe.contents().find("body")
  cy.wrap($body).find("#bin").click();
})

// 操作被覆盖的元素
cy.get("#btn").click({ force: true })

// 模拟键盘操作
cy.get("input").type("111")
cy.get("input").type("{enter}")

初步方案

  1. 在现有项目上安装 cypress 环境
  2. 手动编写模拟操作,完成运行测试
  3. 尝试使用 AI 编写模拟操作,节约时间(当前使用 Fitten Code)

操作步骤

  1. 安装 cypress 环境
    1
    npm install cypress --save-dev
  2. 创建测试文件(从项目根目录打开)
    1
    npx cypress open
  3. 编写测试用例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    describe('My First Test', () => {
    it('passes', () => {
    cy.visit('https://***')
    cy.contains('type').click()
    cy.get('#email').type('<EMAIL>')
    cy.get('#password').type('password')
    cy.get('#login').click()
    cy.contains('Welcome to Cypress!')
    })
    })
  4. 运行测试用例
    1
    npx cypress run
    cypress测试结果
    也可以修改后直接在 cypress 控制的浏览器中运行,实时查看结果
  5. 编写测试用例
    1
    2
    <!-- 通过添加 data-cy 属性来定位元素,能防止 tag/class/id 被他人修改 -->
    <span data-cy="counter">{count}</span>
    it 代表一个独立的测试用例,第一个参数是一个简要描述,第二个包含测试代码
    1
    2
    3
    4
    5
    describe('Test', function() {
    it('stepper should default to 0', function() {
    cy.get('[data-cy=counter]').should('have.text', '0')
    })
    })

cypress 目录结构

安装之后,会在项目根目录下生成 cypress 文件夹,包含以下文件:
|– cypress
|– e2e # 测试代码
|– fixtures # 测试数据、账号
|– integration # 集成测试(所有自动化测试用例-cypress代码)
|– plugins # 模块、依赖、插件
|– support # 自定义命令

注意事项

  1. “Cypress is currently automating this browser.” Cypress 自动控制了当前浏览器,建议新开一个浏览器窗口运行项目。实验时发现 cookie 不能共享给 Cypress 控制的页面(自动使用无痕模式登录),必须写一段登录的代码。
  2. 直接运行不走 vue 的接口代理,会请求失败

附录
官网
前端自动化测试框架cypress
Vue项目采用Cypress做e2e自动化测试

后续思考

  1. Q:是否可以用来自动化做一些事情,例如:资料整理
    A:暂时有问题,聊天机器人都是使用一些长连接?URL 较长且中带有一些特殊信息,不太方便用来模拟打开网站。
  2. Q:有 apisix 验证的接口,怎么绕过登录?
    A:自己写 cookie(过期需要手动改)

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!