Cucumber自动化测试框架

前言

闲来无事,不小心接触到了cucumber自动化测试框架,于是上网查了一下,国内关于这个框架的内容竟然很少。
索性自己补充一下,也是学习的总结吧。 
-项目模板弄好,下载即食(后面有链接。。。)
先搞清楚这个东西是什么?

Cucumber 是一个用于行为驱动开发(Behavior Driven Development, BDD)的工具,是一个自动化测试框架。
它最初是为 Ruby 设计的,但现在已被移植到了多种编程语言中,包括 Java、JavaScript、.NET 等。
Cucumber 的核心理念是让非技术人员(如产品经理、业务分析师)也能参与到软件开发的过程中,通过自然语言来描述软件的行为,
从而增强团队之间的沟通。

好了,总结就是简单版的自动化测试用的框架,跟selenium,playwright差不多。

来!直接上手项目,看项目学的最快。

这个项目是基于Cucumber框架进行行为驱动开发(BDD),并使用WebdriverIO作为前端自动化测试框架。

先说说cucumber的一些基础信息。
主要就包含两个重要的部分:feature文件和定义步骤的step文件
  1. feature文件

在这里插入图片描述

长这样!

1. **Given**:
    - 表示测试的前提条件或者初始状态。
    - 它描述的是在执行任何动作之前系统应该处于的状态。
    - 例如,“Given I am logged into my account”意味着测试开始前,用户应当已成功登录到他们的账户。
2. **When**:
    - 描述用户采取的动作或触发某个事件的操作。
    - 这个部分通常包含用户的交互行为,比如点击按钮、填写表单字段等。
    - 例如,“When I click the 'Submit' button”意味着用户点击了提交按钮。
3. **Then**:
    - 描述期望的结果或系统的响应。
    - 这里会列出对用户操作的预期反应,包括界面变化、数据更新等。
    - 例如,“Then I should see a success message”意味着用户应能看到一条成功的提示信息。
</aside>
  1. 既然展示了测试流程,也要定义测试步骤,怎么定义如下:

在这里插入图片描述

webdriverIO写好了很多基础的函数,一路导入写进去即可。

举个运行例子:怎么在百度页面输入恭喜你并截图。

很简单吧 一图看懂

在这里插入图片描述

测试结果

在这里插入图片描述

下面就是怎么从0做一个cucumber+webdriverIO的项目,去完成一些自动化测试的demo,或者你也可以拿来爬虫?看你咯

1.基础准备

node的安装

1、下载和安装Node.js
(1)下载路径:https://nodejs.org/zh-cn/
建议下载与操作系统对应的LTS版,即长期维护版。
(2)成功安装Node.js后,在命令行窗口中,运行命令node -v,
若能看到Node.js的版本信息,则表示Node.js已正常安装。

2.配置node的镜像源  安装快一点 
npm config set registry https://registry.npmmirror.com

3.查看镜像源
npm config get registry

浏览器驱动的安装

浏览器驱动-> 用来自动操作网页的工具
参考下面链接

详解Chrome驱动安装步骤:版本选择与配置全解析_谷歌浏览器驱动-CSDN博客

2.初始化一个node项目

这一步很简单,idea 里面创建一个空项目,然后打开命令行输入下面初始化命令
npm init -y 

#出现一个package.json文件  是一个依赖文件

修改package.json内容如下

{
  "name": "xz-test2",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "clean": "read -p \"Are you sure you want to clean the project? [y/n] \" REPLY; if [[ $REPLY =~ ^[Yy]$ ]]; then rm -R .git .github demo-app test .codeclimate.yml .travis.yml jest.json wdio.BUILD.conf.js src/features/**; fi",
    "test": "run-s test:*",
    "test:lint": "eslint 'src/**/*.ts' 'test/**/*.js!(setup.js)'",
    "test:unit": "jest --config=jest.config.cjs --detectOpenHandles",
    "test:features": "wdio run wdio.BUILD.conf.ts",
    "wdio": "wdio run wdio.BUILD.conf.ts"
  },
  "keywords": ["wdio",
    "webdriver",
    "webdriverio",
    "cucumber",
    "test",
    "boilerplate",
    "selenium"],
  "devDependencies": {
    "@types/jest": "^29.5.13",
    "@typescript-eslint/eslint-plugin": "^8.7.0",
    "@typescript-eslint/parser": "^8.7.0",
    "@wdio/cli": "9.1.2",
    "@wdio/config": "9.1.2",
    "@wdio/cucumber-framework": "9.1.2",
    "@wdio/globals": "9.1.2",
    "@wdio/local-runner": "9.1.2",
    "@wdio/spec-reporter": "9.1.2",
    "@wdio/static-server-service": "9.1.2",
    "eslint": "^8.56.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-plugin-import": "^2.30.0",
    "eslint-plugin-wdio": "^9.0.8",
    "http-server": "^14.1.1",
    "jest": "^29.7.0",
    "jest-circus": "^29.7.0",
    "npm-run-all2": "^6.2.3",
    "ts-jest": "^29.2.5",
    "ts-node": "^10.9.2",
    "typescript": "^5.6.2",
    "webdriverio": "9.1.2"
  },
  "author": "",
  "license": "ISC",
  "description": ""
}

使用npm install去下载依赖 ,出现node-modules文件即可

3.配置webdriverIO的配置文件

在项目文件下新建个wdio.comf.json文件,内容如下:

import url from 'node:url';
import path from 'node:path';

import { hooks } from './src/support/hooks.js';

const dirname = url.fileURLToPath(new URL('.', import.meta.url));

export const config: WebdriverIO.Config = {
    //
    // ====================
    // Runner Configuration
    // ====================
    //
    // WebdriverIO allows it to run your tests in arbitrary locations (e.g. locally or
    // on a remote machine).
    runner: 'local',
    //
    // ==================
    // Specify Test Files
    // ==================
    // Define which test specs should run. The pattern is relative to the directory
    // from which `wdio` was called. Notice that, if you are calling `wdio` from an
    // NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
    // directory is where your package.json resides, so `wdio` will be called from there.
    //
    specs: [
        './src/features/**/*.feature',
    ],
    // Patterns to exclude.
    exclude: [
        // 'path/to/excluded/files'
    ],
    //
    // ============
    // Capabilities
    // ============
    // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
    // time. Depending on the number of capabilities, WebdriverIO launches several test
    // sessions. Within your capabilities you can overwrite the spec and exclude options in
    // order to group specific specs to a specific capability.
    //
    // First, you can define how many instances should be started at the same time. Let's
    // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
    // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
    // files and you set maxInstances to 10, all spec files will get tested at the same time
    // and 30 processes will get spawned. The property handles how many capabilities
    // from the same test should run tests.
    //
    // maxInstances: 5,
    //
    // If you have trouble getting all important capabilities together, check out the
    // Sauce Labs platform configurator - a great tool to configure your capabilities:
    // https://docs.saucelabs.com/basics/platform-configurator/
    //
    capabilities: [{

        // maxInstances can get overwritten per capability. So if you have an in-house Selenium
        // grid with only 5 firefox instances available you can make sure that not more than
        // 5 instances get started at a time.
        maxInstances: 5,
        //
        browserName: 'chrome',
        // If outputDir is provided WebdriverIO can capture driver session logs
        // it is possible to configure which logTypes to include/exclude.
        // excludeDriverLogs: ['*'], // pass '*' to exclude all driver session logs
        // excludeDriverLogs: ['bugreport', 'server'],
    }],
    //
    // ===================
    // Test Configurations
    // ===================
    // Define all options that are relevant for the WebdriverIO instance here
    //
    // Level of logging verbosity: trace | debug | info | warn | error | silent
    logLevel: 'trace',
    outputDir: path.join(dirname, '/logs'),
    //
    // Set specific log levels per logger
    // loggers:
    // - webdriver, webdriverio
    // - @wdio/applitools-service, @wdio/browserstack-service,
    //   @wdio/devtools-service, @wdio/sauce-service
    // - @wdio/mocha-framework, @wdio/jasmine-framework
    // - @wdio/local-runner, @wdio/lambda-runner
    // - @wdio/sumologic-reporter
    // - @wdio/cli, @wdio/config, @wdio/sync, @wdio/utils
    // Level of logging verbosity: trace | debug | info | warn | error | silent
    // logLevels: {
    //     webdriver: 'info',
    //     '@wdio/applitools-service': 'info'
    // },
    //
    // If you only want to run your tests until a specific amount of tests have failed use
    // bail (default is 0 - don't bail, run all tests).
    bail: 0,
    //
    // Set a base URL in order to shorten url command calls. If your `url` parameter starts
    // with `/`, the base url gets prepended, not including the path portion of your baseUrl.
    // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
    // gets prepended directly.
    baseUrl: 'http://localhost:8080',
    //
    // Default timeout for all waitFor* commands.
    waitforTimeout: 10000,
    //
    // Default timeout in milliseconds for request
    // if browser driver or grid doesn't send response
    connectionRetryTimeout: 90000,
    //
    // Default request retries count
    connectionRetryCount: 3,
    //
    // Test runner services
    // Services take over a specific job you don't want to take care of. They enhance
    // your test setup with almost no effort. Unlike plugins, they don't add new
    // commands. Instead, they hook themselves up into the test process.
    // services: [],
    //
    // Framework you want to run your specs with.
    // The following are supported: Mocha, Jasmine, and Cucumber
    // see also: https://webdriver.io/docs/frameworks.html
    //
    // Make sure you have the wdio adapter package for the specific framework installed
    // before running any tests.
    framework: 'cucumber',
    //
    // The number of times to retry the entire specfile when it fails as a whole
    // specFileRetries: 1,
    //
    // Whether or not retried specfiles should be retried immediately or deferred
    // to the end of the queue specFileRetriesDeferred: false,
    //
    // Test reporter for stdout.
    // The only one supported by default is 'dot'
    // see also: https://webdriver.io/docs/dot-reporter.html
    reporters: ['spec'],
    //
    // If you are using Cucumber you need to specify the location of your step definitions.
    cucumberOpts: {
        // <boolean> show full backtrace for errors
        backtrace: false,
        // <string[]> module used for processing required features
        requireModule: [],
        // <boolean< Treat ambiguous definitions as errors
        failAmbiguousDefinitions: true,
        // <boolean> invoke formatters without executing steps
        // dryRun: false,
        // <boolean> abort the run on first failure
        failFast: false,
        // <boolean> Enable this config to treat undefined definitions as
        // warnings
        ignoreUndefinedDefinitions: false,
        // <string[]> ("extension:module") require files with the given
        // EXTENSION after requiring MODULE (repeatable)
        names: [],
        // <boolean> hide step definition snippets for pending steps
        snippets: true,
        // <boolean> hide source uris
        source: true,
        // <string[]> (name) specify the profile to use
        profile: [],
        // <string[]> (file/dir) require files before executing features
        require: [
            './src/steps/given.ts',
            './src/steps/then.ts',
            './src/steps/when.ts',
            // Or search a (sub)folder for JS files with a wildcard
            // works since version 1.1 of the wdio-cucumber-framework
            // './src/**/*.js',
        ],
        scenarioLevelReporter: false,
        order: 'defined',
        // <string> specify a custom snippet syntax
        snippetSyntax: undefined,
        // <boolean> fail if there are any undefined or pending steps
        strict: true,
        // <string> (expression) only execute the features or scenarios with
        // tags matching the expression, see
        // https://docs.cucumber.io/tag-expressions/
        tagExpression: 'not @Pending',
        // <boolean> add cucumber tags to feature or scenario name
        tagsInTitle: false,
        // <number> timeout for step definitions
        timeout: 20000,
    } as WebdriverIO.CucumberOpts,
    ...hooks,
};

4.最后是创建文件架构如下:

在这里插入图片描述

  • .idea:IntelliJ IDEA的配置文件夹。
  • logs:日志文件夹,用于存储运行时的日志信息。
  • node_modules:Node.js模块安装目录,包含了项目依赖的所有第三方库。
  • src
    • features:功能特性文件夹,通常包含Gherkin格式的测试用例(.feature 文件)。
    • steps:步骤定义文件夹,包含与Gherkin测试用例对应的实现代码。
      • given.ts: 定义给定条件的步骤。
      • then.ts: 定义然后/结果的步骤。
      • when.ts: 定义当/动作的步骤。
  • support:支持文件夹,包含辅助类、函数等。
    • action:操作相关的辅助类或函数。
    • check:检查相关的方法或函数。
    • lib:通用库或工具方法。
    • screenshots:截图文件夹,用于保存测试过程中生成的截图。
    • hooks.ts: 测试钩子文件,可以在这里定义测试前后的钩子函数。
  • package.json: 项目配置文件,描述了项目的基本信息和依赖关系。
  • package-lock.json: 包锁定文件,记录了具体版本的依赖项。
  • wdio.conf.ts: WebdriverIO配置文件,用于设置测试环境和浏览器驱动。
  • xz-test2.iml: IntelliJ IDEA的项目索引文件。

!!!文件src内容自己写,我是站在前人的肩膀上已经准备好了一些基础的步骤代码,如果你也不想写基础的像什么打开链接,点击按钮等基础步骤。你可以直接复制我的src文件到你的项目里面。以下是下载文件链接。

链接:https://pan.baidu.com/s/1pJmdGydVmOLLSDNVs9KtJw?pwd=1314
提取码:1314
–来自百度网盘超级会员V4的分享

已完成但不限于下面内容

Given steps 给定步骤
			I open the (url|site) "([^"]*)?"
			Open a site in the current browser window/tab
			在当前浏览器窗口/选项卡中打开站点
			the element "([^"]*)?" is( not)* displayed
			Check the (in)visibility of an element
			检查元素的 (in) 可见性
			the element "([^"]*)?" is( not)* enabled
			Check if an element is (not) enabled
			检查元素是否已启用
			the element "([^"]*)?" is( not)* selected
			Check if an element is (not) selected
			检查元素是否已选中
			the checkbox "([^"]*)?" is( not)* checked
			Check if a checkbox is (not) checked
			检查复选框是否被选中(未)
			there is (an|no) element "([^"]*)?" on the page
			Check if an element (does not) exist
			检查元素是否(不存在)
			the title is( not)* "([^"]*)?"
			Check the title of the current browser window/tab
			检查当前浏览器窗口/选项卡的标题
			the element "([^"]*)?" contains( not)* the same text as element "([^"]*)?"
			Compare the text of two elements
			比较两个元素的文本
			the (button|element) "([^"]*)?"( not)* contains the text "([^"]*)?"
			Check if an element contains the given text
			检查元素是否包含给定的文本
			the (button|element) "([^"]*)?"( not)* contains any text
			Check if an element does not contain any text
			检查元素是否不包含任何文本
			the (button|element) "([^"]*)?" is( not)* empty
			Check if an element is empty
			检查元素是否为空
			the page url is( not)* "([^"]*)?"
			Check the url of the current browser window/tab
			检查当前浏览器窗口/选项卡的 url
			the( css)* attribute "([^"]*)?" from element "([^"]*)?" is( not)* "([^"]*)?"
			Check the value of an element's (css) attribute
			检查元素的 (css) 属性的值
			the cookie "([^"]*)?" contains( not)* the value "([^"]*)?"
			Check the value of a cookie
			检查 Cookie 的值
			the cookie "([^"]*)?" does( not)* exist
			Check the existence of a cookie
			检查 Cookie 是否存在
			the element "([^"]*)?" is( not)* ([\d]+)px (broad|tall)
			Check the width/height of an element
			检查元素的宽度/高度
			the element "([^"]*)?" is( not)* positioned at ([\d]+)px on the (x|y) axis
			Check the position of an element
			检查元素的位置
			I have a screen that is ([\d]+) by ([\d]+) pixels
			Set the browser size to a given size
			将浏览器大小设置为给定大小
			I have closed all but the first (window|tab)
			Close all but the first browser window/tab
			关闭除第一个浏览器窗口/选项卡之外的所有浏览器窗口/选项卡
			a (alertbox|confirmbox|prompt) is( not)* opened
			Check if a modal is opened
			检查是否打开了模态框

Then steps 然后步骤
	I expect that the title is( not)* "([^"]*)?"
	Check the title of the current browser window/tab
	检查当前浏览器窗口/选项卡的标题
	I expect that element "([^"]*)?" does( not)* appear exactly "([^"]*)?" times
	Checks that the element is on the page a specific number of times
	检查元素是否在页面上显示特定次数
	I expect that element "([^"]*)?" is( not)* visible
	Check if a certain element is visible
	检查某个元素是否可见
	I expect that element "([^"]*)?" becomes( not)* visible
	Check if a certain element becomes visible
	检查某个元素是否可见
	I expect that element "([^"]*)?" is( not)* within the viewport
	Check if a certain element is within the current viewport
	检查某个元素是否在当前视区内
	I expect that element "([^"]*)?" does( not)* exist
	Check if a certain element exists
	检查某个元素是否存在
	I expect that element "([^"]*)?"( not)* contains the same text as element "([^"]*)?"
	Compare the text of two elements
	比较两个元素的文本
	I expect that (button|element) "([^"]*)?"( not)* contains the text "([^"]*)?"
	Check if an element or input field contains the given text
	检查元素或输入字段是否包含给定的文本
	I expect that (button|element) "([^"]*)?"( not)* contains any text
	Check if an element or input field contains any text
	检查元素或输入字段是否包含任何文本
	I expect that (button|elementelement) "([^"]*)?" is( not)* empty
	Check if an element or input field is empty
	检查元素或输入字段是否为空
	I expect that the url is( not)* "([^"]*)?"
	Check if the the URL of the current browser window/tab is a certain string
	检查当前浏览器窗口/选项卡的 URL 是否为某个字符串
	I expect that the path is( not)* "([^"]*)?"
	Check if the path of the URL of the current browser window/tab is a certain string
	检查当前浏览器窗口/标签页的 URL 路径是否为某个字符串
	I expect the url to( not)* contain "([^"]*)?"
	Check if the URL of the current browser window/tab contains a certain string
	检查当前浏览器窗口/选项卡的 URL 是否包含某个字符串
	I expect that the( css)* attribute "([^"]*)?" from element "([^"]*)?" is( not)* "([^"]*)?"
	Check the value of an element's (css) attribute
	检查元素的 (css) 属性的值
	I expect that checkbox "([^"]*)?" is( not)* checked
	Check if a check-box is (not) checked
	检查复选框是否被选中(未)
	I expect that element "([^"]*)?" is( not)* selected
	Check if an element is (not) selected
	检查元素是否已选中
	I expect that element "([^"]*)?" is( not)* enabled
	Check if an element is (not) enabled
	检查元素是否已启用
	I expect that cookie "([^"]*)?"( not)* contains "([^"]*)?"
	Check if a cookie with a certain name contains a certain value
	检查具有特定名称的 Cookie 是否包含特定值
	I expect that cookie "([^"]*)?"( not)* exists
	Check if a cookie with a certain name exist
	检查是否存在具有特定名称的 Cookie
	I expect that element "([^"]*)?" is( not)* ([\d]+)px (broad|tall)
	Check the width/height of an element
	检查元素的宽度/高度
	I expect that element "([^"]*)?" is( not)* positioned at ([\d]+)px on the (x|y) axis
	Check the position of an element
	检查元素的位置
	I expect that element "([^"]*)?" (has|does not have) the class "([^"]*)?"
	Check if an element has a certain class
	检查元素是否具有特定类
	I expect a new (window|tab) has( not)* been opened
	Check if a new window/tab has been opened
	检查是否已打开新窗口/选项卡
	I expect the url "([^"]*)?" is opened in a new (tab|window)
	Check if a URL is opened in a new browser window/tab
	检查 URL 是否在新的浏览器窗口/选项卡中打开
	I expect that element "([^"]*)?" is( not)* focused
	Check if an element has the focus
	检查元素是否具有焦点
	I wait on element "([^"]*)?"( for (\d+)ms)*( to( not)* (be checked|be enabled|be selected|be visible|contain a text|contain a value|exist))*
	Wait for an element to be checked, enabled, selected, visible, contain a certain value or text or to exist
	等待元素被选中、启用、选择、可见、包含特定值或文本或存在
	I expect that a (alertbox|confirmbox|prompt) is( not)* opened
	Check if a modal is opened
	检查是否打开了模态框
	I expect that a (alertbox|confirmbox|prompt)( not)* contains the text "$text"
	Check the text of a modal
	检查模态框的文本
When steps 步骤
	I (click|doubleclick) on the (link|button|element) "([^"]*)?"
	(Double)click a link, button or element
	(双击)链接、按钮或元素
	I (add|set) "([^"]*)?" to the inputfield "([^"]*)?"
	Add or set the content of an input field
	添加或设置输入字段的内容
	I clear the inputfield "([^"]*)?"
	Clear an input field 清除输入字段
	I drag element "([^"]*)?" to element "([^"]*)?"
	Drag an element to another element
	将一个元素拖动到另一个元素
	I submit the form "([^"]*)?"
	我提交表格“([^”]*)?
	Submit a form 提交表单
	I pause for (\d+)ms
	我暂停了 (\d+)ms
	Pause for a certain number of milliseconds
	暂停一定毫秒数
	I set a cookie "([^"]*)?" with the content "([^"]*)?"
	Set the content of a cookie with the given name to the given string
	将具有给定名称的 Cookie 的内容设置为给定的字符串
	I delete the cookie "([^"]*)?"
	Delete the cookie with the given name
	删除具有给定名称的 Cookie
	I press "([^"]*)?"
	我按“([^”]*)?
	Press a given key. You’ll find all supported characters here. To do that, the value has to correspond to a key from the table.
	按给定的键。您可以在此处找到所有支持的角色。为此,该值必须与表中的键相对应。
	I (accept|dismiss) the (alertbox|confirmbox|prompt)
	Accept or dismiss a modal window
	接受或关闭模式窗口
	I enter "([^"]*)?" into the prompt
	Enter a given text into a modal prompt
	在模态提示符中输入给定文本
	I scroll to element "([^"]*)?"
	Scroll to a given element
	滚动到给定元素
	I close the last opened (window|tab)
	Close the last opened browser window/tab
	关闭上次打开的浏览器窗口/选项卡
	I focus the last opened (window|tab)
	Focus the last opened browser window/tab
	聚焦上次打开的浏览器窗口/选项卡
	I select the (\d+)(st|nd|rd|th) option for element "([^"]*)?"
	Select an option based on it's index
	根据索引选择一个选项
	I select the option with the (name|value|text) "([^"]*)?" for element "([^"]*)?"
	Select an option based on its name, value or visible text
	根据选项的名称、值或可见文本选择选项
	I move to element "([^"]*)?"( with an offset of (\d+),(\d+))
	Move the mouse by an (optional) offset of the specified element
	将鼠标移动指定元素的 (可选) 偏移量
	I switch to the iframe "([^"]*)?"
	Switch to a particular iFrame on the webpage
	切换到网页上的特定 iFrame

对了 怎么执行忘记说了,cmd执行下面命令

npx wdio wdio.conf.js --spec src/features/githubLogin.feature

#src/features/githubLogin.feature替换成你要测试的那个文件

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值