Skip to content

Commit cb757d2

Browse files
authored
Improved using of reporters (#193)
* improved xml/html/cli reports * moved header output to cli reporter to be compatible with xunit * moved version and root output to cli reporter * added reporters documentation * parse options * fixed tests * tests are fixed
1 parent e2f818e commit cb757d2

File tree

21 files changed

+257
-59
lines changed

21 files changed

+257
-59
lines changed

docs/reports.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Reporters
2+
3+
## Cli (default)
4+
5+
By default CodeceptJS provides cli reporter with console output.
6+
Test names and failures will be printed to screen.
7+
8+
```
9+
GitHub --
10+
✓ search in 2577ms
11+
✓ signin in 2170ms
12+
✖ register in 1306ms
13+
14+
-- FAILURES:
15+
16+
1) GitHub: register:
17+
Field q not found by name|text|CSS|XPath
18+
19+
Scenario Steps:
20+
21+
- Within .js-signup-form: I.fillField("q", "aaa") at examples/github_test.js:29:7
22+
- Within .js-signup-form: I.fillField("user[password]", "user@user.com") at examples/github_test.js:28:7
23+
- Within .js-signup-form: I.fillField("user[email]", "user@user.com") at examples/github_test.js:27:7
24+
- Within .js-signup-form: I.fillField("user[login]", "User") at examples/github_test.js:26:7
25+
26+
27+
28+
Run with --verbose flag to see NodeJS stacktrace
29+
```
30+
31+
For dynamic step-by-step output add `--steps` option to `run` command:
32+
33+
```
34+
GitHub --
35+
search
36+
• I am on page "https://github.com"
37+
• I am on page "https://github.com/search"
38+
• I fill field "Search GitHub", "CodeceptJS"
39+
• I press key "Enter"
40+
• I see "Codeception/CodeceptJS", "a"
41+
✓ OK in 2681ms
42+
43+
signin
44+
• I am on page "https://github.com"
45+
• I click "Sign in"
46+
• I see "Sign in to GitHub"
47+
• I fill field "Username or email address", "something@totest.com"
48+
• I fill field "Password", "123456"
49+
• I click "Sign in"
50+
• I see "Incorrect username or password.", ".flash-error"
51+
✓ OK in 2252ms
52+
53+
register
54+
• I am on page "https://github.com"
55+
Within .js-signup-form:
56+
• I fill field "user[login]", "User"
57+
• I fill field "user[email]", "user@user.com"
58+
• I fill field "user[password]", "user@user.com"
59+
• I fill field "q", "aaa"
60+
✖ FAILED in 1260ms
61+
```
62+
To get additional information about test execution use `--debug` option. This will show execution steps
63+
as well as notices from test runner. To get even more information with more technical details like error stacktraces,
64+
and global promises, or events use `--verbose` mode.
65+
66+
```
67+
GitHub --
68+
register
69+
[1] Starting recording promises
70+
Emitted | test.before
71+
> WebDriverIO._before
72+
[1] Queued | hook WebDriverIO._before()
73+
[1] Queued | amOnPage: https://github.com
74+
Emitted | step.before (I am on page "https://github.com")
75+
• I am on page "https://github.com"
76+
Emitted | step.after (I am on page "https://github.com")
77+
Emitted | test.start ([object Object])
78+
...
79+
```
80+
81+
Please use verbose output when reporting issues to GitHub.
82+
83+
## XML
84+
85+
Use default xunit reporter of Mocha to print xml reports. Provide `--reporter xunit` to get the report to screen.
86+
It is recommended to use more powerful [`mocha-junit-reporter`](https://www.npmjs.com/package/mocha-junit-reporter) package
87+
ot get better support for Jenkins CI.
88+
89+
Install it via NPM (locally or globally, depending on CodeceptJS installation type):
90+
91+
```
92+
npm i mocha-junit-reporter
93+
```
94+
95+
Additional configuration should be added to `codecept.json` to print xml report to `output` directory:
96+
97+
```json
98+
"mocha": {
99+
"reporterOptions": {
100+
"mochaFile": "output/result.xml"
101+
}
102+
},
103+
```
104+
105+
Execute CodeceptJS with JUnit reporter:
106+
107+
```
108+
codeceptjs run --reporter mocha-junit-reporter
109+
```
110+
111+
Result will be located at `output/result.xml` file.
112+
113+
114+
## Html
115+
116+
Best HTML reports could be prodused with [mochawesome](https://www.npmjs.com/package/mochawesome) reporter.
117+
Install it via NPM:
118+
119+
```
120+
npm i mochawesome
121+
```
122+
123+
Configure it to use `output` directory to print HTML reports:
124+
125+
```json
126+
"mocha": {
127+
"reporterOptions": {
128+
"reportDir": "output"
129+
}
130+
},
131+
```
132+
133+
Execute CodeceptJS with HTML reporter:
134+
135+
```
136+
codeceptjs run --reporter mochawesome.
137+
```
138+
139+
Result will be located at `output/index.html` file.
140+

examples/codecept.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66
"WebDriverIO": {
77
"url": "http://localhost",
88
"browser": "firefox",
9-
"restart": false
9+
"restart": true
10+
}
11+
},
12+
"mocha": {
13+
"reporterOptions": {
14+
"mochaFile": "./output/result.xml"
1015
}
1116
},
12-
"mocha": {},
1317
"name": "tests",
1418
"bootstrap": "./bootstrap.js",
1519
"include": {

lib/assert/empty.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ class EmptinessAssertion extends Assertion {
2020
if (Array.isArray(this.params.value)) {
2121
this.params.value = '[' + this.params.value.join(', ') + ']';
2222
}
23-
23+
2424
let err = new AssertionFailedError(this.params, "{{customMessage}}expected {{subject}} '{{value}}' {{type}}");
2525

2626
err.cliMessage = () => {
27-
let msg = err.message
28-
.replace('{{value}}', output.colors.yellow.bold('{{value}}'))
27+
let msg = err.template
28+
.replace('{{value}}', output.colors.bold('{{value}}'))
2929
.replace('{{subject}}', output.colors.bold('{{subject}}'));
3030
return template(msg, this.params);
3131
};

lib/assert/equal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class EqualityAssertion extends Assertion {
2020
let err = new AssertionFailedError(params, "{{customMessage}}expected {{jar}} '{{expected}}' {{type}} '{{actual}}'");
2121
err.showDiff = false;
2222
err.cliMessage = () => {
23-
let msg = err.message
23+
let msg = err.template
2424
.replace('{{jar}}', output.colors.bold('{{jar}}'));
2525
return template(msg, this.params);
2626
};

lib/assert/error.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function AssertionFailedError(params, template) {
2525
this.inspect = () => {
2626
let params = this.params || {};
2727
let msg = params.customMessage || '';
28-
return msg + subs(this.template, params);
28+
return msg + subs(this.template, params);
2929
};
3030

3131
this.cliMessage = () => {

lib/assert/include.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ class InclusionAssertion extends Assertion {
2424
getException() {
2525
let params = this.params;
2626
params.jar = template(params.jar, params);
27-
let err = new AssertionFailedError(params, "{{customMessage}}expected {{jar}} {{type}} {{needle}}");
27+
let err = new AssertionFailedError(params, '{{customMessage}}expected {{jar}} {{type}} "{{needle}}"');
2828
err.expected = params.needle;
2929
err.actual = params.haystack;
3030
if (Array.isArray(this.params.haystack)) {
3131
this.params.haystack = this.params.haystack.join("\n___(next element)___\n");
3232
}
33-
err.cliMessage = () => {
34-
let msg = err.message
35-
.replace('{{needle}}', output.colors.yellow.bold('{{needle}}'))
36-
.replace('{{jar}}', output.colors.bold('{{jar}}'));
33+
err.cliMessage = function() {
34+
let msg = this.template
35+
.replace('{{jar}}', output.colors.bold('{{jar}}'))
36+
.replace('{{needle}}', output.colors.bold('{{needle}}'));
3737
return template(msg, this.params);
3838
};
3939
return err;

lib/codecept.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class Codecept {
2121
this.mocha.ui(scenarioUi);
2222
if (opts.reporter) {
2323
// custom reporters
24-
this.mocha.reporter(opts.reporter, opts.reporterOptions);
24+
this.mocha.reporter(opts.reporter, this.reporterOptions());
2525
} else {
2626
// standard reporter. TODO: make them run side by side
2727
this.mocha.reporter(reporter, opts);
@@ -43,6 +43,7 @@ class Codecept {
4343
require('./listener/steps');
4444
require('./listener/helpers');
4545
require('./listener/exit');
46+
require('./listener/trace');
4647

4748
// loading bootstrap
4849
if (this.config.bootstrap && fileExists(fsPath.join(dir, this.config.bootstrap))) {
@@ -64,6 +65,24 @@ class Codecept {
6465
});
6566
}
6667

68+
reporterOptions() {
69+
var reporterOptions = Object.assign(this.config.mocha.reporterOptions || {});
70+
if (this.opts.reporterOptions !== undefined) {
71+
this.opts.reporterOptions.split(",").forEach(function(opt) {
72+
var L = opt.split("=");
73+
if (L.length > 2 || L.length === 0) {
74+
throw new Error("invalid reporter option '" + opt + "'");
75+
} else if (L.length === 2) {
76+
reporterOptions[L[0]] = L[1];
77+
} else {
78+
reporterOptions[L[0]] = true;
79+
}
80+
});
81+
}
82+
return reporterOptions;
83+
84+
}
85+
6786
run(test) {
6887
this.mocha.files = this.testFiles;
6988
if (test) {

lib/command/run.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
'use strict';
22
let getConfig = require('./utils').getConfig;
33
let getTestRoot = require('./utils').getTestRoot;
4-
var Codecept = require('../codecept');
4+
let Codecept = require('../codecept');
5+
let output = require('../output');
56

67
module.exports = function (suite, test, options) {
7-
console.log('CodeceptJS v' + Codecept.version());
88
let testRoot = getTestRoot(suite);
99
let config = getConfig(testRoot);
10-
try {
10+
try {
1111
let codecept = new Codecept(config, options);
1212
codecept.init(testRoot);
13-
codecept.loadTests();
13+
codecept.loadTests();
1414
codecept.run(test);
1515
} catch (err) {
16-
let output = require('../output');
1716
output.print('');
1817
output.error(err.message);
1918
output.print('');

lib/command/utils.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@ let colors = require('colors');
77

88
module.exports.getTestRoot = function (currentPath) {
99
let testsPath = path.resolve(currentPath || '.');
10-
11-
if (!currentPath) {
12-
output.print(`Test root is assumed to be ${colors.yellow.bold(testsPath)}`);
13-
} else {
14-
output.print(`Using test root ${colors.bold(testsPath)}`);
15-
}
1610
return testsPath;
1711
};
1812

lib/event.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ module.exports = {
3030
msg += ` (${param.toString()})`;
3131
}
3232
log(msg);
33-
this.dispatcher.emit.apply(this.dispatcher, arguments);
33+
try {
34+
this.dispatcher.emit.apply(this.dispatcher, arguments);
35+
} catch (err) {
36+
log(`Error processing ${event} event:`);
37+
log(err.stack);
38+
throw err;
39+
}
3440
},
3541

3642
// for testing only!

0 commit comments

Comments
 (0)