-
Notifications
You must be signed in to change notification settings - Fork 33
/
loader.rb
136 lines (120 loc) · 3.2 KB
/
loader.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
module Specjour
class Loader
include Protocol
include Fork
attr_reader :test_paths, :printer_uri, :project_path, :task, :worker_size, :worker_pids, :quiet
def initialize(options = {})
@options = options
@printer_uri = options[:printer_uri]
@test_paths = options[:test_paths]
@worker_size = options[:worker_size]
@task = options[:task]
@quiet = options[:quiet]
@project_path = options[:project_path]
@worker_pids = []
Dir.chdir project_path
Specjour.load_custom_hooks
end
def start
load_app
Configuration.after_load.call
(1..worker_size).each do |index|
worker_pids << fork do
Worker.new(
:number => index,
:printer_uri => printer_uri,
:quiet => quiet
).send(task)
end
end
Process.waitall
ensure
kill_worker_processes
end
def spec_files
@spec_files ||= file_collector(spec_paths) do |path|
if path == project_path
Dir["#{path}/spec/**/*_spec.rb"]
else
Dir["#{path}/**/*_spec.rb"]
end
end
end
def feature_files
@feature_files ||= file_collector(feature_paths) do |path|
if path == project_path
Dir["#{path}/features/**/*.feature"]
else
Dir["#{path}/**/*.feature"]
end
end
end
protected
def spec_paths
@spec_paths ||= test_paths.select {|p| p =~ /spec.*$/}
end
def feature_paths
@feature_paths ||= test_paths.select {|p| p =~ /features.*$/}
end
def file_collector(paths, &globber)
if spec_paths.empty? && feature_paths.empty?
globber[project_path]
else
paths.map do |path|
path = File.expand_path(path, project_path)
if File.directory?(path)
globber[path]
else
path
end
end.flatten.uniq
end
end
def load_app
RSpec::Preloader.load spec_files if spec_files.any?
Cucumber::Preloader.load if feature_files.any?
register_tests_with_printer
end
def register_tests_with_printer
tests = rspec_examples | feature_files
connection.send_message :tests=, tests
end
def rspec_examples
if spec_files.any?
filtered_examples
else
[]
end
end
def filtered_examples
examples = ::RSpec.world.example_groups.map do |g|
g.descendant_filtered_examples
end.flatten
locations = examples.map do |e|
meta = e.metadata
shared_group = e.example_group.ancestors.detect do |group|
group.metadata[:shared_group_name]
end
if shared_group
meta = shared_group.metadata[:example_group]
end
meta[:location]
end
ensure
::RSpec.reset
end
def kill_worker_processes
if Specjour.interrupted?
Process.kill('INT', *worker_pids) rescue Errno::ESRCH
else
Process.kill('KILL', *worker_pids) rescue Errno::ESRCH
end
end
def connection
@connection ||= begin
at_exit { connection.disconnect }
Connection.new URI.parse(printer_uri)
end
end
end
end