#!/usr/bin/env ruby # encoding: UTF-8 require 'tins/xt' require 'tins/lines_file' include Tins::GO require 'utils' begin require 'utils/line_formatter' rescue LoadError end include Utils require 'drb' def usage puts <<-EOT Usage: #{File.basename($0)} [OPTS] [FILENAME[:LINENO]] Options are -n TESTNAME run the test TESTNAME in file FILENAME -t FRAMEWORK use test framework FRAMEWORK (rspec, test-unit or cucumber) -c start probe as a client -C FOO[=BAR] set/get env variable on probe server -l start probe as a server -u URI use this DRb URI communication -f FORMATTER use FORMATTER to display rspec output -h display this help Version is #{File.basename($0)} #{Utils::VERSION}. EOT exit 1 end def cmd(*args) if ENV.key?('BUNDLE_GEMFILE') args.unshift 'bundle', 'exec' end p args puts args * ' ' system(*args) or exit $?.exitstatus end def find_cmd(*cmds, on_fail: -> *cmds { raise fail "no #{cmds * '|'} command found" }) cmds.map { |c| `which #{c}`.full?(:chomp) }.compact.first or on_fail.(*cmds) end def spring? `bin/spring status`.lines.first =~ /^Spring is running:/ rescue Errno::ENOENT false end singleton_class.class_eval do memoize_function :spring? end def start_server Thread.abort_on_exception = $DEBUG spring? and puts "Found spring running, I'll try to use it for running tests." begin DRb.start_service DRbObject.new_with_uri($uri).shutdown rescue DRb::DRbConnError end Utils::ProbeServer.new($uri).start end def connect_server DRb.start_service probe_server = DRbObject.new_with_uri($uri) if setting = $opts[?C] case setting when /\A([^=]+)=([^=]+)\z/ probe_server.env[$1] = $2 when /\A([^=]+)\z/ puts probe_server.env[$1] else usage end end if $opts[?c] opts = $opts.subhash(*%w[n t f]).each_with_object([]) { |(k, v), a| v.full? and a.concat [ "-#{k}", v ] } probe_server.enqueue opts + $args exit end end $config = Utils::ConfigFile.new $config.configure_from_paths testrunner_args = [] if i = ARGV.index('--') testrunner_args.concat ARGV[(i + 1)..-1] $args = ARGV[0...i] else $args = ARGV.dup end $opts = go 'lct:n:u:C:f:h', $args $opts[?h] and usage $uri = $opts[?u] || 'drbunix:probe.socket' case when $opts[?l] start_server exit when $opts[?c], $opts[?C] connect_server end $args.empty? and exit puts "Running tests in #{$args.inspect}" case ($opts[?t] || $config.probe.test_framework).to_sym when :rspec case when spring? rspec = %w[ bin/spring rspec ] else rspec = [ find_cmd('rspec', 'spec') ] end rspec << '-rutils' unless $args.any? { |a| a.start_with?('-f') } rspec << '-f' << ($opts[?f] || 'Utils::LineFormatter') end $args = $args.map do |a| if Utils::Editor::FILE_LINENUMBER_REGEXP =~ a $~.captures.compact * ':' else a end end cmd 'ruby', '-I', $config.probe.include_dirs_argument, *rspec, *($args + testrunner_args) when :'test-unit' if testname = $opts[?n] cmd 'ruby', '-I', $config.probe.include_dirs_argument, *($args + testrunner_args), '-n', testname else $args = $args.inject([]) { |args, a| args.push(*File.directory?(a) ? Dir[File.join(a, ?*)] : a) } for filename in $args sl = filename.source_location if sl.linenumber lf = Tins::LinesFile.for_filename(*sl) if testname = lf.match_backward(/def\s+(\S+?)(?:\(|\s*$)/).full?(:first) cmd 'ruby', '-I', $config.probe.include_dirs_argument, sl.filename, *testrunner_args, '-n', testname else warn "no test found before line #{sl.linenumber}" end else cmd 'ruby', '-I', $config.probe.include_dirs_argument, sl.filename, *testrunner_args end end end when :cucumber cucumber = find_cmd('cucumber') if linenumber = $opts[?n] cmd 'ruby', cucumber, '-r', $config.probe.include_dirs_argument, '-l', linenumber, *($args + testrunner_args) else $args = $args.map do |a| if Utils::Editor::FILE_LINENUMBER_REGEXP =~ a $~.captures.compact * ':' else a end end cmd 'ruby', cucumber, '-r', $config.probe.include_dirs_argument, *($args + testrunner_args) end end