Cypress Cucumber Setup

译文来自npm官网:https://www.npmjs.com/package/cypress-cucumber-preprocessor#cypress-configuration

使用Cypress测试时,cypress-cucumber-preprocessor 提供使用Feature文件。

你可以按照以下文档,或者你喜欢在实例上进行黑客攻击,你可以看一下: https://github.com/TheBrainFamily/cypress-cucumber-example

目录

  • 开始
    • 安装
    • Cypress 配置
    • 配置
  • 如何管理测试
    • 单个的Feature文件
    • 多个Feature文件
    • 测试步骤定义
      • 创建测试步骤
      • 可重复使用的测试步骤
  • 如何写测试用例
    • Cucumber的表达
    • Given/When/Then 功能
    • 自定义参数类型的解析
    • Before和After钩子
    • 背景部分
    • 文件共享
    • 智能标记
  • 如何运行测试
    • 运行标记的测试用例
    • 输出
  • 支持的编辑器
    • Webstorm
    • Intellij IDEA
    • Visual Studio Code

开始

安装

使用下边的命令安装插件:

npm install --save-dev cypress-cucumber-preprocessor 

Cypress 配置

添加下边代码在cypress/plugins/index.js文件中:

const cucumber = require('cypress-cucumber-preprocessor').default
module.exports = (on, config) => {
   on('file:preprocessor', cucumber())
}

在Cypress的配置文件cypress.json中添加支持的Feature文件

{
  "testFiles": "**/*.feature"
}

配置

确保使用cosmiconfig 去创建插件的配置,例如,将以下代码添加到package.json文件中:

"cypress-cucumber-preprocessor": {
    "nonGlobalStepDefinitions": true
}
配置选择
选择 默认值 描述
commonPath nonGlobalStepDefinitions = true,则路径为cypress/integration/commonnonGlobalStepDefinitions = false,则路径为cypress/support/step_definitions 默认的路径文件中包含所有共有的测试步骤
nonGlobalStepDefinitions false 同上
step_definitions cypress/support/step_definitions 包含测试步骤的文件路径

如何管理测试

  • 单个feature文件

cypress/integration/文件夹下创建一个新的feature文件,例如: cypress/integration/Google.feature
@facus 标记不是必须的,但是希望你注意到这个标记,在以后,使用这个标记会大大提高你的测试效率。

Feature: The Facebook
  I want to open a social network page

  @focus
  Scenario: Opening a social network page
    Given I open Google page
    Then I see "google" in the title
  • 多个feature文件

当用headless运行cypress测试时,测试执行速度慢,这个发生的原因是因为Cypress默认的会在每个feature文件之前重新打开浏览器。在运行测试之前,cypress-cucumber-preprocessor 提供了打包所有feature文件的选项,因此降低了测试执行的时间。
你可以利用这一点来创建feature文件,你可以选择在根目录cypress/integrations下只有一个feature文件,或者是每一个目录下只有一个Feature文件。
或者是你也可以添加支持的feature文件在Cypress的配置文件cypress.json中,如下所示:

{
  "testFiles": "**/*.{feature,features}"
}

然后可以运行多个feature文件的测试,使用命令:

cypress run --spec **/*.features
  • 测试步骤定义 (这是一个推荐的方法)

测试步骤的创建

.feature文件将使用与.feature文件同名的js文件中的步骤。如果要将包含步骤定义的javascript文件分解为不同的关注点,则可以使用其他名称。
为了更容易理解,所以假设feature文件在cypress/integration/Google.feature,如上所示,预处理器将读取cypress/integration/Google/ 里的所有文件,如cypress/integration/Google/google.js (或者同一路径下的任何其他的 .js 文件)

import { Given } from "cypress-cucumber-preprocessor/steps";
const url = 'https://google.com'

Given('I open Google page', () => {
  cy.visit(url)
})

这是一个很好的地方去放置before/beforeEach/after/afterEach 钩子相关的一些特定特性,This is incredibly hard to get right with pure cucumber.

可重复使用的测试步骤

我们也可以有一个方法去创建可重用的测试步骤,把他们放在 cypress/integration/common/。例如:cypress/integration/common/i_see_string_in_the_title.js

import { Then } from "cypress-cucumber-preprocessor/steps";

Then(`I see {string} in the title`, (title) => {
  cy.title().should('include', title)
})

这是一个很好的地方去放置全局的 before/beforeEach/after/afterEach 钩子。

如何写测试用例

  • Cucumber 的表达

当你使用Cucumber来描述你的feature文件,请使用下边文件作为参考: https://docs.cucumber.io/cucumber/cucumber-expressions/

  • Given/When/Then 功能

因为Given/When/Then是全局变量,请使用以下示例,确保编辑器可以直接导入他们。

/* global Given, When, Then */
  • 定义参数类型的解析

感谢 @Oltodo, 现在我们可以使用自定义参数类型的解析。这里是示例, 以及使用的feature文件

  • Before 和 After 钩子

cypress-cucumber-preprocessor 支持两种钩子,一种是Mocha的 before/beforeEach/after/afterEach 钩子,一种是 Cucumber的 Before and After 钩子。
Cucumber钩子完全支持标记如cucumber js文件中描述的一样,所以他们可以基于场景标记进行有条件的选择。使用Mocha钩子,这是可能实现的。
Cucumber 的Before钩子会在Mocha的before和beforeEach钩子完成之后运行,Cucumber 的After钩子会在Mocha的afterEach和after执行之前运行。示例如下:

const {
  Before,
  After,
  Given,
  Then 
} = require("cypress-cucumber-preprocessor/steps");

// this will get called before each scenario
Before(() => {
  beforeCounter += 1;
  beforeWithTagCounter = 0;
});

// this will only get called before scenarios tagged with @foo
Before({ tags: "@foo" }, () => {
  beforeWithTagCounter += 1;
});

Given("My Step Definition", () => {
  // ...test code here
})

注意: 为了避免与Mocha 的before和after钩子名字的混淆,Cucumber 的钩子不会导出到全局变量,所以他们需要显示导入,如上边的例子所示。

  • 背景部分

在feature文件中添加背景部分可以在每一个测试之前运行这些步骤。例如,你有一个计数器,需要在每个测试之前重置,我们可以创建一个步骤去重置计数器。

let counter = 0;
Given("counter has been reset", () => {
  counter = 0;
});

When("counter is incremented", () => {
  counter += 1;
});

Then("counter equals {int}", value => {
  expect(counter).to.equal(value);
});
Feature: Background Section
   
Background:
    Given counter has been reset
  
 Scenario: Basic example #1
     When counter is incremented
     Then counter equals 1

   Scenario: Basic example #2
     When counter is incremented
     When counter is incremented
     Then counter equals 2
  • 文件共享

可以使用cy.as()重命名,来实现文件在两个步骤文件之间的共享。更多的信息请查看: https://docs.cypress.io/api/commands/as.html, 例如:

Given('I go to the add new item page', () => {
  cy.visit('/addItem');
});

When('I add a new item', () => { 
  cy.get('input[name="addNewItem"]').as('addNewItemInput');
  cy.get('@addNewItemInput').type('My item');
  cy.get('button[name="submitItem"]').click();
})

Then('I see new item added', () => {
  cy.get('td:contains("My item")');
});

Then('I can add another item', () => {
  expect(cy.get('@addNewItemInput').should('be.empty');
});
  • 智能标记

开始的测试时没有任何的标记。之后可以在你想要等开发修复完问题集中关注的测试用例前加上标记@focus 。例如:

Feature: Smart Tagging

  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,例如:

./node_modules/.bin/cypress open

点击列表中的.feature文件,你会看到神奇地事情发生!

  • 运行有标记的测试

你可以通过标记来选择哪些测试用例需要去运行。请记住,我们使用的是最新的语法,如:'not @foo and (@bar or @zap)'。为了使用标记初始化测试用例,你需要运行cypress并且传递标记的环境变量。例如:

./node_modules/.bin/cypress-tags run -e TAGS='not @foo and (@bar or @zap)'

请注意:我们使用自己的Cypress-tags 来提高速度,更多详细的示例请: https://github.com/TheBrainFamily/cypress-cucumber-example

  • 限定一个feature文件的子集

你可以使用全局表达去选择哪一个feature文件应该被包含。例如:

  ./node_modules/.bin/cypress-tags run -e GLOB='cypress/integration/**/*.feature'
  • 输出

cypress-cucumber-preprocessor可以在运行feature文件的时候生成一个 cucumber.json 文件输出。这是分开的,除了在cypress中配置Mocha报告。
这些文件可以和其他任何一个cucumber报告生成器一起使用,下边两个都很好: https://github.com/jenkinsci/cucumber-reports-pluginhttps://github.com/wswebcreation/multiple-cucumber-html-reporter

默认的输出,会写在文件cypress/cucumber-json中,而且一个Feature文件生成一个。这个习惯是可以配置的,使用 cosmiconfig 去为插件创建一个配置,to create a configuration for the plugin, 请参考上边的步骤定义讨论,并且将下边的内容添加到package.json文件中,更改默认值。

  "cypress-cucumber-preprocessor": {
    "cucumberJson": {
      "generate": true,
      "outputFolder": "cypress/cucumber-json",
      "filePrefix": "",
      "fileSuffix": ".cucumber"
    }
  }

Cucumber 的.json 配置

选项 默认值 描述
outputFolder cypress/cucumber-json 输出文件的地址
filePrefix '' (no prefix) 每一个feature文件根据名字生成一个单独的json文件. 如果指定,则每一个生成的json文件将以此作为前缀
fileSuffix .cucumber 为每一个生成的文件添加后缀名
generate false 标记生成 cucumber.json 文件还是不生成

支持的编辑器

  • WebStorm

如果你想要使用WebStorm解析你的步骤,请使用大写:Given/When/Then 方法名来代替小写 given/when/then。 注意:只有WebStorm 2019.2或者更新的版本才能使用解析在step_definitions文件之外的步骤

  • Intellij IDEA

Intellij IDEA 社区版不支持 cucumber 使用 javascript,但是终极版可以提供和WebStorm同样的级别的步骤解析的支持。
为了确保能够解决
为了能够在Intellij IDEA 终极版编辑器中解析cucumber步骤,你需要下载和授权JetBrains Cucumber JS plugin。在 WebStorm,这个插件已经绑定在授权版本中。

  • Visual Studio Code

使用VSCode解析cucumber步骤,需要下载扩展插件:Cucumber (Gherkin) Full Support。而且你需要告诉扩展工具你的Feature和测试步骤文件的路径, 像这里描述的
注意,和WebStorm不同, WebStorm可以正确的匹配步骤的多个实现,但是VSCode当前只能解析第一个他在对应路径下匹配的实现。

TypeScript支持

  • 有 Webpack

可以使用Webpack加载程序处理的功能文件(TypeScript 支持)。想知道如何做,请看这里: cypress-cucumber-webpack-typescript-example

  • 没有 Webpack

如果你想使用TypeScript,添加下边的代码在plugins/index.js文件中,而且安装tsifynpm install tsify。我默认你已经安装了TypeScript。

const cucumber = require("cypress-cucumber-preprocessor").default;
const browserify = require("@cypress/browserify-preprocessor");
module.exports = (on) => {
  const options = browserify.defaultOptions;
  options.browserifyOptions.plugin.unshift(['tsify']);
  // Or, if you need a custom tsconfig.json for your test files:
  // options.browserifyOptions.plugin.unshift(['tsify', {project: 'path/to/other/tsconfig.json'}]);
  on("file:preprocessor", cucumber(options));
};

之后在你的.ts文件中需要确保要么要求/导入步骤定义的函数,或者声明他们为全局的。

declare const Given, When, Then;
// OR
import { Given, Then, When } from "cypress-cucumber-preprocessor/steps";

在这里可以查看一下示例: https://github.com/TheBrainFamily/cypress-cucumber-typescript-example/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容