#!/usr/bin/env python import os import sys import subprocess from pipes import quote from optparse import OptionParser, BadOptionError, AmbiguousOptionError APPLICATION = 'mocha' DEFAULT_ARGS = ['--recursive', '--require', 'should'] VAGRANT_SCRIPT = '/vagrant/test/js/runtests' REPORT_DIRECTORY = '../../build/log' class PassThroughOptionParser(OptionParser): """ An unknown option pass-through implementation of OptionParser. When unknown arguments are encountered, bundle with largs and try again, until rargs is depleted. sys.exit(status) will still be called if a known argument is passed incorrectly (e.g. missing arguments or bad argument types, etc.) Borrowed from: http://stackoverflow.com/a/9307174 """ def _process_args(self, largs, rargs, values): while rargs: try: OptionParser._process_args(self, largs, rargs, values) except (BadOptionError, AmbiguousOptionError), error: largs.append(error.opt_str) def execute_command(command, return_output=False, shell=False): prog = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE if return_output else None) return prog.wait() if not return_output else \ prog.communicate()[0] def get_report_directory(): path = os.path.abspath(REPORT_DIRECTORY) try: os.makedirs(REPORT_DIRECTORY) except OSError: pass return path def get_script_directory(): return os.path.dirname(os.path.abspath(sys.argv[0])) def parse_commandline(): parser = PassThroughOptionParser(usage='%prog [options] [additional arguments' ' for {0}]'.format(APPLICATION)) parser.add_option('-b', '--build', action='store_true', help='Enable reporting.') parser.add_option('-v', '--verbose', action='store_true', help='Be more verbose.') parser.add_option('-i', '--include', metavar='PATTERN', action='append', help='Include only specific files/test cases.' ' (Can be supplied multiple times.)') parser.add_option('-e', '--exclude', metavar='PATTERN', action='append', help='Exclude specific files/test cases. ' '(Can be supplied multiple times.)') parser.add_option('-V', '--vagrant', action='store_true', help='Run in vagrant VM') return parser.parse_args() def main(): options, arguments = parse_commandline() if options.vagrant and os.environ['USER'] != 'vagrant': # Check if vagrant is installed vagrant_path = execute_command('which vagrant', True, True).strip() if not vagrant_path: print 'ERROR: vagrant not found!' return 2 # Call the script in the Vagrant VM with the same parameters commandline = ' '.join(quote(p) for p in sys.argv[1:]) return execute_command('vagrant ssh -c "{0} {1}"' ''.format(VAGRANT_SCRIPT, commandline), shell=True) else: # Environment preparation and verification os.chdir(get_script_directory()) application_path = execute_command('which {0}'.format(APPLICATION), True, True).strip() if not application_path: print 'ERROR: {0} not found!'.format(APPLICATION) return 2 os.environ['NODE_PATH'] = os.environ.get('NODE_PATH', '') + \ ':/usr/local/lib/node_modules' \ ':/usr/local/share/npm/lib/node_modules' \ ':/usr/lib/node_modules:./testlib' # Commandline preparation command_options, more_command_options = [], None if options.include or options.exclude: for pattern in (options.include or options.exclude): command_options.append('--grep') command_options.append(pattern) if options.exclude: command_options.append('--invert') if options.build: more_command_options = command_options[:len(command_options)] + \ ['--reporter', 'mocha-cobertura-reporter'] command_options.extend(['--reporter', 'xunit']) elif options.verbose: command_options.extend(['--reporter', 'spec']) else: command_options.extend(['--reporter', 'nyan']) if not any(os.path.isfile(a) or os.path.isdir(a) for a in arguments): arguments.append('.') # Application invocation.. if more_command_options is None: execute_command([application_path] + DEFAULT_ARGS + command_options + arguments) else: result_data = execute_command([application_path] + DEFAULT_ARGS + command_options + arguments, True) coverage_data = execute_command([application_path] + DEFAULT_ARGS + more_command_options + arguments, return_output=True) # Result storage report_directory = get_report_directory() result_path = os.path.join(report_directory, 'mocha_results.xml') coverage_path = os.path.join(report_directory, 'mocha_coverage.xml') with open(result_path, 'w') as result_file: result_file.write(result_data) with open(coverage_path, 'w') as coverage_file: coverage_file.write(coverage_data) return 0 if __name__ == '__main__': sys.exit(main())