cypress-cucumber-preprocessor是Cypress对于cucumber功能进行增强的插件
安装
- 安装插件库:npm install --save-dev cypress-cucumber-preprocessor
- 修改插件配置文件 cypress/plugins/index.js
const cucumber = require('cypress-cucumber-preprocessor').default
module.exports = (on, config) => {
on('file:preprocessor', cucumber())
}
- 在项目配置文件cypress.json中设置feature文件目录
{
"testFiles": "**/*.{feature,features}",
"screenshotOnRunFailure": false,
"video": false
}
- 在package.json设置spec文件模式,如果为true,请使用Cypress Cucumber Preprocessor Style模式来放置步骤定义文件。如果为false,我们将使用“oldschool”(所有内容都是全局的)Cucumber样式。
"cypress-cucumber-preprocessor": {
"nonGlobalStepDefinitions": true
}
配置说明:
选项 | 默认值 | 描述 |
---|---|---|
commonPath | 当nononglobalstepdefinitions为true时,使用,cypress/integration/common,当nonGlobalStepDefinitions为false时,使用cypress/support/step_definitions,当nonGlobalStepBaseDir被定义时使用${nonGlobalStepBaseDir}/common | 定义包含测试的所有通用步骤定义的文件夹的路径。当定义了nonGlobalStepBaseDir时,这个路径就是从这个基本位置定义的。如$ {nonGlobalStepBaseDir} / $ {commonPath}。 |
nonGlobalStepDefinitions | false | 如果为true,请使用Cypress Cucumber Preprocessor Style模式来放置步骤定义文件。如果为false,我们将使用“oldschool”(所有内容都是全局的)Cucumber样式。 |
nonGlobalStepBaseDir | undefined | 如果defined和nononglobalstepdefinitions也为true,则步骤定义将从这里提供的目录开始搜索具有特性名称的文件夹 |
stepDefinitions | 当nononglobalstepdefinitions为true时,使用cypress/integration,当nonGlobalStepDefinitions为false时,使用cypress/support/step_definitions | 包含步骤定义的文件夹的路径 |
- 运行文件 cypress run --spec **/*.features
搭建测试工程
- 事件定义:在integration文件夹下新建.feature文件,如baidu.feature。
#language: zh-CN
功能: 百度主页
看到百度搜索页面
场景: 打开百度搜索
假如 打开百度首页
当 我看到"百度一下,你就知道"的标题
- 脚本定义:默认的项目结构中,每个.feature要有一个对应名字的同级文件夹,用来存放对应的.js文件,如cypress/integration/baidu.feature,脚本文件应为cypress/integration/Baidu/baidu.js。我们也可以将其脚本步骤分离放在cypress/integration/common中。示例:baidu.js
import { Before, After ,Then , Given } from "cypress-cucumber-preprocessor/steps";
const url = 'https://baidu.com'
Given('打开百度首页', () => {
cy.visit(url)
})
Then(`我看到{string}的标题`, (title) => {
cy.title().should('include', title)
})
当需要自定义脚本位置时,可在package.json添加配置
"cypress-cucumber-preprocessor": {
"step_definitions": "cypress/support/step_definitions/"
}
编写脚本
- 创建脚本文件引入相关方法,例如Given, When, Then
const {
Before,
After,
When,
Given,
Then
} = require("cypress-cucumber-preprocessor/steps");
- 与对应的.feature文件一一对应的步骤实现
Given("事件步骤内容", () => {
// ...test code here
})
- 参数接受
//1,普通参数
那么 我看到"百度一下,你就知道"的标题 //.feature内容
Then(`我看到{string}的标题`, (title) => { //.js脚本内容,string为参数类型
cy.title().should('include', title)
})
//2,数据列表形式
当 我使用的数据为: //.feature内容
| number | another number |
| 1 | 2 |
| 3 | 4 |
When("I add all following numbers:", (dataTable) => { //.js脚本内容,string为参
sum = dataTable.rawTable
.slice(1)
.reduce(
(rowA, rowB) =>
rowA.reduce((a, b) => parseInt(a, 10) + parseInt(b, 10)) +
rowB.reduce((a, b) => parseInt(a, 10) + parseInt(b, 10))
);
});
//3.示例列表形式
当 修改项目地址为<项目地址> //.feature内容
例子:
|项目地址|
|北京市|
|陕西省西安市|
When(/^修改项目地址为(.*)$/, (address) => {//.js脚本内容,string为参
.....dosamething
});
- 前置和后置函数Before,After。
const {
Before,
After,
} = require("cypress-cucumber-preprocessor/steps");
// 这将在每个场景之前被调用
Before(() => {
beforeCounter += 1;
beforeWithTagCounter = 0;
});
// 这只会在用@foo标记的场景之前被调用
Before({ tags: "@foo" }, () => {
beforeWithTagCounter += 1;
});
- 事件背景:定义的事件背景会在此事件每个场景开始前调用,如我们可以创建一个重置计数器的给定步骤。
事件: 背景示例 //.feature内容
背景:
重置步数计时器
场景:
........
let counter = 0; //.js脚本内容
Given("重置步数计时器", () => {
counter = 0;
});
-
@focus标签:在场景上添加@focus标签,执行脚本时会只执行带有@focus标签的场景。通过标签启动模式,启动脚本
npx cypress-tags run
-
自定义标签:添加自定义标签,同时通过命令的形式来选择只想那些场
npx cypress-tags run -e TAGS=‘not @foo and (@bar or @zap)’
Feature: Smart Tagging
As a cucumber cypress plugin which handles Tags
I want to allow people to select tests to run if focused
So they can work more efficiently and have a shorter feedback loop
Scenario: This scenario should not run if @focus is on another scenario
Then this unfocused scenario should not run
@focus
Scenario: This scenario is focused and should run
Then this focused scenario should run
@this-tag-affects-nothing
Scenario: This scenario should also not run
Then this unfocused scenario should not run
@focus
Scenario: This scenario is also focused and also should run
Then this focused scenario should run
也可以在cypress.json中添加配置来实现:
{
"env": {
"TAGS": "not @ignore"
},
//rest of configuration options
"baseUrl": "yourBaseUrl",
"ignoreTestFiles": "*.js",
//etc
}
cypress 网络请求
cypress提供对包含HTTP 请求的整个生命周期中请求信息的对象的访问,使其能够对其属性进行断言,存根和模拟请求的响应。
主要功能:
- 断言请求的正文
- 断言请求的 url
- 断言请求的标头
- 存根响应的主体
- 存根响应的状态代码
- 存根响应的标头
- 延迟响应
- 等待响应发生
路由
cy.intercept(
{
method: 'GET', // Route all GET requests
url: '/users/*', // that have a URL that matches '/users/*'
},
[] // and force the response to be: []
)
定义的路由会显示在
组织
每个新项目中都会有一个fixtures文件夹,存放路由相关的json文件例如
/cypress/fixtures/example.json
在使用路由时可以使用fixture方式进行读取
cy.intercept('GET', '/activities/*', { fixture: 'activities.json' })
等待
cypress可以通过使用cy.wait()强制等待路由
cy.intercept('/activities/*', { fixture: 'activities' }).as('getActivities')
cy.intercept('/messages/*', { fixture: 'messages' }).as('getMessages')
//访问仪表板,它应该发出匹配的请求
//含有以上两条路径
cy.visit('http://localhost:8888/dashboard')
//传递一个Route alias数组,强制Cypress等待
//直到看到每个匹配的请求的响应
cy.wait(['@getActivities', '@getMessages'])
// 在上面的wait命令解析之前,这些命令不会运行
cy.get('h1').should('contain', 'Dashboard')
断言
cypress可以对请求中的数据进行拦截和断言
// 监视POST请求到/users端点
cy.intercept('POST', '/users').as('new-user')
// 然后,通过操作web应用程序的用户界面来触发网络调用
cy.wait('@new-user').should('have.property', 'response.statusCode', 201)
// 我们可以再次获取已完成的拦截对象,以运行更多断言
//断言请求体
cy.get('@new-user') // yields the same interception object
.its('request.body')
.should(
'deep.equal',
JSON.stringify({
id: '101',
firstName: 'Joe',
lastName: 'Black',
})
)
// 我们可以在一个“should”回调中放置多个断言
cy.get('@new-user').should(({ request, response }) => {
expect(request.url).to.match(/\/users$/)
expect(request.method).to.equal('POST')
expect(response.headers, 'response headers').to.include({
'cache-control': 'no-cache',
expires: '-1',
'content-type': 'application/json; charset=utf-8',
location: '<domain>/users/101',
})
})
测试重试
默认情况下,测试失败时不会重试。需要 在配置中启用测试重试才能使用此功能。开启测试重试后,测试会在失败时重试配置中的次数,在配置文件cypress.json中声明配置:
{
"retries": 1
}
cypress run和cypress open命令下可以在cypress.json中设置不同的配置
{
"retries": {
// cypress run 默认为0
"runMode": 2,
// cypress open 默认为0
"openMode": 2
}
}