require'rake'moduleParallelTestsmoduleTasksclass<<selfdefrails_envENV['RAILS_ENV']||'test'enddefrun_in_parallel(cmd,options={})count=" -n #{options[:count]}"ifoptions[:count]executable=File.expand_path("../../../bin/parallel_test",__FILE__)command="#{executable} --exec '#{cmd}'#{count}#{' --non-parallel'ifoptions[:non_parallel]}"abortunlesssystem(command)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 0defsuppress_output(command,ignore_regex)activate_pipefail="set -o pipefail"remove_ignored_lines=%Q{(grep -v "#{ignore_regex}" || test 1)}ifsystem("#{activate_pipefail} 2>/dev/null && test 1")"#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}"elsecommandendenddefcheck_for_pending_migrationsabort_migrations="db:abort_if_pending_migrations"ifRake::Task.task_defined?(abort_migrations)Rake::Task[abort_migrations].invokeendend# parallel:spec[:count, :pattern, :options]defparse_args(args)# order as given by userargs=[args[:count],args[:pattern],args[:options]]# count given or empty ?# parallel:spec[2,models,options]# parallel:spec[,models,options]count=args.shiftifargs.first.to_s=~/^\d*$/num_processes=count.to_iunlesscount.to_s.empty?pattern=args.shiftoptions=args.shift[num_processes,pattern.to_s,options.to_s]endendendendnamespace:paralleldodesc"create test databases via db:create --> parallel:create[num_cpus]"task:create,:countdo|t,args|ParallelTests::Tasks.run_in_parallel("rake db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}",args)enddesc"drop test databases via db:drop --> parallel:drop[num_cpus]"task:drop,:countdo|t,args|ParallelTests::Tasks.run_in_parallel("rake db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env}",args)enddesc"update test databases by dumping and loading --> parallel:prepare[num_cpus]"task(:prepare,[:count])do|t,args|ParallelTests::Tasks.check_for_pending_migrationsifdefined?(ActiveRecord)&&ActiveRecord::Base.schema_format==:ruby# dump then load in parallelRake::Task['db:schema:dump'].invokeRake::Task['parallel:load_schema'].invoke(args[:count])else# there is no separate dump / load for schema_format :sql -> do it safe and slowargs=args.to_hash.merge(:non_parallel=>true)# normal merge returns nilParallelTests::Tasks.run_in_parallel('rake db:test:prepare --trace',args)endend# when dumping/resetting takes too longdesc"update test databases via db:migrate --> parallel:migrate[num_cpus]"task:migrate,:countdo|t,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,:countdo|t,args|command="rake db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env}"ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_output(command,"^ ->\\|^-- "),args)enddesc"load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]"task:seed,:countdo|t,args|ParallelTests::Tasks.run_in_parallel("rake db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}",args)enddesc"launch given rake command in parallel"task:rake,:commanddo|t,args|ParallelTests::Tasks.run_in_parallel("RAILS_ENV=#{ParallelTests::Tasks.rails_env} rake #{args.command}")end['test','spec','features'].eachdo|type|desc"run #{type} in parallel with parallel:#{type}[num_cpus]"tasktype,[: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::Tasks.parse_args(args)test_framework={'spec'=>'rspec','test'=>'test','features'=>'cucumber'}[type]executable=File.join(File.dirname(__FILE__),'..','..','bin','parallel_test')command="#{executable}#{type} --type #{test_framework} "\"-n #{count} "\"--pattern '#{pattern}' "\"--test-options '#{options}'"abortunlesssystem(command)# allow to chain tasks e.g. rake parallel:spec parallel:featuresendendend