specjour 0.2.5 → 0.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/History.markdown +51 -20
  2. data/README.markdown +53 -26
  3. data/Rakefile +3 -5
  4. data/VERSION +1 -1
  5. data/bin/specjour +1 -48
  6. data/lib/specjour/cli.rb +97 -0
  7. data/lib/specjour/configuration.rb +73 -0
  8. data/lib/specjour/connection.rb +1 -1
  9. data/lib/specjour/cucumber/distributed_formatter.rb +2 -5
  10. data/lib/specjour/cucumber/preloader.rb +13 -0
  11. data/lib/specjour/cucumber.rb +3 -2
  12. data/lib/specjour/db_scrub.rb +8 -1
  13. data/lib/specjour/dispatcher.rb +99 -36
  14. data/lib/specjour/manager.rb +63 -37
  15. data/lib/specjour/printer.rb +33 -11
  16. data/lib/specjour/quiet_fork.rb +11 -0
  17. data/lib/specjour/rspec/distributed_formatter.rb +4 -15
  18. data/lib/specjour/rspec/preloader.rb +8 -0
  19. data/lib/specjour/rspec.rb +1 -0
  20. data/lib/specjour/rsync_daemon.rb +1 -1
  21. data/lib/specjour/socket_helper.rb +28 -0
  22. data/lib/specjour/worker.rb +42 -25
  23. data/lib/specjour.rb +13 -5
  24. data/spec/spec_helper.rb +12 -0
  25. data/spec/specjour/cli_spec.rb +104 -0
  26. data/spec/specjour/configuration_spec.rb +112 -0
  27. data/spec/{cpu_spec.rb → specjour/cpu_spec.rb} +0 -0
  28. data/spec/{manager_spec.rb → specjour/manager_spec.rb} +2 -2
  29. data/spec/specjour/printer_spec.rb +101 -0
  30. data/spec/{rsync_daemon_spec.rb → specjour/rsync_daemon_spec.rb} +2 -0
  31. data/spec/specjour_spec.rb +13 -2
  32. data/specjour.gemspec +33 -26
  33. metadata +69 -31
  34. data/lib/specjour/cucumber/dispatcher.rb +0 -18
  35. data/lib/specjour/cucumber/printer.rb +0 -9
  36. data/lib/specjour/socket_helpers.rb +0 -11
  37. data/lib/specjour/tasks/dispatch.rake +0 -21
  38. data/lib/specjour/tasks/specjour.rb +0 -1
  39. data/rails/init.rb +0 -6
  40. data/spec/lib/specjour/worker_spec.rb +0 -14
@@ -2,39 +2,65 @@ module Specjour
2
2
  class Dispatcher
3
3
  require 'dnssd'
4
4
  Thread.abort_on_exception = true
5
- include SocketHelpers
5
+ include SocketHelper
6
6
 
7
7
  class << self
8
8
  attr_accessor :interrupted
9
9
  alias interrupted? interrupted
10
10
  end
11
11
 
12
- attr_reader :project_path, :managers, :manager_threads, :hosts
13
- attr_accessor :worker_size
12
+ attr_reader :project_alias, :managers, :manager_threads, :hosts, :options, :all_tests
13
+ attr_accessor :worker_size, :project_path
14
14
 
15
- def initialize(project_path)
16
- @project_path = project_path
17
- @managers = []
15
+ def initialize(options = {})
16
+ @options = options
17
+ @project_path = File.expand_path options[:project_path]
18
18
  @worker_size = 0
19
- reset_manager_threads
19
+ @managers = []
20
+ find_tests
21
+ clear_manager_threads
20
22
  end
21
23
 
22
24
  def start
23
- rsync_daemon.start
25
+ abort("#{project_path} doesn't exist") unless File.exists?(project_path)
24
26
  gather_managers
27
+ rsync_daemon.start
25
28
  dispatch_work
26
- printer.join
29
+ Signal.trap('INT') { Dispatcher.interrupted = true; exit 1 }
30
+ printer.join if dispatching_tests?
31
+ wait_on_managers
27
32
  exit printer.exit_status
28
33
  end
29
34
 
30
35
  protected
31
36
 
32
- def all_specs
33
- @all_specs ||= Dir.chdir(project_path) do
34
- Dir["spec/**/**/*_spec.rb"].sort
37
+ def find_tests
38
+ if project_path.match(/(.+)\/((spec|features)(?:\/\w+)*)$/)
39
+ self.project_path = $1
40
+ @all_tests = $3 == 'spec' ? all_specs($2) : all_features($2)
41
+ else
42
+ @all_tests = Array(all_specs) | Array(all_features)
35
43
  end
36
44
  end
37
45
 
46
+ def all_specs(tests_path = 'spec')
47
+ Dir.chdir(project_path) do
48
+ Dir[File.join(tests_path, "**/*_spec.rb")].sort
49
+ end if File.exists? File.join(project_path, tests_path)
50
+ end
51
+
52
+ def all_features(tests_path = 'features')
53
+ Dir.chdir(project_path) do
54
+ Dir[File.join(tests_path, "**/*.feature")].sort
55
+ end if File.exists? File.join(project_path, tests_path)
56
+ end
57
+
58
+ def add_manager(manager)
59
+ set_up_manager(manager)
60
+ managers << manager
61
+ self.worker_size += manager.worker_size
62
+ end
63
+
38
64
  def command_managers(async = false, &block)
39
65
  managers.each do |manager|
40
66
  manager_threads << Thread.new(manager, &block)
@@ -42,53 +68,83 @@ module Specjour
42
68
  wait_on_managers unless async
43
69
  end
44
70
 
71
+ def dispatcher_uri
72
+ @dispatcher_uri ||= URI::Generic.build :scheme => "specjour", :host => hostname, :port => printer.port
73
+ end
74
+
45
75
  def dispatch_work
76
+ puts "Managers found: #{managers.size}"
77
+ puts "Workers found: #{worker_size}"
78
+ printer.worker_size = worker_size
46
79
  command_managers(true) { |m| m.dispatch }
47
80
  end
48
81
 
82
+ def dispatching_tests?
83
+ worker_task == 'run_tests'
84
+ end
85
+
49
86
  def fetch_manager(uri)
50
87
  Timeout.timeout(8) do
51
88
  manager = DRbObject.new_with_uri(uri.to_s)
52
- if !managers.include?(manager) && manager.available_for?(project_name)
53
- set_up_manager(manager, uri)
54
- managers << manager
55
- self.worker_size += manager.worker_size
89
+ if !managers.include?(manager) && manager.available_for?(project_alias)
90
+ add_manager(manager)
56
91
  end
57
92
  end
58
93
  rescue Timeout::Error
59
94
  Specjour.logger.debug "Couldn't work with manager at #{uri}"
95
+ rescue DRb::DRbConnError
96
+ retry
97
+ end
98
+
99
+ def fork_local_manager
100
+ puts "No remote managers found, starting a local manager..."
101
+ manager_options = {:worker_size => options[:worker_size], :registered_projects => [project_alias]}
102
+ manager = Manager.start_quietly manager_options
103
+ fetch_manager(manager.drb_uri)
104
+ at_exit { Process.kill('TERM', manager.pid) rescue Errno::ESRCH }
60
105
  end
61
106
 
62
107
  def gather_managers
63
- puts "Waiting for managers"
64
- Signal.trap('INT') { self.class.interrupted = true; exit }
108
+ puts "Looking for managers..."
109
+ gather_remote_managers
110
+ fork_local_manager if local_manager_needed?
111
+ abort "No managers found" if managers.size.zero?
112
+ end
113
+
114
+ def gather_remote_managers
65
115
  browser = DNSSD::Service.new
66
- begin
67
- Timeout.timeout(10) do
68
- browser.browse '_druby._tcp' do |reply|
69
- if reply.flags.add?
70
- resolve_reply(reply)
71
- end
72
- browser.stop unless reply.flags.more_coming?
116
+ Timeout.timeout(10) do
117
+ browser.browse '_druby._tcp' do |reply|
118
+ if reply.flags.add?
119
+ resolve_reply(reply)
73
120
  end
121
+ browser.stop unless reply.flags.more_coming?
74
122
  end
75
- rescue Timeout::Error
76
123
  end
77
- puts "Managers found: #{managers.size}"
78
- abort unless managers.size > 0
79
- puts "Workers found: #{worker_size}"
80
- printer.worker_size = worker_size
124
+ rescue Timeout::Error
125
+ end
126
+
127
+ def local_manager_needed?
128
+ options[:worker_size] > 0 && no_local_managers?
129
+ end
130
+
131
+ def no_local_managers?
132
+ !managers.any? {|m| m.hostname == hostname}
81
133
  end
82
134
 
83
135
  def printer
84
- @printer ||= Printer.start(all_specs)
136
+ @printer ||= Printer.start(all_tests)
137
+ end
138
+
139
+ def project_alias
140
+ @project_alias ||= options[:project_alias] || project_name
85
141
  end
86
142
 
87
143
  def project_name
88
144
  @project_name ||= File.basename(project_path)
89
145
  end
90
146
 
91
- def reset_manager_threads
147
+ def clear_manager_threads
92
148
  @manager_threads = []
93
149
  end
94
150
 
@@ -105,15 +161,22 @@ module Specjour
105
161
  @rsync_daemon ||= RsyncDaemon.new(project_path, project_name)
106
162
  end
107
163
 
108
- def set_up_manager(manager, uri)
164
+ def set_up_manager(manager)
109
165
  manager.project_name = project_name
110
- manager.dispatcher_uri = URI::Generic.build :scheme => "specjour", :host => hostname, :port => printer.port
111
- at_exit { manager.kill_worker_processes }
166
+ manager.dispatcher_uri = dispatcher_uri
167
+ manager.preload_spec = all_tests.detect {|f| f =~ /_spec\.rb$/}
168
+ manager.preload_feature = all_tests.detect {|f| f =~ /\.feature$/}
169
+ manager.worker_task = worker_task
170
+ at_exit { manager.kill_worker_processes rescue DRb::DRbConnError }
112
171
  end
113
172
 
114
173
  def wait_on_managers
115
174
  manager_threads.each {|t| t.join; t.exit}
116
- reset_manager_threads
175
+ clear_manager_threads
176
+ end
177
+
178
+ def worker_task
179
+ options[:worker_task] || 'run_tests'
117
180
  end
118
181
  end
119
182
  end
@@ -1,29 +1,33 @@
1
1
  module Specjour
2
2
  class Manager
3
3
  require 'dnssd'
4
+ require 'specjour/rspec'
5
+ require 'specjour/cucumber'
6
+
4
7
  include DRbUndumped
5
- include SocketHelpers
8
+ include SocketHelper
9
+
10
+ attr_accessor :project_name, :preload_spec, :preload_feature, :worker_task, :pid
11
+ attr_reader :worker_size, :dispatcher_uri, :registered_projects, :bonjour_service, :worker_pids, :options
6
12
 
7
- attr_accessor :project_name, :specs_to_run
8
- attr_reader :worker_size, :batch_size, :dispatcher_uri, :registered_projects, :bonjour_service, :worker_pids
13
+ def self.start_quietly(options)
14
+ manager = new options.merge(:quiet => true)
15
+ manager.drb_uri
16
+ manager.pid = QuietFork.fork { manager.start }
17
+ manager
18
+ end
9
19
 
10
20
  def initialize(options = {})
21
+ @options = options
11
22
  @worker_size = options[:worker_size]
12
- @batch_size = options[:batch_size]
23
+ @worker_task = options[:worker_task]
13
24
  @registered_projects = options[:registered_projects]
14
25
  @worker_pids = []
26
+ at_exit { kill_worker_processes }
15
27
  end
16
28
 
17
29
  def available_for?(project_name)
18
- registered_projects ? registered_projects.include?(project_name) : true
19
- end
20
-
21
- def bundle_install
22
- Dir.chdir(project_path) do
23
- unless system('bundle check > /dev/null')
24
- system("bundle install --relock > /dev/null")
25
- end
26
- end
30
+ registered_projects ? registered_projects.include?(project_name) : false
27
31
  end
28
32
 
29
33
  def dispatcher_uri=(uri)
@@ -31,50 +35,67 @@ module Specjour
31
35
  @dispatcher_uri = uri
32
36
  end
33
37
 
34
- def kill_worker_processes
35
- Process.kill('TERM', *worker_pids) rescue nil
36
- end
37
-
38
- def project_path
39
- File.join("/tmp", project_name)
40
- end
41
-
42
38
  def dispatch
43
39
  suspend_bonjour do
44
40
  sync
45
- bundle_install
41
+ in_project { Configuration.before_fork.call }
46
42
  dispatch_workers
47
43
  end
48
44
  end
49
45
 
46
+ def drb_start
47
+ DRb.start_service drb_uri.to_s, self
48
+ at_exit { DRb.stop_service }
49
+ end
50
+
51
+ def drb_uri
52
+ @drb_uri ||= begin
53
+ current_uri.scheme = "druby"
54
+ current_uri
55
+ end
56
+ end
57
+
50
58
  def dispatch_workers
51
- GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)
59
+ worker_pids.clear
52
60
  (1..worker_size).each do |index|
53
61
  worker_pids << fork do
54
- exec("specjour --batch-size #{batch_size} #{'--log' if Specjour.log?} --do-work #{project_path},#{dispatcher_uri},#{index}")
55
- Kernel.exit!
62
+ exec "specjour work #{worker_options(index)}"
56
63
  end
57
64
  end
58
- at_exit { kill_worker_processes }
59
65
  Process.waitall
60
66
  end
61
67
 
68
+ def in_project(&block)
69
+ Dir.chdir(project_path, &block)
70
+ end
71
+
72
+ def kill_worker_processes
73
+ Process.kill('TERM', *worker_pids) rescue Errno::ESRCH
74
+ end
75
+
76
+ def pid
77
+ @pid || Process.pid
78
+ end
79
+
80
+ def project_path
81
+ File.join("/tmp", project_name)
82
+ end
83
+
62
84
  def start
63
85
  drb_start
64
- puts "Workers ready: #{worker_size}"
86
+ puts "Workers ready: #{worker_size}."
87
+ puts "Listening for #{registered_projects.join(', ')}"
65
88
  bonjour_announce
66
- Signal.trap('INT') { puts; puts "Shutting down manager..."; exit }
89
+ Signal.trap('INT') { puts; puts "Shutting down manager..."; exit 1 }
67
90
  DRb.thread.join
68
91
  end
69
92
 
70
- def drb_start
71
- DRb.start_service nil, self
72
- puts "Manager started at #{drb_uri}"
73
- at_exit { DRb.stop_service }
93
+ def quiet?
94
+ options.has_key? :quiet
74
95
  end
75
96
 
76
97
  def sync
77
- cmd "rsync -a --delete --port=8989 #{dispatcher_uri.host}::#{project_name} #{project_path}"
98
+ cmd "rsync -aL --delete --port=8989 #{dispatcher_uri.host}::#{project_name} #{project_path}"
78
99
  end
79
100
 
80
101
  protected
@@ -88,14 +109,19 @@ module Specjour
88
109
  system command
89
110
  end
90
111
 
91
- def drb_uri
92
- @drb_uri ||= URI.parse(DRb.uri)
93
- end
94
-
95
112
  def suspend_bonjour(&block)
96
113
  bonjour_service.stop
97
114
  block.call
98
115
  bonjour_announce
99
116
  end
117
+
118
+ def worker_options(index)
119
+ exec_options = "--project-path #{project_path} --printer-uri #{dispatcher_uri} --number #{index} --task #{worker_task}"
120
+ exec_options << " --preload-spec #{preload_spec}" if preload_spec
121
+ exec_options << " --preload-feature #{preload_feature}" if preload_feature
122
+ exec_options << " --log" if Specjour.log?
123
+ exec_options << " --quiet" if quiet?
124
+ exec_options
125
+ end
100
126
  end
101
127
  end
@@ -1,5 +1,6 @@
1
1
  module Specjour
2
2
  require 'specjour/rspec'
3
+ require 'specjour/cucumber'
3
4
 
4
5
  class Printer < GServer
5
6
  include Protocol
@@ -44,11 +45,15 @@ module Specjour
44
45
  end
45
46
 
46
47
  def exit_status
47
- report.exit_status
48
+ reporters.all? {|r| r.exit_status == true}
48
49
  end
49
50
 
50
- def worker_summary=(client, summary)
51
- report.add(summary)
51
+ def rspec_summary=(client, summary)
52
+ rspec_report.add(summary)
53
+ end
54
+
55
+ def cucumber_summary=(client, summary)
56
+ cucumber_report.add(summary)
52
57
  end
53
58
 
54
59
  protected
@@ -66,7 +71,7 @@ module Specjour
66
71
  end
67
72
 
68
73
  def error(exception)
69
- Specjour.logger.debug exception.inspect
74
+ Specjour.logger.debug "#{exception.inspect}\n#{exception.backtrace.join("\n")}"
70
75
  end
71
76
 
72
77
  def process(message, client)
@@ -78,22 +83,39 @@ module Specjour
78
83
  end
79
84
  end
80
85
 
81
- def report
82
- @report ||= Rspec::FinalReport.new
86
+ def rspec_report
87
+ @rspec_report ||= Rspec::FinalReport.new
88
+ end
89
+
90
+ def cucumber_report
91
+ @cucumber_report ||= Cucumber::FinalReport.new
92
+ end
93
+
94
+ def reporters
95
+ [@rspec_report, @cucumber_report].compact
83
96
  end
84
97
 
85
98
  def stopping
86
- report.summarize
87
- if disconnections != completed_workers && !Specjour::Dispatcher.interrupted?
88
- puts abandoned_worker_message
89
- end
99
+ summarize_reports
100
+ warn_if_workers_deserted
101
+ end
102
+
103
+ def summarize_reports
104
+ reporters.each {|r| r.summarize}
90
105
  end
91
106
 
92
107
  def synchronize(&block)
93
108
  @connectionsMutex.synchronize &block
94
109
  end
95
110
 
96
- def abandoned_worker_message
111
+ def warn_if_workers_deserted
112
+ if disconnections != completed_workers && !Dispatcher.interrupted?
113
+ puts
114
+ puts workers_deserted_message
115
+ end
116
+ end
117
+
118
+ def workers_deserted_message
97
119
  data = "* ERROR: NOT ALL WORKERS COMPLETED PROPERLY *"
98
120
  filler = "*" * data.size
99
121
  [filler, data, filler].join "\n"
@@ -0,0 +1,11 @@
1
+ module Specjour::QuietFork
2
+ extend self
3
+ attr_reader :pid
4
+
5
+ def self.fork(&block)
6
+ @pid = Kernel.fork do
7
+ $stdout = StringIO.new
8
+ block.call
9
+ end
10
+ end
11
+ end
@@ -2,11 +2,6 @@ module Specjour::Rspec
2
2
  class DistributedFormatter < Spec::Runner::Formatter::BaseTextFormatter
3
3
  require 'specjour/rspec/marshalable_rspec_failure'
4
4
 
5
- class << self
6
- attr_accessor :batch_size
7
- end
8
- @batch_size = 1
9
-
10
5
  attr_reader :failing_messages, :passing_messages, :pending_messages, :output
11
6
  attr_reader :duration, :example_count, :failure_count, :pending_count, :pending_examples, :failing_examples
12
7
 
@@ -22,18 +17,18 @@ module Specjour::Rspec
22
17
 
23
18
  def example_failed(example, counter, failure)
24
19
  failing_messages << colorize_failure('F', failure)
25
- batch_print(failing_messages)
20
+ print_and_flush(failing_messages)
26
21
  end
27
22
 
28
23
  def example_passed(example)
29
24
  passing_messages << green('.')
30
- batch_print(passing_messages)
25
+ print_and_flush(passing_messages)
31
26
  end
32
27
 
33
28
  def example_pending(example, message, deprecated_pending_location=nil)
34
29
  super
35
30
  pending_messages << yellow('*')
36
- batch_print(pending_messages)
31
+ print_and_flush(pending_messages)
37
32
  end
38
33
 
39
34
  def dump_summary(duration, example_count, failure_count, pending_count)
@@ -41,7 +36,7 @@ module Specjour::Rspec
41
36
  @example_count = example_count
42
37
  @failure_count = failure_count
43
38
  @pending_count = pending_count
44
- output.send_message(:worker_summary=, to_hash)
39
+ output.send_message(:rspec_summary=, to_hash)
45
40
  end
46
41
 
47
42
  def dump_pending
@@ -68,12 +63,6 @@ module Specjour::Rspec
68
63
 
69
64
  protected
70
65
 
71
- def batch_print(messages)
72
- if messages.size == self.class.batch_size
73
- print_and_flush(messages)
74
- end
75
- end
76
-
77
66
  def print_and_flush(messages)
78
67
  output.print messages.to_s
79
68
  output.flush
@@ -0,0 +1,8 @@
1
+ class Specjour::Rspec::Preloader
2
+ def self.load(spec_file)
3
+ $LOAD_PATH.unshift File.join(Dir.pwd, 'spec')
4
+ require spec_file
5
+ ensure
6
+ $LOAD_PATH.shift
7
+ end
8
+ end
@@ -5,5 +5,6 @@ module Specjour
5
5
 
6
6
  require 'specjour/rspec/distributed_formatter'
7
7
  require 'specjour/rspec/final_report'
8
+ require 'specjour/rspec/preloader'
8
9
  end
9
10
  end
@@ -1,7 +1,7 @@
1
1
  module Specjour
2
2
  class RsyncDaemon
3
3
  require 'fileutils'
4
- include SocketHelpers
4
+ include SocketHelper
5
5
 
6
6
  # Corresponds to the version of specjour that changed the configuration
7
7
  # file.
@@ -0,0 +1,28 @@
1
+ module Specjour
2
+ module SocketHelper
3
+ def ip_from_hostname(hostname)
4
+ Socket.getaddrinfo(hostname, nil, Socket::AF_INET, Socket::SOCK_STREAM).first.fetch(3)
5
+ end
6
+
7
+ def hostname
8
+ @hostname ||= Socket.gethostname
9
+ end
10
+
11
+ def current_uri
12
+ @current_uri ||= new_uri
13
+ end
14
+
15
+ def new_uri
16
+ URI::Generic.build :host => faux_server[2], :port => faux_server[1]
17
+ end
18
+
19
+ protected
20
+
21
+ def faux_server
22
+ server = TCPServer.new('0.0.0.0', nil)
23
+ server.addr
24
+ ensure
25
+ server.close
26
+ end
27
+ end
28
+ end
@@ -1,51 +1,78 @@
1
1
  module Specjour
2
+ require 'specjour/rspec'
2
3
  require 'specjour/cucumber'
3
4
 
4
5
  class Worker
5
6
  include Protocol
6
- include SocketHelpers
7
+ include SocketHelper
7
8
  attr_accessor :printer_uri
8
- attr_reader :project_path, :specs_to_run, :number, :batch_size
9
-
10
- def initialize(project_path, printer_uri, number, batch_size)
11
- @project_path = project_path
12
- @specs_to_run = specs_to_run
13
- @number = number.to_i
14
- @batch_size = batch_size.to_i
15
- self.printer_uri = printer_uri
16
- Rspec::DistributedFormatter.batch_size = batch_size
9
+ attr_reader :project_path, :number, :preload_spec, :preload_feature, :task
10
+
11
+ def initialize(options = {})
12
+ ARGV.replace []
13
+ $stdout = StringIO.new if options[:quiet]
14
+ @project_path = options[:project_path]
15
+ @number = options[:number].to_i
16
+ @preload_spec = options[:preload_spec]
17
+ @preload_feature = options[:preload_feature]
18
+ @task = options[:task]
19
+ self.printer_uri = options[:printer_uri]
17
20
  set_env_variables
21
+ Dir.chdir(project_path)
18
22
  end
19
23
 
20
24
  def printer_uri=(val)
21
25
  @printer_uri = URI.parse(val)
22
26
  end
23
27
 
24
- def run
28
+ def prepare
29
+ load_app
30
+ Configuration.prepare.call
31
+ end
32
+
33
+ def run_tests
34
+ load_app
35
+ Configuration.after_fork.call
25
36
  run_time = 0
26
- Dir.chdir(project_path)
37
+
27
38
  while test = connection.next_test
28
- run_time += Benchmark.realtime do
39
+ time = Benchmark.realtime do
29
40
  run_test test
30
41
  end
42
+ run_time += time if test =~ /_spec\.rb$/
31
43
  end
32
- connection.send_message(:worker_summary=, {:duration => sprintf("%6f", run_time)})
44
+ connection.send_message(:rspec_summary=, {:duration => sprintf("%6f", run_time)})
33
45
  connection.send_message(:done)
34
46
  connection.disconnect
35
47
  end
36
48
 
49
+ def start
50
+ send task
51
+ end
52
+
37
53
  protected
38
54
 
39
55
  def connection
40
56
  @connection ||= printer_connection
41
57
  end
42
58
 
59
+ def load_app
60
+ Rspec::Preloader.load(preload_spec) if preload_spec
61
+ Cucumber::Preloader.load(preload_feature) if preload_feature
62
+ end
63
+
43
64
  def printer_connection
44
65
  Connection.new printer_uri
45
66
  end
46
67
 
68
+ def print_status(test)
69
+ status = "[#{ENV['TEST_ENV_NUMBER']}] Running #{test}"
70
+ puts status
71
+ $PROGRAM_NAME = "specjour#{status}"
72
+ end
73
+
47
74
  def run_test(test)
48
- puts "[#{ENV['TEST_ENV_NUMBER']}] Running #{test}"
75
+ print_status(test)
49
76
  if test =~ /\.feature$/
50
77
  run_feature test
51
78
  else
@@ -54,7 +81,6 @@ module Specjour
54
81
  end
55
82
 
56
83
  def run_feature(feature)
57
- set_up_cucumber
58
84
  cli = ::Cucumber::Cli::Main.new(['--format', 'Specjour::Cucumber::DistributedFormatter', feature], connection)
59
85
  cli.execute!(::Cucumber::Cli::Main.step_mother)
60
86
  end
@@ -70,17 +96,8 @@ module Specjour
70
96
  end
71
97
 
72
98
  def set_env_variables
73
- ENV['PREPARE_DB'] = 'true'
74
99
  ENV['RSPEC_COLOR'] = 'true'
75
100
  ENV['TEST_ENV_NUMBER'] = number.to_s
76
101
  end
77
-
78
- def set_up_cucumber
79
- unless @cucumber_loaded
80
- Cucumber::DistributedFormatter.batch_size = batch_size
81
- ::Cucumber::Cli::Options.class_eval { def print_profile_information; end }
82
- @cucumber_loaded = true
83
- end
84
- end
85
102
  end
86
103
  end