专栏首页自动化、性能测试Cypress系列(63)- 使用 Custom Commands

Cypress系列(63)- 使用 Custom Commands

Custom Commands 自定义命令介绍

  • Custom Commands 被认为是替代 PageObject 的良好选择
  • 使用 Custom Commands 可以创建自定义命令和替换现有命令
  • Custom Commands 默认存放在 文件中,它会在任何测试文件被导入之前加载( 定义在 cypress/support/index.js )

cypress/support/commands.js

语法格式

Cypress.Commands.add(name, callbackFn)
Cypress.Commands.add(name, options, callbackFn)
Cypress.Commands.overwrite(name, callbackFn)

参数说明

  • name:要添加或覆盖的命令的名称
  • callbackFn :自定义命令的回调函数,回调函数里自定义函数所需完成的操作步骤
  • options:允许自定义命令的隐性行为

options 可选参数列表

参数

可接受的值类型

默认

描述

prevSubject

Boolean, String or Array

false

如何处理前面产生的对象

prevSubject 可选值

  • false:忽略任何以前的主题(父命令)
  • true:接收上一个主题(子命令)
  • optional:可以启动链,也可以使用现有链(双命令)

除了控制命令的隐式行为,您还可以添加声明性主题验证,例如:

  • element:要求上一个主题是DOM元素
  • document:要求上一个主题为文档
  • window:要求上一个主题是窗口

Cypress 内置命令利用了上述可选值组合中的每一个

注意:仅在 Cypress.Commands.add() 中支持使用options,而在 Cypress.Commands.overwrite() 中不支持使用options

正确用法

Cypress.Commands.add('login', (email, pw) => {})
Cypress.Commands.overwrite('visit', (orig, url, options) => {}) 

前期准备

启动 Cypress 提供的演示项目

cmd 窗口进入下面的文件夹

执行下面的命令

npm start

Custom Commands 的简单栗子

command.js 的代码

在 cypress/support/commands.js 中写如下代码

Cypress.Commands.add('login', (username, pwd) => {
    cy.get('input[name=username]').type(username)
    cy.get('input[name=password]').type(`${pwd}{enter}`)
})

testlogin.js 测试用例文件的代码

context('登录测试,PO 模式', function () {

    const username = 'jane.lane'
    const pwd = 'password123'

    it('登录成功', function () {
        // 创建 po 实例
        const loginInstance = new LoginPage()
        loginInstance.visitPage()
        loginInstance.isTargetPage()

        // 调用 Custom Commands 的命令
        cy.login(username, pwd)
        cy.url().should('include', '/dashboard')

        const manInstance = new mainPage()
        manInstance.isTargetPage()
        manInstance.welComeText.should('contain', 'jane.lane')
    });
})

测试结果

Customn Commands 的好处

  • 定义在 中的命令可以像 Cypress 内置命令那样直接使用,无须 import 对应的 page(实际上 PageObject 模式在 Cypress 看来无非是数据/操作函数的共享)

cypress/support/command.js

  • 自定义命令可以比 PageObject 模式运行更快,Cypress 和应用程序运行在同一个浏览器中,意味着 Cypress 可以直接发送请求到应用程序并设置运行测试所需要的用户状态,而这一切通常无须通过页面操作,这使得使用了自定义命令的测试会更加稳定
  • 自定义命令允许重写 Cypress 内置命令,意味着可以自定义测试框架并立刻全局应用

Custom Commands 完全替换 PageObject 模式的栗子

command.js 代码

在 cypress/support/commands.js 中写如下代码

Cypress.Commands.add('login', (username, pwd) => {
    Cypress.log({
        name: 'login',
        message: `${username} | ${pwd}`
    })

    return cy.request({
        method: 'POST',
        url: '/login',
        form: true,
        body: {
            username: username,
            password: pwd
        }
    })
})

.request() 命令在后面文章会继续介绍

testLogin.js 测试用例文件代码

无须 PageObject 模型,直接在 integration 文件夹下建立 testLogin.js 测试用例文件

context('登录测试,PO 模式', function () {

    const username = 'jane.lane'
    const pwd = 'password123'

    beforeEach(function () {
        cy.login(username, pwd)
    })

    it('访问受保护页', function () {
        // cy.request() 登录成功后,cypress 会自动保存 session cookie
        // 所以下面就可以访问登录后才能访问的页面
        cy.visit('/dashboard')
        cy.url().should('eq', 'http://localhost:7077/dashboard')
        cy.get('h1').should('contain', 'jane.lane')
    });
})

overwrite 覆盖 visit 命令的栗子

// 第一个参数代表需要覆盖的命令
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
    const domain = Cypress.env('BASE_DOMAIN')

    if (domain === '...') {
        url = '...'
    }

    if (options.something === 'else') {
        url = '...'
    }

    // originalFn 代表传入进来的原 visit 命令
    //
    // 记得需要在最后 return
    return originalFn(url, options)
})

overwrite 覆盖 type 命令的栗子

如果在密码字段中键入内容,密码输入将在应用程序中自动屏蔽。但是 .type() 会自动将所有键入的内容记录到测试运行程序的命令日志中

cy.get('#username').type('username@email.com')
cy.get('#password').type('superSecret123')

实际情况

  1. 可能需要屏蔽传递给 命令的某些值,以便敏感数据不会显示在测试运行的屏幕截图或视频中

.type()

  1. 下面的示例将覆盖 命令,以允许屏蔽测试运行程序的命令日志中的敏感数据

.type()

Cypress.Command.overwrite() 代码

Cypress.Commands.overwrite('type', (originalFn, element, text, options) => {
    if (options && options.sensitive) {
        options.log = false
        // 创建自己的日志
        Cypress.log({
            $el: element,
            name: 'type',
            message: '*'.repeat(text.length),
        })
    }

    return originalFn(element, text, options)
})

测试用例代码

cy.get('input[name=username]').type(username)
cy.get('input[name=password]').type(pwd, {sensitive: true})

测试结果

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Cypress系列(89)- Cypress.log 命令详解

    https://www.cnblogs.com/poloyy/category/1768839.html

    小菠萝测试笔记
  • Cypress系列(2)- Cypress 框架的详细介绍

    https://www.cnblogs.com/poloyy/category/1768839.html

    小菠萝测试笔记
  • Cypress系列(11)- Cypress 编写和组织测试用例篇 之 动态生成测试用例

    https://www.cnblogs.com/poloyy/category/1768839.html

    小菠萝测试笔记
  • Cypress系列(2)- Cypress 框架的详细介绍

    https://www.cnblogs.com/poloyy/category/1768839.html

    小菠萝测试笔记
  • 你不知道的Cypress系列(3) -- 是时候重构自己的思维了!

    在跟同学们的交流中,我也了解到, 原来除了国外优秀的公司(例如Adobe, 迪士尼,AutoDesk等等), 国内也有很多公司在尝试使用Cypress提升测试效...

    iTesting
  • Cypress系列(86)- Cypress.version 命令详解

    https://www.cnblogs.com/poloyy/category/1768839.html

    小菠萝测试笔记
  • Cypress系列(85)- Cypress.platform 命令详解

    https://www.cnblogs.com/poloyy/category/1768839.html

    小菠萝测试笔记
  • Cypress基础指南

    下面我们看下Cypress完整的工作过程是怎么样的,为什么我们需要学习下Cypress,如图所示:

    苦叶子
  • 使用信号进制实现进程通信

    而在应用系统开发中,我们常用的方式就是消息队列和套接字两种方式。在程序中写了一个死循环,运行时,常使用<code>ctrl+c</code>来中断进程。突然软件...

    暮雨
  • SpringBoot集成RabbitMQ

    添加依赖 配置 无法远程连接,需要配置文件 cd etc/rabbitmq

    公众号-JavaEdge

扫码关注云+社区

领取腾讯云代金券