cypress 进行 e2e 测试之理论
cypress 是目前 e2e 很火的一个测试组件,内部绑定了 macha、chai、chai-jquery 之类的断言,为了让代码代码
更有说服力,减少提交测试错误,进行 e2e 测试显然是非常有必要的。
官网 \
GitHub
借鉴官网一句话来说:
Cypress is a next generation front end testing tool built for the modern web. We address the key
pain points developers and QA engineers face when testing modern applications.
<!-- more -->
本文环境
node v9.5\
npm v5.5
e2e 简介
e2e 测试端对端测试的简称, e2e 即为end to end
,
指任意一个人的社交、交易、休闲都可以直接与另外任意一个人产生关系,去中心化、渠道化.
cypress
cypress 环境搭建
做前端怎么少的多的了 npm 呢
$ npm i -D cypress
然后为了方便起见,咱们在package.json
中写入下面脚本:
{
"scripts": {
"e2e:open": "cypress open",
"e2e:run": "cypress run"
}
}
运行npm run e2e:open
,启动一个 cypress 的服务器,如下:
如下图这就完成了一个启动一个 cypress。第一次点开时候,cypress 会帮你创建一个初始化配置目录,这是
cypress 推荐的目录的结构,当然也可以自己创建。
点击 example_spec.js 文件,然后可以看到如下界面,cypress 开始测试:
上面就看到 cypress 的运行过程了。下面看看 example_spec.js(文件的位置
:projectName/cypress/integration)文件中写了啥:
describe('Kitchen Sink', function() {
it('.should() - assert that <title> is correct', function() {
// ...
}
})
这是主要结构的,下面大部分都是在一个it
函数内部,是测试里面的回调函数。详细可以查看 TDD 和 BDD 测试
框架,cypress 绑定了这些测试框架。
cy.visit
这是 cypress 里面一个很重要的方法,可以访问一个链接,列入 example.js 文件如下:
beforeEach(function() {
// Visiting our app before each test removes any state build up from
// previous tests. Visiting acts as if we closed a tab and opened a fresh one
cy.visit('https://example.cypress.io/commands/querying')
})
这里就是在前置钩子函数里面访问了https://...../querying
这个链接。如果代码需要浏览器调试,比如用户交
互点击,用户输入之类的。第一步就是访问:cy.visit
cy.get
还是从 example_spec.js 问中说起:
it('cy.get() - query DOM elements', function() {
// https://on.cypress.io/get
// Get DOM elements by id
cy.get('#query-btn').should('contain', 'Button')
// Get DOM elements by class
cy.get('.query-btn').should('contain', 'Button')
cy.get('#querying .well>button:first').should('contain', 'Button')
// ↲
// Use CSS selectors just like jQuery
})
这里定义了一个测试单元,在这个里面做了啥呢?第一步获取 id 为 query-btn 这个按钮。接下来 should 操作
,奉上一张表自行查看:
cy.get 还有一个玩法就是 cy.get('@app')这种,意思说之前你已经cy.get('.app').as('app')
,不需要再次获
取了,直接使用别名就好了
从官网截图的表格,详
细jquery-chai 文档表格
这里看到cy.get()
和jquery.$
是不是很像,在官网这里说了这样一句话:
The querying behavior of this command matches exactly how $(…) works in jQuery.
所以可以将 cy.get()当$一样来用即可,不过这里返回的不过 jquery 对象罢了,这里返回的事通过 cypress 包
装过的对象可以在控制台看到这样的东西,见下图:
是一个用于 cypress 所有方法的对象。然后可以操作他的 api 了。
第一部分,主要是查询,查询页面元素是否按照我们开发想要的存在,下面看第二部分:
context('Actions', function() {
beforeEach(function() {
cy.visit('https://example.cypress.io/commands/actions')
})
// Let's perform some actions on DOM elements
// https://on.cypress.io/interacting-with-elements
it('.type() - type into a DOM element', function() {
// https://on.cypress.io/type
cy
.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
// .type() with special character sequences
.type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
.type('{del}{selectall}{backspace}')
// .type() with key modifiers
.type('{alt}{option}') //these are equivalent
.type('{ctrl}{control}') //these are equivalent
.type('{meta}{command}{cmd}') //these are equivalent
.type('{shift}')
// Delay each keypress by 0.1 sec
.type('slow.typing@email.com', { delay: 100 })
.should('have.value', 'slow.typing@email.com')
cy
.get('.action-disabled')
// Ignore error checking prior to type
// like whether the input is visible or disabled
.type('disabled error checking', { force: true })
.should('have.value', 'disabled error checking')
})
})
这一部分主要是进行获取元素交互, 下面来说交互是如何搞得。 与 cy.get 相似还有:
- cy.contains 通过文本获取元素
- cy.closet 见 jqery
- cy.next/cy.nextAll 可以和 cy.contains 联合使用获取该节点的下一个节点
- cy.prev/cy.prevAll 同上
- cy.children/cy.parents/cy.parent 获取子节点/ 所有的父节点 / 父节点
- cy.first/cy.last
- cy.url 获取当前页面 url
- cy.title 获取当前页面标题
- ... API 挺多的,同样奉
上api 文档
cypress 交互逻辑
既然要交互肯定需要点击输入滚动,可以还存在拖拽等等。咱们就暂时从输入开始说起啦
cy.type
这不是一个可以直接使用的方法,要配合cy.get
使用的,作用是给空间进行输入。例如:
测试输入例如 text, textarea
cy.get('input').type('hello world')
测试 tabIndex
<div class="el" tabIndex="1">
This is TabIndex div.
</div>
cy.get('.el').type('laldkadaljdkljasf') // 这个里面是随机字符串
测试 input 为日期的
cy.get('input[type=date]').type('2008-8-9')
键盘绑定
下面直接是对 input 进行组合键盘操作
cy.get('input').type('{shift}{alt}Q')
按住键盘操作
cy.get('input').type('{alt}这里是按了一下alt后输入的内容')
还有长按键盘之类的操作,详细就看官网了这里之类奉上链
接https://docs.cypress.io/api/commands/type.html#Key-Combinations
这里就是关于键盘的组合操作。
对于选择例如 radio, checkbox
这些就只需要利用点击事件即可,如下:
cy
.get('input[type=radio]')
.as('radio')
.click()
cy.get('@radio').should('be.checked')
定时
cy.wait
下面是等待 1s
cy.wait(1000)
cy.clock 和 cy.tick
自己的代码:
var seconds = 0
setInterval(() => {
$('#seconds-elapsed').text(++seconds + ' seconds')
}, 1000)
测试代码
cy.clock()
cy.visit('/index.html')
cy.tick(1000)
cy.get('#seconds-elapsed').should('have.text', '1 seconds')
cy.tick(1000)
cy.get('#seconds-elapsed').should('have.text', '2 seconds')
这里就会出现关于 clock 和 tick
的用法,更多用法看文档,我也有部分迷惑的。待后来再解决。老规矩文档地址:
地址
关于 cypress 的配置
先复制一段出来:
{
"baseUrl": "http://localhost:8080",
"pageLoadTimeout": 3000,
"viewportHeight": 667,
"viewportWidth": 375
}
这是一个非常精简的配置了:
- baseUrl 基础链接,之后在是使用 cy.visit 的时候,只需要访问具体路由例如: cy.visit('/Hello')
-
viewport 两个属性
- viewportHeight 测试窗口的高度
- viewportWidth 测试窗口的宽度
- pageLoadTimeout 页面家安在超过 3000ms 即为超时。
总结
上面是 cypress 的基本用法,cypress 是基于 electron 的一个测试框架,提供 web 环境进行点对点的测试,在
programer 思维下,进行自动化的交互操作,必要点检测说明,这是一个非常棒的用处。例如之后拥有数据埋点,
可以在固定的位置检测是否有埋点。测试想要的地方是否匹配的数据。模拟用户的点击操作,这都是非常棒的。在
jquery 操作年代,各种 id 和 class 奇怪命名下,这些都可以容易找到,在 vue 和 react 大行其道的年代,但
是却可以通过文本寻找节点。这也是非常棒的体验,更多秘密需要去体验,奉上官方地址
:官网 cypress
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。