Cypress快速部署+使用指南+视觉回归测试

1,376 阅读5分钟

官方文档

Testing Your App | Cypress Documentation

部署

下载cypress

npm install cypress --save-dev

下载各种需要用到的插件,不需要可以跳过

npm i -D cypress-image-diff-js //图片对比插件
npm i -D moment@2.29.1  //时间插件
npm i -D js-md5@0.7.3  //md5加密
npm i -D mochawesome //生成测试报告
npm i -D eslint-plugin-cypress //eslint代码检查 
npm install mochawesome-merge --save-dev // 合并生成报告

添加快速启动命令

// package.json
{
  "scripts": {
    "cypress:open": "npx cypress open",
    "cypress:run": "npx cypress run""cypress:report": "node cypress/cypress.js"
  },
  "devDependencies": {
    "cypress": "^10.3.0",
    "cypress-image-diff-js": "^1.19.2",
    "js-md5": "^0.7.3",
    "mochawesome": "^7.1.3",
    "moment": "^2.29.1"
  }
}

打开Cypress启动面板。

 npm run cypress:open

选择E2E测试,Cypress会自动生成相关的目录和文件。

目录结构

  • cypress/e2e:存放测试脚本的目录,可以按照页面进行区分,一个页面对应一个/多个测试文件。
  • cypress/e2e/utlis:存放测试脚本里可复用的通用函数。
  • cypress/fixtures:存放测试脚本需要用到的静态数据(JSON格式)。
  • cypress/support:存放可复用的自定义指令。
  • cypress/.eslintrc.json:eslint配置文件。
  • cypress-visual-screenshots:视觉回归测试的截图存放目录。// 执行一次视觉回归自动生成
  • mochawesome-report:测试报告的存放目录。 // 执行一次生成测试报告自动生成
  • cypress.config.js:框架的全局配置文件。
  • cypress/cypress.js: 配置合并报告的函数存放的位置

全局配置文件

框架配置文件

// cypress.config.js
const { defineConfig } = require("cypress");
const imageDiff = require("cypress-image-diff-js/dist/plugin");
module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      imageDiff(on, config); // 引入插件
      return config;
    },
    viewportWidth: 1920, // 窗口分辨率
    viewportHeight: 1080,
    experimentalSessionAndOrigin: true, // 使用cy.session
    baseUrl: 'https://localhost:xxxx', // url前缀
    video: false, // 不录制视频
  },
  reporter: 'mochawesome', // 生成报告的依赖名
  reporterOptions: {
    reportFilename: "[name]-report",  // 生成的报告名
    overwrite: false,  // 是否重写
    html: true, // 是否生成html文件
    json: true  // 是否生成json文件
  }
});

eslint代码检查文件

文档:GitHub - cypress-io/eslint-plugin-cypress: An ESLint plugin for projects that use Cypress

// .eslintrc.json
{
    "extends": [
        "plugin:cypress/recommended"
    ]
}

添加自定义指令

// support/commands.js
import compareSnapshotCommand from 'cypress-image-diff-js/dist/command'
import md5 from 'js-md5'
compareSnapshotCommand()
Cypress.Commands.add('login', (username, password) => {
    const login = () => {
        // 两种登陆方法可以二选一
        // 通过页面登陆
        // cy.visit('/login')         
        // cy.get('#login_username').type(username)         
        // cy.get('#login_password').type(password)         
        // cy.contains('登 录').click()         
        // cy.url().should('include', '/monitor')
        // 通过请求登陆
        cy.request({
            method: 'POST',
            url: '/api/login',
            body: { username, password:md5(`${password}sdb`) },
          }).then((req) => {
            // ...
          })
    }
    cy.session([username, password], login)
})

✍️测试脚本编写方法

模板

describe('测试组名称', () => {
  before(() => {
    console.log(' --- 在当前 describe 中所有 it 执行前,运行一次 --- ')
  })
  after(() => {
    console.log(' --- 在当前 describe 中所有 it 执行后,运行一次 --- ')
  })
  beforeEach(() => {
    console.log(' --- 在当前 describe 中每个 it 执行前,运行一次 --- ')
  })
  afterEach(() => {
    console.log(' --- 在当前 describe 中每个 it 执行后,运行一次 --- ')
  })
 
  it('测试用例1', () => {
    // 在这里写测试逻辑...
  })
 
  it('测试用例2', () => {
    // 在这里写测试逻辑...
  })
 
})

例子

编写步骤:

  1. 先执行登录操作获取权限
  2. 使用GUI获取DOM元素的脚本语言,复制到测试脚本里。

  1. 根据测试用例逻辑编写测试脚本
import moment from 'moment'
moment.locale('zh-cn')
// describe 将测试用例分组,便于阅读和管理。 
describe("时间范围", () => {
    // beforeEach代表每次执行it的用例前执行的函数
    beforeEach(() => {
        cy.login('username', 'password')
        cy.visit('/sequoiadb/performance')
    })
    // 抽离重复的逻辑进行服用     
    const assertTimeRange = (time) => {
        cy.get('[placeholder="开始日期"]').should('have.value', moment().startOf(time).format('yyyy-MM-DD'))
        cy.get('[placeholder="结束日期"]').should('have.value', moment().endOf(time).format('yyyy-MM-DD'))
    }
    // it是一个完整的单个用例(case),是用例的全部流程,可以操作dom,执行对应的操作,并通过断言判断正确与否     
    it("年月周日的时间范围验证", () => {
        cy.get('.time > .flex-jc-start > :nth-child(1)').click().then(() => {
            // expect(element[0]).to.have.class('activeTime') 这是检查css的例子            
            assertTimeRange('day')
        })
        cy.get('.time > .flex-jc-start > :nth-child(2)').click().then(() => {
            assertTimeRange('week')
        })
        cy.get('.time > .flex-jc-start > :nth-child(3)').click().then(() => {
            assertTimeRange('month')
        })
        cy.get('.time > .flex-jc-start > :nth-child(4)').click().then(() => {
            assertTimeRange('year')
        })
    })
});

测试结果:

👀视觉回归测试方法

文档

GitHub - uktrade/cypress-image-diff: Visual regression test with cypress

目录结构

  • baseline:基准图片的存放位置,第一次执行视觉回归测试时,会以第一次截图作为基准图片。
  • comparison:对比图片的存放位置,每次执行视觉回归测试时,截图的图片都会存放在此目录,然后会与baseline目录里的同名图片自动对比。
  • diff:当两张图片对比大于脚本里写的阈值,就会在diff文件里生成同名的截图,该目录的截图会标出两张图片对比后哪里差异比较大。

核心方法

const retryOptions = { limit: 5, retriesdelay: 500 }
cy.compareSnapshot('图片名', 0.2, retryOptions)
  • 参数1是生成的截图命名。
  • 参数2是图片对比的阈值,阈值用于描述图片最大允许的差异程度,取值0~1,值越小,允许的差异越少,默认值为0。
  • 参数3是超过阈值时重试截图的参数,limit代表重试多少次,retriesdelay代表重试前等待多少ms。

例子

describe("视觉回归测试", () => {
    beforeEach(() => {
        cy.login('username', 'password')
        cy.visit('/sequoiadb/performance')
    })
    it("趋势分析页面",  () => {
        // eslint-disable-next-line cypress/no-unnecessary-waiting         
        cy.wait(3000)
        cy.compareSnapshot('趋势分析页面', 0.2)
    })
  })

图片正常时

基准图片:

测试结果:

图片差异为0,小于设置的0.2阈值,测试通过。

图片不正常时

对比图片:

测试结果:

图片差异为0.88,大于设置的0.2阈值,测试不通过。

diff目录会显示出两张图片不一样的地方。

需要注意的点

  • 运行测试时截图的分辨率很重要,请确保每次测试时全局配置文件内的屏幕宽高分辨率一致。
  • 尽管将截图分辨率设置为特定的高度和宽度,但如果测试是在不同尺寸的屏幕上运行,结果也有可能是不一样的,请确保测试运行在同一屏幕。

生成测试报告

具体如何生成可以去mochawesome-report的官方仓库下查看,生成后的测试报告在mochawesome-report目录下,点击即可打开。