Class: Paraspec::Master
- Inherits:
-
Object
- Object
- Paraspec::Master
- Defined in:
- lib/paraspec/master.rb
Overview
The master process has three responsibilities:
-
Load all tests and abort the run if there are errors outside of examples.
-
Maintain the queue of tests to feed the workers. The master process also synchronizes access to this queue.
-
Aggregate test reports from the workers and present them to the outside world in a coherent fashion. The latter means that numbers presented are for the entire suite, not for parts of it as executed by any single worker, and that output from a single test execution is not broken up by output from other test executions.
Instance Attribute Summary collapse
-
#non_example_exception_count ⇒ Object
readonly
Returns the value of attribute non_example_exception_count.
Instance Method Summary collapse
- #do_example_passed(spec, execution_result) ⇒ Object
- #dump_summary ⇒ Object
- #example_count ⇒ Object
- #example_passed(payload) ⇒ Object
- #find_example(spec) ⇒ Object
- #get_spec ⇒ Object
- #ident ⇒ Object
-
#initialize(options = {}) ⇒ Master
constructor
A new instance of Master.
- #notify_example_started(payload) ⇒ Object
- #ping ⇒ Object
- #reporter ⇒ Object
- #run ⇒ Object
- #status ⇒ Object
- #stop ⇒ Object
- #stop? ⇒ Boolean
- #suite_ok? ⇒ Boolean
- #suite_started ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Master
Returns a new instance of Master.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/paraspec/master.rb', line 14 def initialize(={}) @supervisor_pipe = [:supervisor_pipe] #RSpec.configuration.formatter = 'progress' if RSpec.world.example_groups.count > 0 raise 'Example groups loaded too early/spilled across processes' end = RSpec::Core::ConfigurationOptions.new(ARGV) @non_example_exception_count = 0 begin # This can fail if for example a nonexistent formatter is referenced .configure(RSpec.configuration) rescue Exception => e puts "#{e.class}: #{e}" puts e.backtrace.join("\n") # TODO and report this situation as a configuration problem # and not a test suite problem @non_example_exception_count = 1 end =begin if RSpec.configuration.files_to_run.empty? RSpec.configuration.send(:remove_instance_variable, '@files_to_run') RSpec.configuration.files_or_directories_to_run = RSpec.configuration.default_path RSpec.configuration.files_to_run p ['aa1',RSpec.configuration.files_to_run] rspec_options.configure(RSpec.configuration) RSpec.configuration.load_spec_files end =end # It seems that load_spec_files sometimes rescues exceptions outside of # examples and sometimes does not, handle it both ways if @non_example_exception_count == 0 begin RSpec.configuration.load_spec_files rescue Exception => e puts "#{e.class}: #{e}" puts e.backtrace.join("\n") @non_example_exception_count = 1 end end if @non_example_exception_count == 0 @non_example_exception_count = RSpec.world.reporter.non_example_exception_count end @queue = [] if @non_example_exception_count == 0 @queue += RSpecFacade.all_example_groups puts "#{@queue.length} example groups queued" else puts "#{@non_example_exception_count} errors outside of examples, aborting" end end |
Instance Attribute Details
#non_example_exception_count ⇒ Object (readonly)
Returns the value of attribute non_example_exception_count.
68 69 70 |
# File 'lib/paraspec/master.rb', line 68 def non_example_exception_count @non_example_exception_count end |
Instance Method Details
#do_example_passed(spec, execution_result) ⇒ Object
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/paraspec/master.rb', line 133 def do_example_passed(spec, execution_result) #return example = find_example(spec) # Can write to example here example.[:execution_result] = execution_result status = execution_result.status m = "example_#{status}" reporter.send(m, example) nil end |
#dump_summary ⇒ Object
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/paraspec/master.rb', line 180 def dump_summary reporter.stop all_examples = RSpecFacade.all_examples notification = RSpec::Core::Notifications::SummaryNotification.new( @start_time ? Time.now-@start_time : 0, all_examples, all_examples.select { |e| e.execution_result.status == :failed }, all_examples.select { |e| e.execution_result.status == :pending }, 0, non_example_exception_count, ) examples_notification = RSpec::Core::Notifications::ExamplesNotification.new(reporter) RSpec.configuration.formatters.each do |f| if f.respond_to?(:dump_summary) f.dump_summary(notification) end if f.respond_to?(:dump_failures) f.dump_failures(examples_notification) end if f.respond_to?(:dump_pending) f.dump_pending(examples_notification) end end nil end |
#example_count ⇒ Object
98 99 100 |
# File 'lib/paraspec/master.rb', line 98 def example_count RSpecFacade.all_examples.count end |
#example_passed(payload) ⇒ Object
121 122 123 124 125 126 |
# File 'lib/paraspec/master.rb', line 121 def example_passed(payload) spec = payload[:spec] # ExecutionResult result = payload['result'] do_example_passed(spec, result) end |
#find_example(spec) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/paraspec/master.rb', line 144 def find_example(spec) if spec.nil? #byebug raise ArgumentError, 'Nil spec' end example = (RSpecFacade.all_example_groups + RSpecFacade.all_examples).detect do |example| example.[:file_path] == spec[:file_path] && example.[:scoped_id] == spec[:scoped_id] end unless example puts "Not found: #{spec[:file_path]}[#{spec[:scoped_id]}]" #byebug raise "Not found: #{spec[:file_path]}[#{spec[:scoped_id]}]" end example end |
#get_spec ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/paraspec/master.rb', line 102 def get_spec while true example_group = @queue.shift return nil if example_group.nil? # TODO I am still not 100% on what should be filtered and pruned where, # but we shouldn't be returning a specification here unless # there are tests in it that a worker will run pruned_examples = RSpec.configuration.filter_manager.prune(example_group.examples) next if pruned_examples.empty? m = example_group. return { file_path: m[:file_path], scoped_id: m[:scoped_id], } end end |
#ident ⇒ Object
215 216 217 |
# File 'lib/paraspec/master.rb', line 215 def ident "[m]" end |
#notify_example_started(payload) ⇒ Object
128 129 130 131 |
# File 'lib/paraspec/master.rb', line 128 def notify_example_started(payload) example = find_example(payload[:spec]) reporter.example_started(example) end |
#ping ⇒ Object
81 82 83 |
# File 'lib/paraspec/master.rb', line 81 def ping true end |
#reporter ⇒ Object
161 162 163 |
# File 'lib/paraspec/master.rb', line 161 def reporter @reporter ||= RSpec.configuration.reporter end |
#run ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/paraspec/master.rb', line 70 def run Thread.new do #HttpServer.set(:master, self).run!(port: 6031) MsgpackServer.new(self).run end until @stop sleep 1 end Paraspec.logger.debug_state("Exiting") end |
#status ⇒ Object
207 208 209 210 211 212 213 |
# File 'lib/paraspec/master.rb', line 207 def status if RSpecFacade.all_examples.any? { |example| example.execution_result.status == :failed } 1 else 0 end end |
#stop ⇒ Object
85 86 87 88 |
# File 'lib/paraspec/master.rb', line 85 def stop Paraspec.logger.debug_state("Stopping") @stop = true end |
#stop? ⇒ Boolean
90 91 92 |
# File 'lib/paraspec/master.rb', line 90 def stop? @stop end |
#suite_ok? ⇒ Boolean
94 95 96 |
# File 'lib/paraspec/master.rb', line 94 def suite_ok? RSpec.configuration.reporter.send(:instance_variable_get,'@non_example_exception_count') == 0 end |
#suite_started ⇒ Object
165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/paraspec/master.rb', line 165 def suite_started @start_time = Time.now notification = RSpec::Core::Notifications::StartNotification.new( RSpecFacade.all_examples.count, 0 ) RSpec.configuration.formatters.each do |f| if f.respond_to?(:start) f.start(notification) end end true end |