为什么 Cucumber 不被视为测试工具?

Why isn't Cucumber considered as a testing tool?

我是 Cucumber 的新手,我正在尝试了解该工具。在阅读 the documentation 时,我发现它被简短地定义为 "a tool that supports BDD":

Cucumber is a tool that supports Behaviour-Driven Development(BDD).

也被描述为“验证工具”:

Cucumber reads executable specifications written in plain text and validates that the software does what those specifications say.

在另一边,我注意到“测试”这个词在10-minute tutorial上被过度使用了。

AFAIK,此工具的作用是敏捷测试,因为它在端到端测试中大量使用(测试基础 = Gherkin 功能规范 + 步骤定义)。但是,the blog 说的是不同的东西:

Finally, remember that Cucumber is not a testing tool. It is a tool for capturing common understanding on how a system should work. A tool that allows you, but doesn't require you, to automate the verification of the behaviour of your system if you find it useful.

现在,如果这个工具不是真正用于测试,那么它的用途是什么?

TL;DR

Cucumber 是一个 BDD 框架。它的主要组成部分是:

  1. Gherkin:作为沟通工具的无处不在的语言 任何东西,都可以作为协作的跳板。它 帮助管理业务的期望,如果每个人都可以 以易于理解的格式查看您所做的更改,他们会 希望不要对开发团队感到沮丧,但也 如果有,您可以使用它来加快团队的反应时间 是错误,通过编写 cucumber 用心态包装的测试 有人将不得不回来调试它 点.
  2. CLI implementation(或 CLI):一个测试 运行ner 基于 小黄瓜。它是由志愿者开发的,他们都捐赠了一部分 他们的业余时间。每个实现都特定于一个编程 支持准备测试的生产代码的语言。这是 被视为具体的工具/实用程序。

长版

Gherkin 的预期用途是作为一种通信工具,从多个角度(或参与者)描述与系统的交互,恰好你可以将它与测试框架集成,这有助于确保系统在place 正确地处理了这些交互。

最常见的是,这是从用户的角度来看:

Given John has logged in
When he receives a message from Brenda
Then he should be able to click through to his message thread with Brenda via the notification

但也可以从component/pages的角度来看:

Given the customer history table is displayed
And there have been changes to the customer table for that user since the page was first loaded
When it receives a click to refresh the data
Then the new changes should be displayed

一切都是为了描述行为,并允许业务和开发人员自由协作,同时打破通常最终困扰沟通的语言障碍,并且通常使双方因缺乏相互挫折而彼此沮丧对一个问题的理解

这是 "fun" 开始的地方 - 阿纳金,第三集

您可以使用这些文件在您的整个开发团队(如果成功的话,更广泛的业务)中创建一个 "living documentation" 的环境,并且在理论上 - 措辞和显示正确,这将是一个令人难以置信的福音客户服务人员,他们将更容易跟上变化,并且会拥有描述得非常详尽的帮助文档——无需任何额外的努力,但这并不是我在野外看到的很多东西。我在工作中编写了一个脚本,通过将功能转换为 markdown 以及各种其他 markdown 工具(mermaid 用于图表,tsdoc-plugin-markdown 用于生成 API 文档,以及各种我选择的 HTML 转换器的扩展,docsify) 我已经设法生成了一些不难导航的东西,并打开了团队之间的沟通,以前发现很难将他们的问题传达给开发团队(现在大多数人都知道一点 markdown,即使它必须被描述为 "the characters you type in reddit threads and youtube comments to make text bold and italics, etc" 才能让人们明白它是什么,但这意味着每个人都可以为它做出贡献)

在调试测试时,它是一个非常有用的工具,尤其是在与 screenplay 模式一起使用时(由于缺少 pom 提供的额外上下文,因此与标准页面对象模型的情况不太一样,但它仍然有用),因为所有内容的描述方式都会在失败时从用户或组件的角度复制问题。

我将它与流程图配对,我在其中绘制了用户交互,将功能固定到它上面,并能够以更直观的方式看到用户可以在哪些地方做我们可能没有的事情计划,甚至弄清楚我们不知何故错过的一些花哨的场景。

加长版

我这里的示例主要在 javascript 中,因为我们一直在 node 环境中开发,但如果您想创建自己的版本,应该不会有太大差异。

文档

本质上,这只是为了以一种易于业务消化的方式显示功能文件(我也计划将测试报告集成到其中,并提供切换分支等的能力)

首先,您想要获取功能文件夹中所有文件的简单数组,并挑选出末尾带有“.feature”的文件。

本质上,你只需要在这里压平一个ls(这个可以改进,但是我们要求使用LTS版本的node,而不是一般的最新版本)

const fs = require('fs');
const path = require('path');
const walkSync = (d) => fs.statSync(d).isDirectory() ? fs.readdirSync(d).map(f => walkSync(path.join(d, f))) : d;

const flatten = (arr, result = []) => {
  if (!Array.isArray(arr)){
    return [...result, arr];
  }
  arr.forEach((a) => {
    result = flatten(a, result)
  })
  return result
}

function features (folder) {
  const allFiles = flatten(walkSync(path.relative(process.cwd(), folder)))
  let convertible = []
  for (let file of allFiles) {
    if (file.match(/.feature$/)) {
      convertible.push(file)
    }
  }
  return convertible
}

...

使用 Gherkin 解析器浏览所有这些文件以提取您的场景需要一些设置,尽管这很简单,因为 Gherkin 具有非常明确的结构和已知关键字。

可以有很多自引用,因为当您将其归结为基础时,很多黄瓜都是建立在定义良好的组件之上的。例如,您可以将场景描述为背景,背景可以包含描述、标签和名称:

class Convert {

   ...

   static background (background) {
    return {
      cuke: `${background.keyword.trim()}:`,
      steps: this.steps(background.steps),
      location: this.location(background.location),
      keyword: background.keyword
    }
  }

  static scenario (scenario) {
    return {
      ...this.background(scenario),
      tags: this.tags(scenario.tags),
      cuke: `${scenario.keyword.trim()}: ${scenario.name}\n`,
      description: `${scenario.description.replace(/(?!^\s+[>].*$)(^.*$)/gm, "<br>").trim()}`,
      examples: this.examples(scenario.examples)
    }
  }

  ...
}

您可以充实它以写入单个文件,或输出几个降价文件(确保在菜单文件中引用它们)

流程图

流程图可以更轻松地帮助可视化问题,并且有一些工具使用 markdown 来帮助生成它们,如下所示:

在后面,它最终看起来像这样:

### Login

Customers should be able to log into their account, as long as they have registered.

...


```mermaid
 graph TD
        navigateToLogin["Navigate to Login"] -->logIn{"Login"}
        logIn -->validCredentials["Valid<br>Credentials"]
        logIn -->invalidCredentials{"Invalid<br>Credentials"}
        invalidCredentials -->blankPass["Blank Password"]
        invalidCredentials -->wrongPass["Wrong Password"]
        invalidCredentials -->blankEmail["Blank Email"]
        invalidCredentials -->wrongEmail["Wrong Email"]
        ...

        click blankPass "/#/areas/login/scenario-blank-password" "View Scenario"
        ...
 ```

它本质上只是一种非常快速的可视化问题的方法,并将我们链接到文档中的正确位置以找到答案。该工具绘制了流程图,您只需在页面上的关键概念或想法之间建立联系(即新客户获得不同的开始屏幕)

剧本模式、Serenity 和调试

我认为这里真正需要说明的是,当您 运行 测试时,这是您的输出:

✓ Correct information on the billing page
    ✓ Given Valerie has logged into her account
        ✓ Valerie attempts to log in
            ✓ Valerie visits the login page
                ✓ Valerie navigates to '/login'
            ✓ Valerie waits up to 5s until the email field does become visible
            ✓ Valerie enters 'thisisclearlyafakeemail@somemailprovider.com' into the email field
            ✓ Valerie enters 'P@ssword!231' into the password field
            ✓ Valerie clicks on the login button
            ✓ Valerie waits for 1s

它将测试的任何部分分解为描述,这意味着如果 CSS 发生变化,我们将不会搜索不再存在的东西,甚至是调试该区域的新手该站点将能够从测试失败中恢复过来。

通讯

我认为所有这些都应该表明如何从更普遍的意义上改善沟通。这一切都是为了确保尽可能多的人可以访问这些项目,他们可以输入有价值的东西(应该是您企业中的每个人)