lib/parallel_tests/tasks.rb in parallel_tests-0.8.12 vs lib/parallel_tests/tasks.rb in parallel_tests-0.8.13

- old
+ new

@@ -1,84 +1,119 @@ -namespace :parallel do - rails_env = ENV['RAILS_ENV'] || 'test' +require 'rake' - def run_in_parallel(cmd, options) - count = "-n #{options[:count]}" if options[:count] - executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') - command = "#{executable} --exec '#{cmd}' #{count} #{'--non-parallel' if options[:non_parallel]}" - abort unless system(command) - end +module ParallelTests + module Tasks + class << self + def rails_env + ENV['RAILS_ENV'] || 'test' + end - # this is a crazy-complex solution for a very simple problem: - # removing certain lines from the output without chaning the exit-status - # normally I'd not do this, but it has been lots of fun and a great learning experience :) - # - # - sed does not support | without -r - # - grep changes 0 exitstatus to 1 if nothing matches - # - sed changes 1 exitstatus to 0 - # - pipefail makes pipe fail with exitstatus of first failed command - # - pipefail is not supported in (zsh) - # - defining a new rake task like silence_schema would force users to load parallel_tests in test env - # - do not use ' since run_in_parallel uses them to quote stuff - # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0 - def parallel_tests_suppress_output(command, ignore_regex) - activate_pipefail = "set -o pipefail" - remove_ignored_lines = %Q{(grep -v "#{ignore_regex}" || test 1)} + def run_in_parallel(cmd, options={}) + count = " -n #{options[:count]}" if options[:count] + executable = File.expand_path("../../../bin/parallel_test", __FILE__) + command = "#{executable} --exec '#{cmd}'#{count}#{' --non-parallel' if options[:non_parallel]}" + abort unless system(command) + end - if system("#{activate_pipefail} && test 1") - "#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}" - else - command + # this is a crazy-complex solution for a very simple problem: + # removing certain lines from the output without chaning the exit-status + # normally I'd not do this, but it has been lots of fun and a great learning experience :) + # + # - sed does not support | without -r + # - grep changes 0 exitstatus to 1 if nothing matches + # - sed changes 1 exitstatus to 0 + # - pipefail makes pipe fail with exitstatus of first failed command + # - pipefail is not supported in (zsh) + # - defining a new rake task like silence_schema would force users to load parallel_tests in test env + # - do not use ' since run_in_parallel uses them to quote stuff + # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0 + def suppress_output(command, ignore_regex) + activate_pipefail = "set -o pipefail" + remove_ignored_lines = %Q{(grep -v "#{ignore_regex}" || test 1)} + + if system("#{activate_pipefail} && test 1") + "#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}" + else + command + end + end + + def check_for_pending_migrations + abort_migrations = "db:abort_if_pending_migrations" + if Rake::Task.task_defined?(abort_migrations) + Rake::Task[abort_migrations].invoke + end + end + + # parallel:spec[:count, :pattern, :options] + def parse_args(args) + # order as given by user + args = [args[:count], args[:pattern], args[:options]] + + # count given or empty ? + # parallel:spec[2,models,options] + # parallel:spec[,models,options] + count = args.shift if args.first.to_s =~ /^\d*$/ + num_processes = count.to_i unless count.to_s.empty? + pattern = args.shift + options = args.shift + + [num_processes, pattern.to_s, options.to_s] + end end end +end +namespace :parallel do desc "create test databases via db:create --> parallel:create[num_cpus]" task :create, :count do |t,args| - run_in_parallel("rake db:create RAILS_ENV=#{rails_env}", args) + ParallelTests::Tasks.run_in_parallel("rake db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end desc "drop test databases via db:drop --> parallel:drop[num_cpus]" task :drop, :count do |t,args| - run_in_parallel("rake db:drop RAILS_ENV=#{rails_env}", args) + ParallelTests::Tasks.run_in_parallel("rake db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end desc "update test databases by dumping and loading --> parallel:prepare[num_cpus]" - task(:prepare, [:count] => 'db:abort_if_pending_migrations') do |t,args| + task(:prepare, [:count]) do |t,args| + ParallelTests::Tasks.check_for_pending_migrations if defined?(ActiveRecord) && ActiveRecord::Base.schema_format == :ruby # dump then load in parallel Rake::Task['db:schema:dump'].invoke Rake::Task['parallel:load_schema'].invoke(args[:count]) else # there is no separate dump / load for schema_format :sql -> do it safe and slow args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil - run_in_parallel('rake db:test:prepare --trace', args) + ParallelTests::Tasks.run_in_parallel('rake db:test:prepare --trace', args) end end # when dumping/resetting takes too long desc "update test databases via db:migrate --> parallel:migrate[num_cpus]" task :migrate, :count do |t,args| - run_in_parallel("rake db:migrate RAILS_ENV=#{rails_env}", args) + ParallelTests::Tasks.run_in_parallel("rake db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end # just load the schema (good for integration server <-> no development db) desc "load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" task :load_schema, :count do |t,args| - command = "rake db:schema:load RAILS_ENV=#{rails_env}" - run_in_parallel(parallel_tests_suppress_output(command, "^ ->\\|^-- "), args) + command = "rake db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env}" + ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_output(command, "^ ->\\|^-- "), args) end desc "load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]" task :seed, :count do |t,args| - run_in_parallel("rake db:seed RAILS_ENV=#{rails_env}", args) + run_in_parallel("rake db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end ['test', 'spec', 'features'].each do |type| desc "run #{type} in parallel with parallel:#{type}[num_cpus]" - task type, [:count, :pattern, :options] => 'db:abort_if_pending_migrations' do |t,args| + task type, [:count, :pattern, :options] do |t,args| + ParallelTests::Tasks.check_for_pending_migrations $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..')) require "parallel_tests" - count, pattern, options = ParallelTests.parse_rake_args(args) + count, pattern, options = ParallelTests::Tasks.parse_args(args) test_framework = { 'spec' => 'rspec', 'test' => 'test', 'features' => 'cucumber' }[type]