diff --git a/README.md b/README.md index f99dcaf..16f2222 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,72 @@ You can pass list of reporters as a CLI argument too: karma start --reporters junit,dots ``` +## Produce test result with schema acceptable in sonar + +To make this possible, it's required to make the classnames of each tests to match its file name. + +For Example: +```js +describe('analytics.AnalyticsModule_test', function(){ + + var analytics; + beforeEach(module('ECApp')); + beforeEach(module('angularytics')); + beforeEach(module('AnalyticsModule')); +... +``` + +should have a file name AnalyticsModule_test.js + +This will produce test result with schema acceptable in sonar. + +Grunt file reporters property example: +```js +reporters: ['junit', 'coverage', 'progress'], +junitReporter: { + outputDir: $junitResults, + suite: 'models' +}, +coverageReporter: { + type: 'lcov', + dir: $coverageOutputDir, + subdir: '.' +}, +preprocessors: { + 'src/main/webapp/public/js/ec3.3/**/*.js': 'coverage', + 'src/main/webapp/public/js/ec3/**/*.js': 'coverage' +}, +plugins: [ + 'karma-jasmine', + 'karma-phantomjs-launcher', + 'ec-karma-junit-reporter23', + 'karma-coverage' +] +``` + +Sonar property example: +```js +sonar.projectName=js +sonar.sources=site-main-php/src/main/webapp/public/js +sonar.projectBaseDir=. +sonar.exclusions=site-main-php/src/main/webapp/public/js/lib/*.js,site-main-php/src/main/webapp/public/js/tests/**/*.php,site-main-php/src/main/webapp/public/js/tests/**/*.js,site-main-php/src/main/webapp/public/js/ec3.3/vendor/** +sonar.javascript.lcov.reportPath=site-main-php/target/coverage/lcov.info +sonar.javascript.jstestdriver.reportsPath=site-main-php/target/surefire-reports/ +sonar.tests=site-main-php/src/main/webapp/public/js/tests +``` + +Example junit xml report: +```xml + + + + + + + + +... +``` ---- For more information on Karma see the [homepage]. diff --git a/index.js b/index.js index 0252186..4d316c4 100644 --- a/index.js +++ b/index.js @@ -8,10 +8,12 @@ var JUnitReporter = function(baseReporterDecorator, config, logger, helper, form var log = logger.create('reporter.junit'); var reporterConfig = config.junitReporter || {}; var pkgName = reporterConfig.suite || ''; - var outputFile = helper.normalizeWinPath(path.resolve(config.basePath, reporterConfig.outputFile - || 'test-results.xml')); - var xml; + if (!reporterConfig.outputDir) { + throw new Error('You must set an output directory for JUnitReporter via the outputDir config property'); + } + + var outputDir = helper.normalizeWinPath(path.resolve(config.basePath, reporterConfig.outputDir)) + path.sep; var suites; var pendingFileWritings = 0; var fileWritingFinished = function() {}; @@ -25,15 +27,38 @@ var JUnitReporter = function(baseReporterDecorator, config, logger, helper, form var initliazeXmlForBrowser = function(browser) { var timestamp = (new Date()).toISOString().substr(0, 19); - var suite = suites[browser.id] = xml.ele('testsuite', { - name: browser.name, 'package': pkgName, timestamp: timestamp, id: 0, hostname: os.hostname() + var suite = suites[browser.id] = builder.create('testsuite'); + suite.att('name', browser.name) + .att('package', pkgName) + .att('timestamp', timestamp) + .att('id', 0) + .att('hostname', os.hostname()); + suite.ele('properties') + .ele('property', {name: 'browser.fullName', value: browser.fullName}); + }; + + var writeXmlForBrowser = function(browser) { + var outputFile = outputDir + 'TESTS-' + browser.name.replace(/ /g, '_') + '.xml'; + var xmlToOutput = suites[browser.id]; + + pendingFileWritings++; + helper.mkdirIfNotExists(outputDir, function() { + fs.writeFile(outputFile, xmlToOutput.end({pretty: true}), function(err) { + if (err) { + log.warn('Cannot write JUnit xml\n\t' + err.message); + } else { + log.debug('JUnit results written to "%s".', outputFile); + } + + if (!--pendingFileWritings) { + fileWritingFinished(); + } + }); }); - suite.ele('properties').ele('property', {name: 'browser.fullName', value: browser.fullName}); }; this.onRunStart = function(browsers) { suites = Object.create(null); - xml = builder.create('testsuites'); // TODO(vojta): remove once we don't care about Karma 0.10 browsers.forEach(initliazeXmlForBrowser); @@ -45,13 +70,6 @@ var JUnitReporter = function(baseReporterDecorator, config, logger, helper, form this.onBrowserComplete = function(browser) { var suite = suites[browser.id]; - - if (!suite) { - // This browser did not signal `onBrowserStart`. That happens - // if the browser timed out during the start phase. - return; - } - var result = browser.lastResult; suite.att('tests', result.total); @@ -61,34 +79,19 @@ var JUnitReporter = function(baseReporterDecorator, config, logger, helper, form suite.ele('system-out').dat(allMessages.join() + '\n'); suite.ele('system-err'); + + writeXmlForBrowser(browser); }; this.onRunComplete = function() { - var xmlToOutput = xml; - - pendingFileWritings++; - helper.mkdirIfNotExists(path.dirname(outputFile), function() { - fs.writeFile(outputFile, xmlToOutput.end({pretty: true}), function(err) { - if (err) { - log.warn('Cannot write JUnit xml\n\t' + err.message); - } else { - log.debug('JUnit results written to "%s".', outputFile); - } - - if (!--pendingFileWritings) { - fileWritingFinished(); - } - }); - }); - - suites = xml = null; + suites = null; allMessages.length = 0; }; this.specSuccess = this.specSkipped = this.specFailure = function(browser, result) { var spec = suites[browser.id].ele('testcase', { name: result.description, time: ((result.time || 0) / 1000), - classname: (pkgName ? pkgName + ' ' : '') + browser.name + '.' + result.suite.join(' ').replace(/\./g, '_') + classname: browser.name.replace(/ /g,'_').replace(/\./g,'_') + '.' + (pkgName ? pkgName + '.' : '') + result.suite[0] }); if (result.skipped) { @@ -117,4 +120,4 @@ JUnitReporter.$inject = ['baseReporterDecorator', 'config', 'logger', 'helper', // PUBLISH DI MODULE module.exports = { 'reporter:junit': ['type', JUnitReporter] -}; +}; \ No newline at end of file