Skip to content

Commit

Permalink
Allow junit-reporter to work when a runner has multiple spec files pe…
Browse files Browse the repository at this point in the history
…r runner (#3818)

## Proposed changes

When a runner/instance runs more than a single spec file, the output from the junit-reporter is mangled. The logic of `prepareXml()` assumed that there is only one spec file/suite to process. These changes still process a single spec file per runner, but now also outputs correct xml if there is more than one spec file run per runner.

## Types of changes

[//]: # (What types of changes does your code introduce to WebdriverIO?)
[//]: # (_Put an `x` in the boxes that apply_)

- [ ] Bugfix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

## Checklist

[//]: # (_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._)

- [x] I have read the [CONTRIBUTING](https://github.com/webdriverio/webdriverio/blob/master/CONTRIBUTING.md) doc
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] I have added necessary documentation (if appropriate)

## Further comments

[//]: # (If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...)

### Reviewers: @webdriverio/technical-committee
  • Loading branch information
naddison authored and christian-bromann committed Apr 8, 2019
1 parent 3668cc9 commit 217db81
Show file tree
Hide file tree
Showing 5 changed files with 761 additions and 45 deletions.
94 changes: 49 additions & 45 deletions packages/wdio-junit-reporter/src/index.js
Expand Up @@ -29,59 +29,63 @@ class JunitReporter extends WDIOReporter {
? `${runner.sanitizedCapabilities}-${this.options.packageName}`
: runner.sanitizedCapabilities

for (let specId of Object.keys(runner.specs)) {
for (let suiteKey of Object.keys(this.suites)) {
/**
* ignore root before all
*/
/* istanbul ignore if */
if (suiteKey.match(/^"before all"/)) {
continue
}
let index = 0

const suite = this.suites[suiteKey]
const suiteName = this.prepareName(suite.title)
const testSuite = builder.testSuite()
.name(suiteName)
.timestamp(suite.start)
.time(suite._duration / 1000)
.property('specId', specId)
.property('suiteName', suite.title)
.property('capabilities', runner.sanitizedCapabilities)
.property('file', runner.specs[0].replace(process.cwd(), '.'))

for (let testKey of Object.keys(suite.tests)) {
if (testKey !== 'undefined') { // fix cucumber hooks crashing reporter
const test = suite.tests[testKey]
const testName = this.prepareName(test.title)
const testCase = testSuite.testCase()
.className(`${packageName}.${suiteName}`)
.name(testName)
.time(test._duration / 1000)

if (test.state === 'pending' || test.state === 'skipped') {
testCase.skipped()
}
for (let suiteKey of Object.keys(this.suites)) {
/**
* ignore root before all
*/
/* istanbul ignore if */
if (suiteKey.match(/^"before all"/)) {
continue
}

if (test.error) {
const errorOptions = this.options.errorOptions
if (errorOptions) {
for (const key of Object.keys(errorOptions)) {
testCase[key](test.error[errorOptions[key]])
}
} else {
// default
testCase.error(test.error.message)
const specFileName = runner.specs[index]
const suite = this.suites[suiteKey]
const suiteName = this.prepareName(suite.title)
const testSuite = builder.testSuite()
.name(suiteName)
.timestamp(suite.start)
.time(suite._duration / 1000)
.property('specId', index)
.property('suiteName', suite.title)
.property('capabilities', runner.sanitizedCapabilities)
.property('file', specFileName.replace(process.cwd(), '.'))

for (let testKey of Object.keys(suite.tests)) {
if (testKey !== 'undefined') { // fix cucumber hooks crashing reporter
const test = suite.tests[testKey]
const testName = this.prepareName(test.title)
const testCase = testSuite.testCase()
.className(`${packageName}.${suiteName}`)
.name(testName)
.time(test._duration / 1000)

if (test.state === 'pending' || test.state === 'skipped') {
testCase.skipped()
}

if (test.error) {
const errorOptions = this.options.errorOptions
if (errorOptions) {
for (const key of Object.keys(errorOptions)) {
testCase[key](test.error[errorOptions[key]])
}
testCase.standardError(`\n${test.error.stack}\n`)
} else {
// default
testCase.error(test.error.message)
}

const output = this.getStandardOutput(test)
if (output) testCase.standardOutput(`\n${output}\n`)
testCase.standardError(`\n${test.error.stack}\n`)
}

const output = this.getStandardOutput(test)
if (output) testCase.standardOutput(`\n${output}\n`)
}
}

index++
}

return builder.build()
}

Expand Down
@@ -0,0 +1,109 @@
{
"type": "runner",
"start": "2018-04-17T09:09:27.771Z",
"_duration": 907,
"cid": "0-0",
"capabilities": {
"acceptSslCerts": true,
"applicationCacheEnabled": false,
"browserConnectionEnabled": false,
"browserName": "chrome",
"chrome": {
"chromedriverVersion": "2.33.506106 (8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2)",
"userDataDir": "/var/folders/ns/8mj2mh0x27b_gsdddy1knnsm0000gn/T/.org.chromium.Chromium.wPrPpk"
},
"cssSelectorsEnabled": true,
"databaseEnabled": false,
"handlesAlerts": true,
"hasTouchScreen": false,
"javascriptEnabled": true,
"locationContextEnabled": true,
"mobileEmulationEnabled": false,
"nativeEvents": true,
"networkConnectionEnabled": false,
"pageLoadStrategy": "normal",
"platform": "Mac OS X",
"rotatable": false,
"setWindowRect": true,
"takesHeapSnapshot": true,
"takesScreenshot": true,
"unexpectedAlertBehaviour": "",
"version": "65.0.3325.181",
"webStorageEnabled": true
},
"sanitizedCapabilities": "chrome.65_0_3325_181.macosx",
"config": {
"hostname": "127.0.0.1",
"port": 4444,
"sync": true,
"specs": [
"./specs/sync.spec.js"
],
"suites": {},
"exclude": [],
"outputDir": "/path/to/project/test",
"logLevel": "trace",
"baseUrl": "http://localhost",
"bail": 0,
"waitforInterval": 500,
"waitforTimeout": 10000,
"framework": "mocha",
"reporters": [
"dot",
"junit",
"spec"
],
"maxInstances": 1,
"maxInstancesPerCapability": 100,
"connectionRetryTimeout": 90000,
"connectionRetryCount": 3,
"debug": false,
"execArgv": [],
"runnerEnv": {},
"runner": "local",
"mochaOpts": {
"timeout": 60000,
"ui": "bdd",
"fullStackTrace": true,
"files": [
"/path/to/project/test/specs/sync.spec.js"
]
},
"jasmineNodeOpts": {
"defaultTimeoutInterval": 10000
},
"before": [],
"beforeSession": [],
"beforeSuite": [],
"beforeHook": [],
"beforeTest": [],
"beforeCommand": [],
"afterCommand": [],
"afterTest": [],
"afterHook": [],
"afterSuite": [],
"afterSession": [],
"after": [],
"onReload": [],
"beforeFeature": [],
"beforeScenario": [],
"beforeStep": [],
"afterFeature": [],
"afterScenario": [],
"afterStep": [],
"coloredLogs": true,
"_": [
"wdio.conf.js"
],
"$0": "../packages/wdio-cli/bin/wdio",
"capabilities": {
"browserName": "chrome"
}
},
"specs": [
"/path/to/project/test/specs/sync.spec.js",
"/path/to/project/test/specs/aSecondSpec.spec.js"
],
"failures": 1,
"end": "2018-04-17T09:09:28.678Z"
}

0 comments on commit 217db81

Please sign in to comment.