Class: Paraspec::WorkerRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/paraspec/worker_runner.rb

Overview

An RSpec test runner - in a worker process. This runner collects results and output and forwards them to the master process via DRb.

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ WorkerRunner

Returns a new instance of WorkerRunner.



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/paraspec/worker_runner.rb', line 6

def initialize(options={})
  @master_client = options[:master_client]

  # TODO capture stdout & stderr
  class << STDERR
    def master_client
      @master_client
    end
  end
  STDERR.send(:instance_variable_set, '@master_client', @master_client)
  runner.setup(STDOUT, STDERR)
end

Instance Method Details

#run(spec) ⇒ Object



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
67
68
69
70
71
72
73
74
75
# File 'lib/paraspec/worker_runner.rb', line 19

def run(spec)
  if RSpecFacade.all_example_groups.count == 0
    raise "No example groups loaded"
  end
  group = RSpecFacade.all_example_groups.detect do |g|
    g.[:file_path] == spec[:file_path] &&
    g.[:scoped_id] == spec[:scoped_id]
  end
  unless group
    puts "No example group for #{spec.inspect}, #{RSpecFacade.all_example_groups.count} total groups"
  #byebug
    raise "No example group for #{spec.inspect}"
  end
  if group.[:paraspec] && group.[:paraspec][:group]
    # unsplittable group
    # get all examples in child groups
    examples = []
    group_queue = [group]
    until group_queue.empty?
      next_group_queue = []
      group_queue.each do |group|
        next_group_queue += group.children
        examples += group.examples
      end
      group_queue = next_group_queue
    end
  else
    # leaf group
    examples = group.examples
    #Paraspec.logger.debug_state("Spec #{spec}: #{examples.length} examples")
    return if examples.empty?
    ids = examples.map { |e| e.[:scoped_id] }
    RSpec.configuration.send(:instance_variable_set, '@filter_manager', RSpec::Core::FilterManager.new)
    RSpec.configuration.filter_manager.add_ids(spec[:file_path], ids)
    RSpec.world.filter_examples
    examples = RSpec.configuration.filter_manager.prune(examples)
  end
  return if examples.empty?
  # It is important to run the entire world here because if
  # a particular example group is run, before/after :all hooks
  # aren't always run.
  # And "the entire world" means our complete list of example groups,
  # not RSpec.world.ordered_example_groups which are top level only!
  RSpecFacade.all_example_groups.each do |group|
    group.reset_memoized
  end
  # Hack to not run examples from each group each time I want to run
  # a single example. It seems that rspec performs filtering by file
  # at one time and by expressions/scoped id at a different time,
  # because simply requesting filtering by scoped id makes rspec
  # include examples from all other files (it also mutates the filters
  # when querying them for example groups... ugh)
  run_example_groups = RSpec.world.ordered_example_groups.select do |c_group|
    c_group.[:file_path] == spec[:file_path]
  end
  runner.run_specs(run_example_groups)
end