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

README refined.

parent dbe304f5
# 一款小巧灵活的端到端Web自动化测试框架 # 一款小巧灵活的端到端Web自动化测试框架
关键词: ## 关键词:
- [Cypress](https://www.cypress.io/) - [Cypress](https://www.cypress.io/)
- [Cucumber](https://cucumber.io) - [Cucumber](https://cucumber.io)
## 说明
```text ```text
Cypress几年前还属于一个比较小众的Web测试方案,现如今已有替代Selenium成为Web自动化测试头把交椅的实力。 Cypress几年前还属于一个比较小众的Web测试方案,现如今已有替代Selenium成为Web自动化测试头把交椅的实力。
...@@ -16,5 +17,10 @@ Cypress几年前还属于一个比较小众的Web测试方案,现如今已有 ...@@ -16,5 +17,10 @@ Cypress几年前还属于一个比较小众的Web测试方案,现如今已有
- 并发执行 - 并发执行
- 各大 IDE 均支持关键词高亮 - 各大 IDE 均支持关键词高亮
用例参考: ## 用例参考:
[点击此链接](./cypress/integration/case-948.feature) [点击此链接](./cypress/integration/case-948.feature)
## 测试执行及结果展示:
- 运行命令: npm run cypress:run
- 测试执行完成后可借助插件 [multiple-cucumber-html-reporter](https://github.com/wswebcreation/multiple-cucumber-html-reporter) 在项目根目录运行命令 node report.js。结束后测试报告已生成在./cypress/reports/index.html。
- ![结果截图](./cypress/reports/result.png)
{ {
"baseUrl": "http://172.22.18.152/", "baseUrl": "http://172.22.18.152/",
"env": { "env": {
"TAGS": "" "TAGS": "@dryrun"
}, },
"retries": { "retries": {
"runMode": 0, "runMode": 0,
......
...@@ -13,17 +13,17 @@ ...@@ -13,17 +13,17 @@
"uri": "case-948.feature", "uri": "case-948.feature",
"elements": [ "elements": [
{ {
"id": "end-to-end-test-case-948;case-948", "id": "end-to-end-test-case-948;hello-world",
"keyword": "Scenario", "keyword": "Scenario",
"line": 8, "line": 8,
"name": "case-948", "name": "hello world",
"tags": [ "tags": [
{ {
"name": "@case-948", "name": "@case-948",
"line": 1 "line": 1
}, },
{ {
"name": "@register", "name": "@dryrun",
"line": 7 "line": 7
} }
], ],
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
"name": "Home page opened", "name": "Home page opened",
"result": { "result": {
"status": "passed", "status": "passed",
"duration": 155000000 "duration": 555000000
} }
}, },
{ {
...@@ -51,13 +51,58 @@ ...@@ -51,13 +51,58 @@
}, },
{ {
"arguments": [], "arguments": [],
"keyword": "Then ", "keyword": "Given ",
"line": 9, "line": 9,
"name": "Register with testData number \"case-948\"", "name": "Home page opened",
"result": {
"status": "passed",
"duration": 121000000
}
}
]
},
{
"id": "end-to-end-test-case-948;case-948",
"keyword": "Scenario",
"line": 16,
"name": "case-948",
"tags": [
{
"name": "@case-948",
"line": 1
},
{
"name": "@login",
"line": 15
}
],
"type": "scenario",
"steps": [
{
"arguments": [],
"keyword": "Given ",
"line": 4,
"name": "Home page opened",
"result": {
"status": "skipped"
}
},
{
"arguments": [],
"keyword": "Then ",
"line": 5,
"name": "Get testing data file \"accounts.json\" and save in context",
"result": {
"status": "skipped"
}
},
{
"arguments": [],
"keyword": "Then ",
"line": 17,
"name": "login after input credential with testData number \"case-948\"",
"result": { "result": {
"status": "failed", "status": "skipped"
"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)"
} }
} }
] ]
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
"name": "automation", "name": "automation",
"password": "admin123", "password": "admin123",
"email": "automation@33.cn", "email": "automation@33.cn",
"mobilePhone": "13000000000" "mobilePhone": "13000000000",
"authCode": 1111
} }
} }
...@@ -3,6 +3,10 @@ Feature: end to end test case 948 ...@@ -3,6 +3,10 @@ Feature: end to end test case 948
Background: log on home page Background: log on home page
Given Home page opened Given Home page opened
Then Get testing data file "accounts.json" and save in context Then Get testing data file "accounts.json" and save in context
@dryrun
Scenario: hello world
Given Home page opened
@register @register
Scenario: case-948 Scenario: case-948
......
...@@ -12,8 +12,11 @@ Then('login after input credential with testData number {string}', (caseNum) => ...@@ -12,8 +12,11 @@ Then('login after input credential with testData number {string}', (caseNum) =>
cy.get('form').should('have.class', 'login-form').within(() => { cy.get('form').should('have.class', 'login-form').within(() => {
debugger debugger
var data = testFile[caseNum] var data = testFile[caseNum]
cy.xpath('div[1]//input').type(data.username) cy.xpath('div[1]//input').type(data.name)
cy.xpath('div[2]//input').type(data.password) cy.xpath('div[2]//input').type(data.password)
cy.xpath('div[3]//input').type(data.authCode)
cy.xpath('div[4]//button').click()
}) })
}) })
cy.url().should('include', 'home')
}) })
\ No newline at end of file
const {After} = require("cypress-cucumber-preprocessor/steps") const {After} = require("cypress-cucumber-preprocessor/steps")
// Asynchronous Promise // Asynchronous Promise
After(() => { After(() => {
cy.log('produce cucumber reports.') 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() return Promise.resolve()
}); });
\ No newline at end of file
...@@ -17,8 +17,16 @@ ...@@ -17,8 +17,16 @@
*/ */
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const cucumber = require('cypress-cucumber-preprocessor').default const cucumber = require('cypress-cucumber-preprocessor').default
const fs = require('fs');
module.exports = (on, config) => { module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits // `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config // `config` is the resolved Cypress config
on('file:preprocessor', cucumber()) on('file:preprocessor', cucumber())
on('after:run', (results) => {
if (results) {
fs.mkdirSync("cypress/.run", { recursive: true });
fs.writeFile("cypress/.run/results.json", JSON.stringify(results));
}
})
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
"cypress:open": "npx cypress open", "cypress:open": "npx cypress open",
"cypress:record": "npx cypress run --record --key <YOUR_KEY>", "cypress:record": "npx cypress run --record --key <YOUR_KEY>",
"cypress:ci": "npx cypress:run --parallel", "cypress:ci": "npx cypress:run --parallel",
"cypress:run": "npx cypress-tags run -g **/*.features", "cypress:run": "npx cypress-tags run -g **/*.features --browser chrome",
"cypress:tags": "npx cypress-tags run -e TAGS='@dryrun'" "cypress:tags": "npx cypress-tags run -e TAGS='@dryrun'"
}, },
"author": "", "author": "",
......
const report = require('multiple-cucumber-html-reporter');
const fs = require('fs');
const mapOs = (os) => {
if(os.startsWith('win')) {
return 'windows';
} else if (os.startsWith('osx')) {
return 'osx';
} else if (os.startsWith('linux')) {
return 'linux';
} else if (os.startsWith('ubuntu')) {
return 'ubuntu';
} else if (os.startsWith('android')) {
return 'android';
} else if (os.startsWith('ios')) {
return 'ios';
}
};
fs.readFile('cypress/.run/results.json', function read(err, data) {
if (err) {
throw err;
}
var runInfos = JSON.parse(data);
report.generate({
jsonDir: './cypress/cucumber-json/',
reportPath: './cypress/reports/',
metadata:{
browser: {
name: runInfos.browserName,
version: runInfos.browserVersion
},
device: 'Cypress',
platform: {
name: mapOs(runInfos.osName)
}
},
customData: {
title: 'Run info',
data: [
{label: 'Project', value: 'project'},
{label: 'Execution Start Time', value: new Date(runInfos.startedTestsAt).toLocaleString()},
{label: 'Execution End Time', value: new Date(runInfos.endedTestsAt).toLocaleString()}
]
}
});
});
\ No newline at end of file
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