parallel_tests 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Readme.md +7 -3
  3. data/bin/parallel_cucumber +5 -1
  4. data/bin/parallel_rspec +5 -1
  5. data/bin/parallel_spinach +5 -1
  6. data/bin/parallel_test +5 -2
  7. data/lib/parallel_tests.rb +0 -1
  8. metadata +3 -51
  9. data/.gitignore +0 -4
  10. data/.rspec +0 -2
  11. data/.travis.yml +0 -10
  12. data/Gemfile +0 -9
  13. data/Gemfile.lock +0 -53
  14. data/Rakefile +0 -10
  15. data/ReadmeRails2.md +0 -48
  16. data/lib/parallel_tests/cli.rb +0 -206
  17. data/lib/parallel_tests/cucumber/failures_logger.rb +0 -25
  18. data/lib/parallel_tests/cucumber/runner.rb +0 -37
  19. data/lib/parallel_tests/cucumber/scenario_line_logger.rb +0 -51
  20. data/lib/parallel_tests/cucumber/scenarios.rb +0 -34
  21. data/lib/parallel_tests/gherkin/io.rb +0 -41
  22. data/lib/parallel_tests/gherkin/listener.rb +0 -87
  23. data/lib/parallel_tests/gherkin/runner.rb +0 -116
  24. data/lib/parallel_tests/gherkin/runtime_logger.rb +0 -28
  25. data/lib/parallel_tests/grouper.rb +0 -73
  26. data/lib/parallel_tests/railtie.rb +0 -8
  27. data/lib/parallel_tests/rspec/failures_logger.rb +0 -54
  28. data/lib/parallel_tests/rspec/logger_base.rb +0 -55
  29. data/lib/parallel_tests/rspec/runner.rb +0 -73
  30. data/lib/parallel_tests/rspec/runtime_logger.rb +0 -59
  31. data/lib/parallel_tests/rspec/summary_logger.rb +0 -19
  32. data/lib/parallel_tests/spinach/runner.rb +0 -19
  33. data/lib/parallel_tests/tasks.rb +0 -157
  34. data/lib/parallel_tests/test/runner.rb +0 -186
  35. data/lib/parallel_tests/test/runtime_logger.rb +0 -98
  36. data/lib/parallel_tests/version.rb +0 -3
  37. data/parallel_tests.gemspec +0 -14
  38. data/spec/integration_spec.rb +0 -437
  39. data/spec/parallel_tests/cli_spec.rb +0 -149
  40. data/spec/parallel_tests/cucumber/failure_logger_spec.rb +0 -43
  41. data/spec/parallel_tests/cucumber/runner_spec.rb +0 -25
  42. data/spec/parallel_tests/cucumber/scenarios_spec.rb +0 -69
  43. data/spec/parallel_tests/gherkin/listener_spec.rb +0 -96
  44. data/spec/parallel_tests/gherkin/runner_behaviour.rb +0 -216
  45. data/spec/parallel_tests/grouper_spec.rb +0 -61
  46. data/spec/parallel_tests/rspec/failures_logger_spec.rb +0 -82
  47. data/spec/parallel_tests/rspec/logger_base_spec.rb +0 -35
  48. data/spec/parallel_tests/rspec/runner_spec.rb +0 -201
  49. data/spec/parallel_tests/rspec/runtime_logger_spec.rb +0 -131
  50. data/spec/parallel_tests/rspec/summary_logger_spec.rb +0 -37
  51. data/spec/parallel_tests/spinach/runner_spec.rb +0 -12
  52. data/spec/parallel_tests/tasks_spec.rb +0 -178
  53. data/spec/parallel_tests/test/runner_spec.rb +0 -407
  54. data/spec/parallel_tests/test/runtime_logger_spec.rb +0 -112
  55. data/spec/parallel_tests_spec.rb +0 -137
  56. data/spec/spec_helper.rb +0 -182
@@ -1,8 +0,0 @@
1
- # rake tasks for Rails 3+
2
- module ParallelTests
3
- class Railtie < ::Rails::Railtie
4
- rake_tasks do
5
- require "parallel_tests/tasks"
6
- end
7
- end
8
- end
@@ -1,54 +0,0 @@
1
- require 'parallel_tests/rspec/logger_base'
2
- require 'parallel_tests/rspec/runner'
3
-
4
- class ParallelTests::RSpec::FailuresLogger < ParallelTests::RSpec::LoggerBase
5
- if RSPEC_3
6
- RSpec::Core::Formatters.register self, :dump_failures, :dump_summary
7
- end
8
-
9
- # RSpec 1: does not keep track of failures, so we do
10
- def example_failed(example, *args)
11
- if RSPEC_1
12
- @failed_examples ||= []
13
- @failed_examples << example
14
- else
15
- super
16
- end
17
- end
18
-
19
- if RSPEC_1
20
- def dump_failure(*args)
21
- end
22
- else
23
- def dump_failures(*args)
24
- end
25
- end
26
-
27
- def dump_summary(*args)
28
- lock_output do
29
- if RSPEC_1
30
- dump_commands_to_rerun_failed_examples_rspec_1
31
- elsif RSPEC_3
32
- notification = args.first
33
- unless notification.failed_examples.empty?
34
- colorizer = ::RSpec::Core::Formatters::ConsoleCodes
35
- output.puts notification.colorized_rerun_commands(colorizer)
36
- end
37
- else
38
- dump_commands_to_rerun_failed_examples
39
- end
40
- end
41
- @output.flush
42
- end
43
-
44
- private
45
-
46
- def dump_commands_to_rerun_failed_examples_rspec_1
47
- (@failed_examples||[]).each do |example|
48
- file, line = example.location.to_s.split(':')
49
- next unless file and line
50
- file.gsub!(%r(^.*?/spec/), './spec/')
51
- @output.puts "#{ParallelTests::RSpec::Runner.send(:executable)} #{file}:#{line} # #{example.description}"
52
- end
53
- end
54
- end
@@ -1,55 +0,0 @@
1
- module ParallelTests
2
- module RSpec
3
- end
4
- end
5
-
6
- begin
7
- require 'rspec/core/formatters/base_text_formatter'
8
- base = RSpec::Core::Formatters::BaseTextFormatter
9
- rescue LoadError
10
- require 'spec/runner/formatter/base_text_formatter'
11
- base = Spec::Runner::Formatter::BaseTextFormatter
12
- end
13
-
14
- ParallelTests::RSpec::LoggerBaseBase = base
15
-
16
- class ParallelTests::RSpec::LoggerBase < ParallelTests::RSpec::LoggerBaseBase
17
- RSPEC_1 = !defined?(RSpec::Core::Formatters::BaseTextFormatter) # do not test for Spec, this will trigger deprecation warning in rspec 2
18
- RSPEC_3 = !RSPEC_1 && RSpec::Core::Version::STRING.start_with?('3')
19
-
20
- def initialize(*args)
21
- super
22
-
23
- @output ||= args[1] || args[0] # rspec 1 has output as second argument
24
-
25
- if String === @output # a path ?
26
- FileUtils.mkdir_p(File.dirname(@output))
27
- File.open(@output, 'w'){} # overwrite previous results
28
- @output = File.open(@output, 'a')
29
- elsif File === @output # close and restart in append mode
30
- @output.close
31
- @output = File.open(@output.path, 'a')
32
- end
33
- end
34
-
35
- #stolen from Rspec
36
- def close(*args)
37
- @output.close if (IO === @output) & (@output != $stdout)
38
- end
39
-
40
- protected
41
-
42
- # do not let multiple processes get in each others way
43
- def lock_output
44
- if File === @output
45
- begin
46
- @output.flock File::LOCK_EX
47
- yield
48
- ensure
49
- @output.flock File::LOCK_UN
50
- end
51
- else
52
- yield
53
- end
54
- end
55
- end
@@ -1,73 +0,0 @@
1
- require "parallel_tests/test/runner"
2
-
3
- module ParallelTests
4
- module RSpec
5
- class Runner < ParallelTests::Test::Runner
6
- DEV_NULL = (WINDOWS ? "NUL" : "/dev/null")
7
- NAME = 'RSpec'
8
-
9
- class << self
10
- def run_tests(test_files, process_number, num_processes, options)
11
- exe = executable # expensive, so we cache
12
- version = (exe =~ /\brspec\b/ ? 2 : 1)
13
- cmd = [exe, options[:test_options], (rspec_2_color if version == 2), spec_opts, *test_files].compact.join(" ")
14
- options = options.merge(:env => rspec_1_color) if version == 1
15
- execute_command(cmd, process_number, num_processes, options)
16
- end
17
-
18
- def determine_executable
19
- cmd = case
20
- when File.exists?("bin/rspec")
21
- WINDOWS ? "ruby bin/rspec" : "bin/rspec"
22
- when File.file?("script/spec")
23
- "script/spec"
24
- when ParallelTests.bundler_enabled?
25
- cmd = (run("bundle show rspec-core") =~ %r{Could not find gem.*} ? "spec" : "rspec")
26
- "bundle exec #{cmd}"
27
- else
28
- %w[spec rspec].detect{|cmd| system "#{cmd} --version > #{DEV_NULL} 2>&1" }
29
- end
30
-
31
- cmd or raise("Can't find executables rspec or spec")
32
- end
33
-
34
- def runtime_log
35
- 'tmp/parallel_runtime_rspec.log'
36
- end
37
-
38
- def test_file_name
39
- "spec"
40
- end
41
-
42
- def test_suffix
43
- /_spec\.rb$/
44
- end
45
-
46
- private
47
-
48
- # so it can be stubbed....
49
- def run(cmd)
50
- `#{cmd}`
51
- end
52
-
53
- def rspec_1_color
54
- if $stdout.tty?
55
- {'RSPEC_COLOR' => "1"}
56
- else
57
- {}
58
- end
59
- end
60
-
61
- def rspec_2_color
62
- '--color --tty' if $stdout.tty?
63
- end
64
-
65
- def spec_opts
66
- options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect{|f| File.file?(f) }
67
- return unless options_file
68
- "-O #{options_file}"
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,59 +0,0 @@
1
- require 'parallel_tests'
2
- require 'parallel_tests/rspec/logger_base'
3
-
4
- class ParallelTests::RSpec::RuntimeLogger < ParallelTests::RSpec::LoggerBase
5
- def initialize(*args)
6
- super
7
- @example_times = Hash.new(0)
8
- @group_nesting = 0 unless RSPEC_1
9
- end
10
-
11
- if RSPEC_3
12
- RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump
13
- end
14
-
15
- if RSPEC_1
16
- def example_started(*args)
17
- @time = ParallelTests.now
18
- super
19
- end
20
-
21
- def example_passed(example)
22
- file = example.location.split(':').first
23
- @example_times[file] += ParallelTests.now - @time
24
- super
25
- end
26
- else
27
- def example_group_started(example_group)
28
- @time = ParallelTests.now if @group_nesting == 0
29
- @group_nesting += 1
30
- super
31
- end
32
-
33
- def example_group_finished(notification)
34
- @group_nesting -= 1
35
- if @group_nesting == 0
36
- path = (RSPEC_3 ? notification.group.file_path : notification.file_path)
37
- @example_times[path] += ParallelTests.now - @time
38
- end
39
- super if defined?(super)
40
- end
41
- end
42
-
43
- def dump_summary(*args);end
44
- def dump_failures(*args);end
45
- def dump_failure(*args);end
46
- def dump_pending(*args);end
47
-
48
- def start_dump(*args)
49
- return unless ENV['TEST_ENV_NUMBER'] #only record when running in parallel
50
- # TODO: Figure out why sometimes time can be less than 0
51
- lock_output do
52
- @example_times.each do |file, time|
53
- relative_path = file.sub(/^#{Regexp.escape Dir.pwd}\//,'')
54
- @output.puts "#{relative_path}:#{time > 0 ? time : 0}"
55
- end
56
- end
57
- @output.flush
58
- end
59
- end
@@ -1,19 +0,0 @@
1
- require 'parallel_tests/rspec/failures_logger'
2
-
3
- class ParallelTests::RSpec::SummaryLogger < ParallelTests::RSpec::LoggerBase
4
- if RSPEC_3
5
- RSpec::Core::Formatters.register self, :dump_failures
6
- end
7
-
8
- if RSPEC_1
9
- def dump_failure(*args)
10
- lock_output { super }
11
- @output.flush
12
- end
13
- else
14
- def dump_failures(*args)
15
- lock_output { super }
16
- @output.flush
17
- end
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- require "parallel_tests/gherkin/runner"
2
-
3
- module ParallelTests
4
- module Spinach
5
- class Runner < ParallelTests::Gherkin::Runner
6
- class << self
7
- def name
8
- 'spinach'
9
- end
10
-
11
- def runtime_logging
12
- #Not Yet Supported
13
- ""
14
- end
15
-
16
- end
17
- end
18
- end
19
- end
@@ -1,157 +0,0 @@
1
- require 'rake'
2
-
3
- module ParallelTests
4
- module Tasks
5
- class << self
6
- def rails_env
7
- ENV['RAILS_ENV'] || 'test'
8
- end
9
-
10
- def run_in_parallel(cmd, options={})
11
- count = " -n #{options[:count]}" unless options[:count].to_s.empty?
12
- executable = File.expand_path("../../../bin/parallel_test", __FILE__)
13
- command = "#{executable} --exec '#{cmd}'#{count}#{' --non-parallel' if options[:non_parallel]}"
14
- abort unless system(command)
15
- end
16
-
17
- # this is a crazy-complex solution for a very simple problem:
18
- # removing certain lines from the output without chaning the exit-status
19
- # normally I'd not do this, but it has been lots of fun and a great learning experience :)
20
- #
21
- # - sed does not support | without -r
22
- # - grep changes 0 exitstatus to 1 if nothing matches
23
- # - sed changes 1 exitstatus to 0
24
- # - pipefail makes pipe fail with exitstatus of first failed command
25
- # - pipefail is not supported in (zsh)
26
- # - defining a new rake task like silence_schema would force users to load parallel_tests in test env
27
- # - do not use ' since run_in_parallel uses them to quote stuff
28
- # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0
29
- def suppress_output(command, ignore_regex)
30
- activate_pipefail = "set -o pipefail"
31
- remove_ignored_lines = %Q{(grep -v "#{ignore_regex}" || test 1)}
32
-
33
- if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1")
34
- # We need to shell escape single quotes (' becomes '"'"') because
35
- # run_in_parallel wraps command in single quotes
36
- %Q{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'}
37
- else
38
- command
39
- end
40
- end
41
-
42
- def check_for_pending_migrations
43
- ["db:abort_if_pending_migrations", "app:db:abort_if_pending_migrations"].each do |abort_migrations|
44
- if Rake::Task.task_defined?(abort_migrations)
45
- Rake::Task[abort_migrations].invoke
46
- break
47
- end
48
- end
49
- end
50
-
51
- # parallel:spec[:count, :pattern, :options]
52
- def parse_args(args)
53
- # order as given by user
54
- args = [args[:count], args[:pattern], args[:options]]
55
-
56
- # count given or empty ?
57
- # parallel:spec[2,models,options]
58
- # parallel:spec[,models,options]
59
- count = args.shift if args.first.to_s =~ /^\d*$/
60
- num_processes = count.to_i unless count.to_s.empty?
61
- pattern = args.shift
62
- options = args.shift
63
-
64
- [num_processes, pattern.to_s, options.to_s]
65
- end
66
- end
67
- end
68
- end
69
-
70
- namespace :parallel do
71
- desc "create test databases via db:create --> parallel:create[num_cpus]"
72
- task :create, :count do |t,args|
73
- ParallelTests::Tasks.run_in_parallel("rake db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
74
- end
75
-
76
- desc "drop test databases via db:drop --> parallel:drop[num_cpus]"
77
- task :drop, :count do |t,args|
78
- ParallelTests::Tasks.run_in_parallel("rake db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
79
- end
80
-
81
- desc "update test databases by dumping and loading --> parallel:prepare[num_cpus]"
82
- task(:prepare, [:count]) do |t,args|
83
- ParallelTests::Tasks.check_for_pending_migrations
84
- if defined?(ActiveRecord) && ActiveRecord::Base.schema_format == :ruby
85
- # dump then load in parallel
86
- Rake::Task['db:schema:dump'].invoke
87
- Rake::Task['parallel:load_schema'].invoke(args[:count])
88
- else
89
- # there is no separate dump / load for schema_format :sql -> do it safe and slow
90
- args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil
91
- taskname = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare'
92
- ParallelTests::Tasks.run_in_parallel("rake #{taskname}", args)
93
- end
94
- end
95
-
96
- # when dumping/resetting takes too long
97
- desc "update test databases via db:migrate --> parallel:migrate[num_cpus]"
98
- task :migrate, :count do |t,args|
99
- ParallelTests::Tasks.run_in_parallel("rake db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
100
- end
101
-
102
- # just load the schema (good for integration server <-> no development db)
103
- desc "load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
104
- task :load_schema, :count do |t,args|
105
- command = "rake db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env}"
106
- ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_output(command, "^ ->\\|^-- "), args)
107
- end
108
-
109
- # load the structure from the structure.sql file
110
- desc "load structure for test databases via db:structure:load --> parallel:load_structure[num_cpus]"
111
- task :load_structure, :count do |t,args|
112
- ParallelTests::Tasks.run_in_parallel("rake db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
113
- end
114
-
115
- desc "load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]"
116
- task :seed, :count do |t,args|
117
- ParallelTests::Tasks.run_in_parallel("rake db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
118
- end
119
-
120
- desc "launch given rake command in parallel"
121
- task :rake, :command do |t, args|
122
- ParallelTests::Tasks.run_in_parallel("RAILS_ENV=#{ParallelTests::Tasks.rails_env} rake #{args.command}")
123
- end
124
-
125
- ['test', 'spec', 'features', 'features-spinach'].each do |type|
126
- desc "run #{type} in parallel with parallel:#{type}[num_cpus]"
127
- task type, [:count, :pattern, :options] do |t, args|
128
- ParallelTests::Tasks.check_for_pending_migrations
129
-
130
- $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
131
- require "parallel_tests"
132
-
133
- count, pattern, options = ParallelTests::Tasks.parse_args(args)
134
- test_framework = {
135
- 'spec' => 'rspec',
136
- 'test' => 'test',
137
- 'features' => 'cucumber',
138
- 'features-spinach' => 'spinach',
139
- }[type]
140
-
141
- if test_framework == 'spinach'
142
- type = 'features'
143
- end
144
- executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test')
145
-
146
- command = "#{executable} #{type} --type #{test_framework} " \
147
- "-n #{count} " \
148
- "--pattern '#{pattern}' " \
149
- "--test-options '#{options}'"
150
- if ParallelTests::WINDOWS
151
- ruby_binary = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
152
- command = "#{ruby_binary} #{command}"
153
- end
154
- abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features
155
- end
156
- end
157
- end