Basic knowledge of front-end automated testing framework Cypress

1. Cypress directory and environment construction

(1) Install Cypress

  • Online installation using npm
    npm install cypress --save-dev
  • Offline installation
    Step 1: Download the cpress.zip compressed package from the official website☟Click to download
    Step 2: Configure system environment variables
    CYPRESS_INSTALL_BINARY 下载并安装的Cypress二进制文件的目标位置
    Step 3: Execute the installation command☞Official
    CYPRESS_INSTALL_BINARY=2.0.1 npm install [email protected]
    website api

(2) Directory structure

Insert image description here

  • Save in support folder, specify collection
/**
 - 编写人:
 - 日期:
 - 目的:登录
 - 参数说明:
 */
Cypress.Commands.add("login", (userName, password) => {
    
    
  cy.visit('/#/login-page')
  cy.get("#app > div input").type(userName)
  cy.get("#secpwd").type(password)
  cy.get("#app > button").click()
})
  • Store test cases in the specs directory
describe('My First Test', function() {
    
    
  before(() => {
    
    
    // 在全部案例执行之前执行一次
    // 浏览器模式访问时,可按照自己的需要设置窗口大小,如 cy.viewport(1920,1100)
    // 访问首页
    cy.visit('http://localhost:2000/#/input-demo')
  })
  after(() => {
    
    
    // 在全部案例执行完成之后执行一次
  })
  beforeEach(() => {
    
    
    // 在每一条案例之前执行
  })
  afterEach(() => {
    
    
    // 在每一条案例执行完成之后执行
  })
  
  it('Does not do much!', function() {
    
    
    expect(true).to.equal(false)
  })
  
  it('Gets, types and asserts', function() {
    
    
    cy.visit('https://example.cypress.io')

    cy.contains('type').click()

    // 应该存在一个包含'/commands/actions'的新URL
    cy.url().should('include', '/commands/actions')

    // 获取一个输入, 输入进去并且验证文本值已经更新了
    cy.get('.action-email')
      .type('[email protected]')
      .should('have.value', '[email protected]')
  })
})

2. Run the case test

  • Configuration instructions
    "test:e2e-gui": "vue-cli-service test:e2e --mode development"
  • Page operation
    Insert image description here
    click on the required test file as follows
    Insert image description here

3. Cypress closure environment variables

1. describe

describe('', () => { // Various hook functions before(() => { // Executed once before all cases are executed }) after(() => { // Executed after all cases are executed. Once }) beforeEach(() => { // Executed before each case }) afterEach(() => { // Executed after each case is executed }) it('Test form validation case', () => {}) // Only execute this case it.only('Test form validation case', () => {}) // Ignore this case it.skip('Test form validation case', () => { }) })


















2. Environment variables in hook functions

  1. You can access the cy object
    and pass in the selector, which is essentially implemented by the jquery selector, so the usage is consistent.
    const $cyElement = cy.get('.demo-ruleForm > .el-form-item:first-child input')
    
  2. Similar to jquery, you can chain call
    the style selector connection like this
cy.get('.demo-ruleForm > .el-form-item:first-child input')
     .should('have.value', '')
     .focus()
     .blur()
  1. js basic variable syntax
    js basic syntax api supports both, but is slightly different
 const arr = [];
 arr.forEach 可以访问
 [].forEach 不可以访问
  1. expect asset assertion
assert.isOk('everything', 'everything is ok')
expect('Jane').to.not.equal('Jane')
  1. Cypress object
    Cypress provides all APIs of cy, in addition, there is an additional .$() method for returning jquery objects, which
    is convenient for operating dom

3. Environment variables in should

Can access Cypress object
js basic variable syntax

const $cyElement = cy.get('.demo-ruleForm > .el-form-item:first-child input')
$cyElement.should($el => {
    
    
      // 闭包环境里可以访问Cypress是个可以操作dom集合
      // Cypress.dom 返回dom的api
      // Cypress.$(dom) 返回jquery对象
      const isDom = Cypress.dom.isDom($el)
      const $jqEl = Cypress.$($el[0])
      expect(isDom).to.be.true
    })
  • Cypress.$() returns a jQuery object and can access jquery’s api
  • Cypress.dom returns the dom API
  • Cpress.cy returns the cy instance, which can be asserted similarly to the hook function

4. Case

code show as below:

// https://docs.cypress.io/api/introduction/api.html

describe('自动化测试表单验证案例', () => {
    
    
  before(() => {
    
    
    // 在全部案例执行之前执行一次
    // 浏览器模式访问时,可按照自己的需要设置窗口大小,如 cy.viewport(1920,1100)
    // 访问首页
    cy.visit('http://localhost:2000/#/input-demo')
  })
  after(() => {
    
    
    // 在全部案例执行完成之后执行一次
  })
  beforeEach(() => {
    
    
    // 在每一条案例之前执行
  })
  afterEach(() => {
    
    
    // 在每一条案例执行完成之后执行
  })

  // 案例一、测试表单验证案例
  it('测试表单验证案例', () => {
    
    
    cy.get('.demo-ruleForm > .el-form-item:first-child input')
      .should('have.value', '')
      .focus()
      .blur()
    cy.get('.demo-ruleForm .el-form-item__error')
      .should('contain', '请输入活动名称')
    cy.get('.demo-ruleForm > .el-form-item:first-child input').type('测试数据')
      .blur()
    cy.get('.demo-ruleForm .el-form-item__error')
      .should('not.be.visible')
    cy.get('.demo-ruleForm > .el-form-item:first-child input').type('测试数据测试数据')
      .blur()
    cy.get('.demo-ruleForm .el-form-item__error')
      .should('contain', '长度在 3 到 5 个字符')
  })

  // 案例二、测试一些闭包环境变量及api
  it('测试表单验证案例', () => {
    
    
    // This is fine, jQuery returns the element synchronously.
    // const $jqElement = $('.demo-ruleForm > .el-form-item:first-child input')
    // This will not work! Cypress does not return the element synchronously.
    const $cyElement = cy.get('.demo-ruleForm > .el-form-item:first-child input')
    // cy操作类型jquery传入selector选择器,但不可以直接操作dom
    // 类似jquery可以链式调用
    // js基本变量语法
    // 但稍有不同
    const arr = [];
    // arr.forEach 可以访问
    // [].forEach 不可以访问
    $cyElement.should($el => {
    
    
      // 闭包环境里可以访问Cypress是个可以操作dom集合
      // Cypress.dom 返回dom的api
      // Cypress.$(dom) 返回jquery对象
      const isDom = Cypress.dom.isDom($el)
      const $jqEl = Cypress.$($el[0])
      expect(isDom).to.be.true
    })
  })
})

4. Get dom elements

1.get

Usage 1. Selector positioning

cy.get(selector)

Usage 2. Positioning by alias

cy.get(alias)

When matching multiple elements, multiple objects are returned

2.find

cy.get(selector).find(selector1)

Positioning method, used to search the descendants of the positioned element in the DOM tree, such as get the selected descendant element

// 错误写法
cy.find(selector)

An error will be reported and a parent class is required to select the element.
Insert image description here

3.contains

Two usages are as follows:

.contains(content)
.contains(selector, content)

Support cy.contains, and cy.get().contains
重点:只会返回第一个匹配到的元素

4.first

Similar to jquery’s first method

5.eq

Similar to jquery's eq method, eq(index) index starts from 0 to get the first element and child element.

5. Get/set DOM element attributes! ! !

1. cy.$$(selector,context) ☆☆☆

cy.$$('input') // 返回input元素的jquery对象
cy.$$('input').value() // 可用用jquery的api
cy.$$('input').text() // 例子,等等

The cy object is mounted under the window, so it can be accessed when the environment variable this points to the window. Generally, the top-level scope points to this window. You can use the arrow function to point the internal scope to the window to access cy.

2. Cypress.$(selector) ☆☆☆

Cypress.$('input') // 返回input元素的jquery对象
Cypress.$('input').value() // 可用用jquery的api
Cypress.$('input').text() // 例子,等等

The Cypress object is mounted under the window, so it can be accessed when the environment variable this points to the window. Generally, the top-level scope points to this window. You can use the arrow function to point the internal scope to the window to access Cypresss.

3.should callback function☆☆☆

  • The formal parameter $e is a jquery object
  • Cpress.$ returns jquery object

Use jquery's api to get the dom attribute of the element

cy.get('.dom-demo')
      .should($e => {
    
    
        // $e jquery对象
        // Cpress.$ 返回jquery对象
        const text = $e.find('.item').first().text();
        const text1 = Cypress.$($e[0]).find('.item').first().text();
        console.log(text === text1) // true
      })

4.Type method of cy object

Input to input box

cy.get('input').type('text')
cy.get('input').type('2222')

6. Mouse events

1. Click event click

// 点击事件
cy.get('#btn').click()

2.Hover event hover

The version does not support this event. There are alternatives as follows:

cy.get('#btn')
  .trigger('mouserover')
  .wait(3000)
  .rightclick()
  .wait(3000)
  .should('have.css', 'color', 'rgb(255, 255, 255)')

3. Double addition event dblclick

// 双击事件
cy.get('#btn').dblclick()

4. Right click event rightclick

// 右击事件
cy.get('#btn').rightclick()

5. Focus event focus

// 聚焦事件
cy.get('input').focus()

6. Out-of-focus event blur

// 失焦事件
cy.get('input').blur()

Summary case

// 案例三、测试鼠标一些事件
  it('测试鼠标一些事件', () => {
    
    
    // 点击事件
    cy.get('#btn')
      .click()
    // 双击事件
    cy.get('#btn')
      .dblclick()
    // 右击事件
    cy.get('#btn')
      .rightclick()
    // 悬浮事件
    // cy.get('#btn').hover()
    // 该事件本版本不支持
    // 代替方案如下:
    cy.get('#btn')
      .trigger('mouserover')
      .wait(3000)
      .rightclick()
      .wait(3000)
      .should('have.css', 'color', 'rgb(255, 255, 255)')
    // 聚焦事件
    cy.get('#int')
      .focus()
    // 失焦事件
    cy.get('#int')
      .blur()
  })

7. Assert should, expect

每条案例都需要加断言,及验证点,否则是一条不完整的案例

(1), should assertion

1. dom assertion

  1. Length
// retry until we find 3 matching <li.selected>
cy.get('li.selected').should('have.length', 3)
  1. Class
// retry until this input does not have class disabled
cy.get('form').find('input').should('not.have.class', 'disabled')
  1. Value
// retry until this textarea has the correct value
cy.get('textarea').should('have.value', 'foo bar baz')
  1. Text Content
// retry until this span does not contain 'click me'
cy.get('a').parent('span.help').should('not.contain', 'click me')
  1. Visibility
// retry until this button is visible
cy.get('button').should('be.visible')
  1. Existence
// retry until loading spinner no longer exists
cy.get('#loading').should('not.exist')
  1. State
// retry until our radio is checked
cy.get(':radio').should('be.checked')
  1. CSS
// retry until .completed has matching css
cy.get('.completed').should('have.css', 'text-decoration', 'line-through')
// retry until .accordion css have display: none
cy.get('#accordion').should('not.have.css', 'display', 'none')

2. Callback function

cy.get('div')
  .should(($div) => {
    
    
    expect($div).to.have.length(1)

    const className = $div[0].className

    // className will be a string like "main-abc123 heading-xyz987"
    expect(className).to.match(/heading-/)
  })

(2), expect affirmation

1. When asserting that the input parameter is not a DOM object

Chain Example
not expect(name).to.not.equal(‘Jane’)
deep expect(obj).to.deep.equal({ name: ‘Jane’ })
nested expect({a: {b: [‘x’, ‘y’]}}).to.have.nested.property(‘a.b[1]’) expect({a: {b: [‘x’, ‘y’]}}).to.nested.include({‘a.b[1]’: ‘y’})
ordered expect([1, 2]).to.have.ordered.members([1, 2]).but.not.have.ordered.members([2, 1])
any expect(arr).to.have.any.keys(‘age’)
all expect(arr).to.have.all.keys(‘name’, ‘age’)
a(type) Aliases: an expect(‘test’).to.be.a(‘string’)
include(value) Aliases: contain, includes, contains expect([1,2,3]).to.include(2)
ok expect(undefined).to.not.be.ok
true expect(true).to.be.true
false expect(false).to.be.false
null expect(null).to.be.null
undefined expect(undefined).to.be.undefined
exist expect(myVar).to.exist
empty expect([]).to.be.empty
arguments Aliases: Arguments expect(arguments).to.be.arguments
equal(value) Aliases: equals, eq expect(42).to.equal(42)
deep.equal(value) expect({ name: ‘Jane’ }).to.deep.equal({ name: ‘Jane’ })
eql(value) Aliases: eqls expect({ name: ‘Jane’ }).to.eql({ name: ‘Jane’ })
greaterThan(value) Aliases: gt, above expect(10).to.be.greaterThan(5)
least(value)Aliases: gte expect(10).to.be.at.least(10)
lessThan(value) Aliases: lt, below expect(5).to.be.lessThan(10)
most(value) Aliases: lte expect(‘test’).to.have.length.of.at.most(4)
within(start, finish) expect(7).to.be.within(5,10)
instanceOf(constructor) Aliases: instanceof expect([1, 2, 3]).to.be.instanceOf(Array)
property(name, [value]) expect(obj).to.have.property(‘name’)
deep.property(name, [value]) expect(deepObj).to.have.deep.property(‘tests[1]’, ‘e2e’)
ownProperty(name) Aliases: haveOwnProperty, own.property expect(‘test’).to.have.ownProperty(‘length’)
ownPropertyDescriptor(name) Aliases: haveOwnPropertyDescriptor expect({a: 1}).to.have.ownPropertyDescriptor(‘a’)
lengthOf(value) expect(‘test’).to.have.lengthOf(3)
match(RegExp) Aliases: matches expect(‘testing’).to.match(/^test/)
string(string) expect(‘testing’).to.have.string(‘test’)
keys(key1, [key2], […]) Aliases: key expect({ pass: 1, fail: 2 }).to.have.keys(‘pass’, ‘fail’)
throw(constructor) Aliases: throws, Throw expect(fn).to.throw(Error)
respondTo(method) Aliases: respondsTo expect(obj).to.respondTo(‘getName’)
itself expect(Foo).itself.to.respondTo(‘bar’)
satisfy(method) Aliases: satisfies expect(1).to.satisfy((num) => { return num > 0 })
closeTo(expected, delta) Aliases: approximately expect(1.5).to.be.closeTo(1, 0.5)
members(set) expect([1, 2, 3]).to.include.members([3, 2])
oneOf(values) expect(2).to.be.oneOf([1,2,3])
change(function) Aliases: changes expect(fn).to.change(obj, ‘val’)
increase(function) Aliases: increases expect(fn).to.increase(obj, ‘val’)
decrease(function) Aliases: decreases expect(fn).to.decrease(obj, ‘val’)

2. 断言入参是dom对象时

Chainers Assertion
attr(name, [value]) expect($el).to.have.attr(‘foo’, ‘bar’)
prop(name, [value]) expect($el).to.have.prop(‘disabled’, false)
css(name, [value]) expect($el).to.have.css(‘background-color’, ‘rgb(0, 0, 0)’)
data(name, [value]) expect($el).to.have.data(‘foo’, ‘bar’)
class(className) expect($el).to.have.class(‘foo’)
id(id) expect($el).to.have.id(‘foo’)
html(html) expect($el).to.have.html(‘I love testing’)
text(text) expect($el).to.have.text(‘I love testing’)
value(value) expect($el).to.have.value(‘[email protected]’)
visible expect($el).to.be.visible
hidden expect($el).to.be.hidden
selected expect($option).not.to.be.selected
checked expect($input).not.to.be.checked
focus[ed] expect($input).not.to.be.focused expect($input).to.have.focus
enabled expect($input).to.be.enabled
disabled expect($input).to.be.disabled
empty expect($el).not.to.be.empty
exist expect($nonexistent).not.to.exist
match(selector) expect($emptyEl).to.match(’:empty’)
contain(text) expect($el).to.contain(‘text’)
descendants(selector) expect($el).to.have.descendants(‘div’)

3.断言对象是 cy.stub() 或 cy.spy()时

Sinon.JS property/method Assertion
called expect(spy).to.be.called
callCount expect(spy).to.have.callCount(n)
calledOnce expect(spy).to.be.calledOnce
calledTwice expect(spy).to.be.calledTwice
calledThrice expect(spy).to.be.calledThrice
calledBefore expect(spy1).to.be.calledBefore(spy2)
calledAfter expect(spy1).to.be.calledAfter(spy2)
calledWithNew expect(spy).to.be.calledWithNew
alwaysCalledWithNew expect(spy).to.always.be.calledWithNew
calledOn expect(spy).to.be.calledOn(context)
alwaysCalledOn expect(spy).to.always.be.calledOn(context)
calledWith expect(spy).to.be.calledWith(…args)
alwaysCalledWith expect(spy).to.always.be.calledWith(…args)
calledWithExactly expect(spy).to.be.calledWithExactly(…args)
alwaysCalledWithExactly expect(spy).to.always.be.calledWithExactly(…args)
calledWithMatch expect(spy).to.be.calledWithMatch(…args)
alwaysCalledWithMatch expect(spy).to.always.be.calledWithMatch(…args)
returned expect(spy).to.have.returned(returnVal)
alwaysReturned expect(spy).to.have.always.returned(returnVal)
threw expect(spy).to.have.thrown(errorObjOrErrorTypeStringOrNothing)
alwaysThrew expect(spy).to.have.always.thrown(errorObjOrErrorTypeStringOrNothing)

(三)、assert断言

Assertion Example
.isOk(object, [message]) assert.isOk(‘everything’, ‘everything is ok’)
.isNotOk(object, [message]) assert.isNotOk(false, ‘this will pass’)
.equal(actual, expected, [message]) assert.equal(3, 3, ‘vals equal’)
.notEqual(actual, expected, [message]) assert.notEqual(3, 4, ‘vals not equal’)
.strictEqual(actual, expected, [message]) assert.strictEqual(true, true, ‘bools strict eq’)
.notStrictEqual(actual, expected, [message]) assert.notStrictEqual(5, ‘5’, ‘not strict eq’)
.deepEqual(actual, expected, [message]) assert.deepEqual({ id: ‘1’ }, { id: ‘1’ })
.notDeepEqual(actual, expected, [message]) assert.notDeepEqual({ id: ‘1’ }, { id: ‘2’ })
.isAbove(valueToCheck, valueToBeAbove, [message]) assert.isAbove(6, 1, ‘6 greater than 1’)
.isAtLeast(valueToCheck, valueToBeAtLeast, [message]) assert.isAtLeast(5, 2, ‘5 gt or eq to 2’)
.isBelow(valueToCheck, valueToBeBelow, [message]) assert.isBelow(3, 6, ‘3 strict lt 6’)
.isAtMost(valueToCheck, valueToBeAtMost, [message]) assert.isAtMost(4, 4, ‘4 lt or eq to 4’)
.isTrue(value, [message]) assert.isTrue(true, ‘this val is true’)
.isNotTrue(value, [message]) assert.isNotTrue(‘tests are no fun’, ‘val not true’)
.isFalse(value, [message]) assert.isFalse(false, ‘val is false’)
.isNotFalse(value, [message]) assert.isNotFalse(‘tests are fun’, ‘val not false’)
.isNull(value, [message]) assert.isNull(err, ‘there was no error’)
.isNotNull(value, [message]) assert.isNotNull(‘hello’, ‘is not null’)
.isNaN(value, [message]) assert.isNaN(NaN, ‘NaN is NaN’)
.isNotNaN(value, [message]) assert.isNotNaN(5, ‘5 is not NaN’)
.exists(value, [message]) assert.exists(5, ‘5 is not null or undefined’)
.notExists(value, [message]) assert.notExists(null, ‘val is null or undefined’)
.isUndefined(value, [message]) assert.isUndefined(undefined, ‘val is undefined’)
.isDefined(value, [message]) assert.isDefined(‘hello’, ‘val has been defined’)
.isFunction(value, [message]) assert.isFunction(x => x * x, ‘val is func’)
.isNotFunction(value, [message]) assert.isNotFunction(5, ‘val not funct’)
.isObject(value, [message]) assert.isObject({num: 5}, ‘val is object’)
.isNotObject(value, [message]) assert.isNotObject(3, ‘val not object’)
.isArray(value, [message]) assert.isArray([‘unit’, ‘e2e’], ‘val is array’)
.isNotArray(value, [message]) assert.isNotArray(‘e2e’, ‘val not array’)
.isString(value, [message]) assert.isString(‘e2e’, ‘val is string’)
.isNotString(value, [message]) assert.isNotString(2, ‘val not string’)
.isNumber(value, [message]) assert.isNumber(2, ‘val is number’)
.isNotNumber(value, [message]) assert.isNotNumber(‘e2e’, ‘val not number’)
.isFinite(value, [message]) assert.isFinite(‘e2e’, ‘val is finite’)
.isBoolean(value, [message]) assert.isBoolean(true, ‘val is bool’)
.isNotBoolean(value, [message]) assert.isNotBoolean(‘true’, ‘val not bool’)
.typeOf(value, name, [message]) assert.typeOf(‘e2e’, ‘string’, ‘val is string’)
.notTypeOf(value, name, [message]) assert.notTypeOf(‘e2e’, ‘number’, ‘val not number’)

8. Solutions to common project errors

Will continue to update. . .

Guess you like

Origin blog.csdn.net/qq_29510269/article/details/107447705