Commit dbe304f5 authored by xie.qin's avatar xie.qin

integrated e2e test cases (web triggering).

parent 07fbc4d6
# 一款小巧灵活的端到端Web自动化测试框架
关键词:
- [Cypress](https://www.cypress.io/)
- [Cucumber](https://cucumber.io)
```text
Cypress几年前还属于一个比较小众的Web测试方案,现如今已有替代Selenium成为Web自动化测试头把交椅的实力。
因其小巧灵活,所以会更适合那些迭代比较频繁,且初期就需要自动化测试介入的项目。
由于官方以及第三方插件的支持,Cypress目前已支持:
```
- BDD语义
- 数据驱动
- CI / CD
- 并发执行
- 各大 IDE 均支持关键词高亮
用例参考:
[点击此链接](./cypress/integration/case-948.feature)
{
"baseUrl": "http://172.22.18.152/",
"env": {
"TAGS": ""
},
"retries": {
"runMode": 0,
"openMode": 0
},
"pageLoadTimeout": 10000,
"defaultCommandTimeout": 5000,
"testFiles": "**/*.{feature,features}"
}
[
{
"keyword": "Feature",
"name": "end to end test case 948",
"line": 2,
"id": "end-to-end-test-case-948",
"tags": [
{
"name": "@case-948",
"line": 1
}
],
"uri": "case-948.feature",
"elements": [
{
"id": "end-to-end-test-case-948;case-948",
"keyword": "Scenario",
"line": 8,
"name": "case-948",
"tags": [
{
"name": "@case-948",
"line": 1
},
{
"name": "@register",
"line": 7
}
],
"type": "scenario",
"steps": [
{
"arguments": [],
"keyword": "Given ",
"line": 4,
"name": "Home page opened",
"result": {
"status": "passed",
"duration": 155000000
}
},
{
"arguments": [],
"keyword": "Then ",
"line": 5,
"name": "Get testing data file \"accounts.json\" and save in context",
"result": {
"status": "passed",
"duration": 7000000
}
},
{
"arguments": [],
"keyword": "Then ",
"line": 9,
"name": "Register with testData number \"case-948\"",
"result": {
"status": "failed",
"duration": 17000000,
"error_message": "TypeError: Object prototype may only be an Object or null: undefined\n\nBecause this error occurred during a `after each` hook we are skipping the remaining tests in the current suite: `end to end test case 948`\n at Function.setPrototypeOf (<anonymous>)\n at eval (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:24470:39)\n at patch (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:24472:5)\n at patch (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:23878:3)\n at Object.eval (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:23870:18)\n at Object.eval (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:24205:4)\n at Object.256../clone.js (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:24205:17)\n at o (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:1:265)\n at eval (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:1:316)\n at Object.284.graceful-fs (http://172.22.18.152/__cypress/tests?p=cypress\\integration\\case-948.feature:49935:12)\nFrom previous event:\n at getRet (http://172.22.18.152/__cypress/runner/cypress_runner.js:141255:20)\nFrom previous event:\n at Context.thenFn (http://172.22.18.152/__cypress/runner/cypress_runner.js:141273:23)\n at Context.then (http://172.22.18.152/__cypress/runner/cypress_runner.js:141725:21)\n at Context.<anonymous> (http://172.22.18.152/__cypress/runner/cypress_runner.js:157781:21)\n at http://172.22.18.152/__cypress/runner/cypress_runner.js:156491:15\nFrom previous event:\n at runCommand (http://172.22.18.152/__cypress/runner/cypress_runner.js:156470:8)\n at next (http://172.22.18.152/__cypress/runner/cypress_runner.js:156613:14)\nFrom previous event:\n at http://172.22.18.152/__cypress/runner/cypress_runner.js:170476:77\nFrom previous event:\n at Object.run (http://172.22.18.152/__cypress/runner/cypress_runner.js:170471:21)\n at Object.run (http://172.22.18.152/__cypress/runner/cypress_runner.js:156667:15)\n at $Cy.cy.<computed> [as then] (http://172.22.18.152/__cypress/runner/cypress_runner.js:157821:17)\n at Context.runnable.fn (http://172.22.18.152/__cypress/runner/cypress_runner.js:158045:21)\n at callFn (http://172.22.18.152/__cypress/runner/cypress_runner.js:112798:21)\n at Hook.../driver/node_modules/mocha/lib/runnable.js.Runnable.run (http://172.22.18.152/__cypress/runner/cypress_runner.js:112785:7)\n at http://172.22.18.152/__cypress/runner/cypress_runner.js:164511:28\nFrom previous event:\n at Object.onRunnableRun (http://172.22.18.152/__cypress/runner/cypress_runner.js:164496:17)\n at $Cypress.action (http://172.22.18.152/__cypress/runner/cypress_runner.js:154154:28)\n at Hook.Runnable.run (http://172.22.18.152/__cypress/runner/cypress_runner.js:162243:13)\n at next (http://172.22.18.152/__cypress/runner/cypress_runner.js:113300:10)\n at http://172.22.18.152/__cypress/runner/cypress_runner.js:113344:5\n at timeslice (http://172.22.18.152/__cypress/runner/cypress_runner.js:107270:27)"
}
}
]
}
]
}
]
\ No newline at end of file
{
"case-948": {
"name": "automation",
"password": "admin123",
"email": "automation@33.cn",
"mobilePhone": "13000000000"
}
}
@case-948
Feature: end to end test case 948
Background: log on home page
Given Home page opened
Then Get testing data file "accounts.json" and save in context
@register
Scenario: case-948
Then Register with testData number "case-948"
@login
Scenario: case-948
Then login after input credential with testData number "case-948"
import { Then } from "cypress-cucumber-preprocessor/steps";
Then('Register with testData number {string}', (caseNum) => {
cy.log('click link "没有账号,去注册"')
cy.url().should('include', 'login')
cy.get('a[href*="register"]').click()
cy.log('assert here to judge jumped already.')
cy.url().should('include', 'register')
cy.get('@testFile').then((testFile) => {
//cy.log('Get testing data:' + data)
cy.log('Loading testing data from context.')
cy.get('form').should('have.class', 'register-form').within(() => {
debugger
var data = testFile[caseNum]
cy.xpath('div[1]//input').type(data.name)
cy.xpath('div[2]//input').type(data.email)
cy.xpath('div[3]//input').type(data.mobilePhone)
cy.xpath('div[4]//input').type(data.password)
cy.xpath('div[5]//input').type(data.password)
cy.xpath('div[6]//button').click()
cy.wait(2000)
cy.xpath('div[6]//input').type("1111")
cy.xpath('div[7]//button').click()
})
})
//cy.url().should('include', 'login')
})
import { Given, Then } from "cypress-cucumber-preprocessor/steps";
Given('Home page opened', () => {
cy.visit('/')
cy.title().should('include', 'BAAS系统')
})
Then('login after input credential with testData number {string}', (caseNum) => {
//cy.url().should('include', 'login')
cy.get('@testFile').then((testFile) => {
cy.get('form').should('have.class', 'login-form').within(() => {
debugger
var data = testFile[caseNum]
cy.xpath('div[1]//input').type(data.username)
cy.xpath('div[2]//input').type(data.password)
})
})
})
\ No newline at end of file
///<reference types="cypress" />
///<reference types="cypress-xpath" />
const {Before} = 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;
});
\ No newline at end of file
const {After} = require("cypress-cucumber-preprocessor/steps")
// Asynchronous Promise
After(() => {
cy.log('produce cucumber reports.')
const report = require('multiple-cucumber-html-reporter');
report.generate({
jsonDir: '../../cucumber-json/',
reportPath: '../../reports/',
metadata:{
browser: {
name: 'chrome',
version: '60'
},
device: 'Local test machine',
platform: {
name: 'ubuntu',
version: '16.04'
}
},
customData: {
title: 'Run info',
data: [
{label: 'Project', value: 'Custom project'},
{label: 'Release', value: '1.2.3'},
{label: 'Cycle', value: 'B11221.34321'},
{label: 'Execution Start Time', value: 'Nov 19th 2017, 02:31 PM EST'},
{label: 'Execution End Time', value: 'Nov 19th 2017, 02:56 PM EST'}
]
}
});
return Promise.resolve()
});
\ No newline at end of file
import { Given } from "cypress-cucumber-preprocessor/steps";
Given('Get testing data file {string} and save in context', (file) => {
cy.log('Loading testing file: ' + file)
cy.fixture('testdatafiles/' + file).as('testFile')
})
\ No newline at end of file
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
const cucumber = require('cypress-cucumber-preprocessor').default
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on('file:preprocessor', cucumber())
}
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
require('cypress-xpath')
{
"name": "e2e",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"cypress:open": "npx cypress open",
"cypress:record": "npx cypress run --record --key <YOUR_KEY>",
"cypress:ci": "npx cypress:run --parallel",
"cypress:run": "npx cypress-tags run -g **/*.features",
"cypress:tags": "npx cypress-tags run -e TAGS='@dryrun'"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cucumber": "^4.2.1",
"cypress": "^8.3.0",
"cypress-cucumber-preprocessor": "^4.2.0",
"cypress-xpath": "^1.6.2",
"multiple-cucumber-html-reporter": "^1.18.0"
},
"cypress-cucumber-preprocessor": {
"nonGlobalStepDefinitions": true,
"cucumberJson": {
"generate": true,
"outputFolder": "cypress/cucumber-json",
"filePrefix": "",
"fileSuffix": ".cucumber"
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment