meilke/nunit-command

View on GitHub
index.js

Summary

Maintainability
D
2 days
Test Coverage
var fs = require('fs'),
path = require('path'),
_ = require('underscore'),
msbuild = require('./msbuild.js'),
sax = require('sax');

exports.findTestAssemblies = function(files, options) {
  var assemblies = [];
  var projects = [];
  files.forEach(function(file) {
    switch(path.extname(file)) {
      case '.sln': projects = projects.concat(msbuild.getSolutionProjectInfo(file)); break;
      case '.csproj': projects.push(msbuild.getProjectInfo(file)); break;
      default: {
        if (!fs.existsSync(file)) throw new Error('Assembly not found: ' + file);
        assemblies.push(path.normalize(file));
      }
    }
  });
  projects.
  filter(function(project) { return _.contains(project.references, 'nunit.framework'); }).
  forEach(function(project) {
    var outputs = project.output.filter(function(output) { return fs.existsSync(output); });
    if (outputs.length === 0) throw new Error('No assemblies exist for project: ' + project.path);
    
    if (options && options.config) {
      outputs = outputs.filter(function(output) { 
        return output.toLowerCase().indexOf(options.config.toLowerCase()) > -1; 
      });
    }

    if (outputs.length === 0) throw new Error('No assemblies exist for project matching config parameter: ' + project.path);
    assemblies.push(path.normalize(outputs[0]));
  });
  return assemblies;
};

exports.buildCommand = function(assemblies, options) {

  var nunit = options.platform === 'x86' ? 'nunit-console-x86.exe' : 'nunit-console.exe';
  if (options.path) nunit = path.join(options.path, nunit);

  nunit = nunit.replace(/\\/g, path.sep);

  var args = assemblies.map(function(assembly) { return '"' + assembly + '"'; });

  if (options.run && options.run.length > 0) args.push('/run:"' + options.run.join(',') + '"');
  if (options.runlist) args.push('/runlist:"' + options.runlist + '"');
  if (options.config) args.push('/config:"' + options.config + '"');
  if (options.result) args.push('/result:"' + options.result + '"');
  if (options.noresult) args.push('/noresult');
  if (options.output) args.push('/output:"' + options.output + '"');
  if (options.err) args.push('/err:"' + options.err + '"');
  if (options.work) args.push('/work:"' + options.work + '"');
  if (options.labels) args.push('/labels');
  if (options.trace) args.push('/trace:' + options.trace);
  if (options.include && options.include.length > 0) args.push('/include:"' + options.include.join(',') + '"');
  if (options.exclude && options.exclude.length > 0) args.push('/exclude:"' + options.exclude.join(',') + '"');
  if (options.framework) args.push('/framework:"' + options.framework + '"');
  if (options.process) args.push('/process:' + options.process);
  if (options.domain) args.push('/domain:' + options.domain);
  if (options.apartment) args.push('/apartment:' + options.apartment);
  if (options.noshadow) args.push('/noshadow');
  if (options.nothread) args.push('/nothread');
  if (options.basepath) args.push('/basepath:"' + options.basepath + '"');
  if (options.privatebinpath && options.privatebinpath.length > 0) args.push('/privatebinpath:"' + options.privatebinpath.join(';') + '"');
  if (options.timeout) args.push('/timeout:' + options.timeout);
  if (options.wait) args.push('/wait');
  if (options.nologo) args.push('/nologo');
  if (options.nodots) args.push('/nodots');
  if (options.stoponerror) args.push('/stoponerror');
  if (options.cleanup) args.push('/cleanup');

  return {
    path: nunit,
    args: args
  };
};

exports.createTeamcityLog = function(results) {

  var parser = sax.parser(true);
  var log = [];
  var ancestors = [];
  var message, stackTrace;

  var getSuiteName = function(node) { return node.attributes.type === 'Assembly' ? 
  path.basename(node.attributes.name.replace(/\\/g, path.sep)) : node.attributes.name; };

  parser.onopentag = function (node) {
    ancestors.push(node);
    switch (node.name) {
      case 'test-suite': log.push('##teamcity[testSuiteStarted name=\'' + getSuiteName(node) + '\']'); break;
      case 'test-case': 
      if (node.attributes.executed === 'True') log.push('##teamcity[testStarted name=\'' + node.attributes.name + '\']'); 
      message = '';
      stackTrace = '';
      break; 
    }
  };

  parser.oncdata = function (data) {
    data = data.
    replace(/\|/g, '||').
    replace(/\'/g, '|\'').
    replace(/\n/g, '|n').
    replace(/\r/g, '|r').
    replace(/\u0085/g, '|x').
    replace(/\u2028/g, '|l').
    replace(/\u2029/g, '|p').
    replace(/\[/g, '|[').
    replace(/\]/g, '|]');

    switch (_.last(ancestors).name) {
      case 'message': message += data; break;
      case 'stack-trace': stackTrace += data; break;
    }
  };

  parser.onclosetag = function (node) {
    node = ancestors.pop();
    switch (node.name) {
      case 'test-suite': log.push('##teamcity[testSuiteFinished name=\'' + getSuiteName(node) + '\']'); break;
      case 'test-case': 
      if (node.attributes.result === 'Ignored')
        log.push('##teamcity[testIgnored name=\'' + node.attributes.name + '\'' + 
          (message ? ' message=\'' + message + '\'' : '') + ']'); 
      else if (node.attributes.executed === 'True') {
        if (node.attributes.success === 'False') {
          log.push('##teamcity[testFailed name=\'' + node.attributes.name + '\'' +
            (message ? ' message=\'' + message + '\'' : '') + 
            (stackTrace ? ' details=\'' + stackTrace + '\'' : '') + ']');
        }
        var duration = node.attributes.time ? ' duration=\'' + parseInt(
          node.attributes.time.replace(/[\.\:]/g, '')) + '\'' : '';
        log.push('##teamcity[testFinished name=\'' + node.attributes.name + '\'' + duration + ']');
      }
      break;
    }
  };

  parser.write(fs.readFileSync(results, 'utf8')).close();

  return log;
};