parallel_tests 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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