#!/usr/bin/env ruby ENV['PARALLEL_TESTS'] = 'yes' require 'multi_json' def tag_args tags tags.flat_map{ |tag| ['--tag', tag] } end def example_ids tags, specs json = `bundle exec rspec -f j --dry-run #{tag_args(tags).join(' ')} -- #{specs.join(' ')}` data = MultiJson.load(json) data['examples'].map{ |example| example['id'] } end def run(*args) pid = spawn(*args) Signal.trap("INT") { Process.kill("INT", pid) } Process.wait(pid) $? == 0 ensure Signal.trap("INT", "DEFAULT") end tags = ARGV.take_while { |arg| arg[0] != '-' } ARGV.shift(tags.length) opts = [] files = nil while arg = ARGV.shift case arg when '--' files = ARGV break when '--remainder' files = Dir['spec/**/*_spec.rb', 'test/**/*_test.rb'] existing = File.open('.travis.yml').each_line.flat_map do |line| next unless matches = line.match(%r{((?:test|spec)/(?:[\w\.]+/?)*)}) path = matches[1] path[-3..-1] == '.rb' ? path : path + '/**/*.rb' end.compact files -= Dir[*existing] else opts << arg end end files ||= Dir['spec', 'test/**/*_test.rb'] specs, tests = files.partition { |file| file.match /^spec/ } puts "The following specs will be executed:\n\t#{specs.join "\n\t"}\n\n" unless specs.empty? puts "The following tests will be executed:\n\t#{tests.join "\n\t"}\n\n" unless tests.empty? results = [] unless specs.empty? # run all non :isolate examples in parallel results << run(*%w{bundle exec parallel_rspec --}, *opts, *tag_args(tags | %w{~isolate}), '--', *specs) # find the example IDs of the isolate examples to be run in serial ids = example_ids(tags, specs) - example_ids(tags | %w{~isolate}, specs) unless ids.empty? results << run(*%w{bundle exec rspec}, *opts, '--', *ids) end end tests.each do |test| results << run(*%w{bundle exec ruby}, test) end if results.any?{ |result| !result } puts "\e[31m########## MONETA TESTSUITE FAILED ##########\e[0m" exit 1 end puts "\e[32m########## MONETA TESTSUITE SUCCEDED ##########\e[0m"