rspec-tracer 0.9.3 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +27 -2
- data/lib/rspec_tracer/cache.rb +75 -40
- data/lib/rspec_tracer/configuration.rb +16 -9
- data/lib/rspec_tracer/coverage_merger.rb +41 -0
- data/lib/rspec_tracer/coverage_reporter.rb +31 -28
- data/lib/rspec_tracer/coverage_writer.rb +58 -0
- data/lib/rspec_tracer/html_reporter/reporter.rb +7 -6
- data/lib/rspec_tracer/remote_cache/validator.rb +1 -1
- data/lib/rspec_tracer/report_generator.rb +158 -0
- data/lib/rspec_tracer/report_merger.rb +81 -0
- data/lib/rspec_tracer/report_writer.rb +141 -0
- data/lib/rspec_tracer/reporter.rb +4 -158
- data/lib/rspec_tracer/rspec_runner.rb +2 -4
- data/lib/rspec_tracer/runner.rb +2 -112
- data/lib/rspec_tracer/version.rb +1 -1
- data/lib/rspec_tracer.rb +197 -27
- metadata +21 -16
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecTracer
|
4
|
+
class ReportGenerator
|
5
|
+
def initialize(reporter, cache)
|
6
|
+
@reporter = reporter
|
7
|
+
@cache = cache
|
8
|
+
end
|
9
|
+
|
10
|
+
def reverse_dependency_report
|
11
|
+
reverse_dependency = Hash.new do |examples, file_name|
|
12
|
+
examples[file_name] = {
|
13
|
+
example_count: 0,
|
14
|
+
examples: Hash.new(0)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
@reporter.dependency.each_pair do |example_id, files|
|
19
|
+
next if @reporter.interrupted_examples.include?(example_id)
|
20
|
+
|
21
|
+
example_file = @reporter.all_examples[example_id][:rerun_file_name]
|
22
|
+
|
23
|
+
files.each do |file_name|
|
24
|
+
reverse_dependency[file_name][:example_count] += 1
|
25
|
+
reverse_dependency[file_name][:examples][example_file] += 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
reverse_dependency.transform_values! do |data|
|
30
|
+
{
|
31
|
+
example_count: data[:example_count],
|
32
|
+
examples: data[:examples].sort_by { |file_name, count| [-count, file_name] }.to_h
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
reverse_dependency.sort_by { |file_name, data| [-data[:example_count], file_name] }.to_h
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_report
|
40
|
+
generate_last_run_report
|
41
|
+
generate_examples_status_report
|
42
|
+
|
43
|
+
%i[all_files all_examples dependency examples_coverage reverse_dependency].each do |report_type|
|
44
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
45
|
+
|
46
|
+
send("generate_#{report_type}_report")
|
47
|
+
|
48
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
49
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
50
|
+
|
51
|
+
puts "RSpec tracer generated #{report_type.to_s.tr('_', ' ')} report (took #{elapsed})" if RSpecTracer.verbose?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def generate_last_run_report
|
58
|
+
@reporter.last_run = {
|
59
|
+
pid: RSpecTracer.pid,
|
60
|
+
actual_count: RSpec.world.example_count + @reporter.skipped_examples.count,
|
61
|
+
example_count: RSpec.world.example_count,
|
62
|
+
duplicate_examples: @reporter.duplicate_examples.sum { |_, examples| examples.count },
|
63
|
+
interrupted_examples: @reporter.interrupted_examples.count,
|
64
|
+
failed_examples: @reporter.failed_examples.count,
|
65
|
+
skipped_examples: @reporter.skipped_examples.count,
|
66
|
+
pending_examples: @reporter.pending_examples.count,
|
67
|
+
flaky_examples: @reporter.flaky_examples.count
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_examples_status_report
|
72
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
73
|
+
|
74
|
+
generate_flaky_examples_report
|
75
|
+
generate_failed_examples_report
|
76
|
+
generate_pending_examples_report
|
77
|
+
|
78
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
79
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
80
|
+
|
81
|
+
puts "RSpec tracer generated flaky, failed, and pending examples report (took #{elapsed})" if RSpecTracer.verbose?
|
82
|
+
end
|
83
|
+
|
84
|
+
def generate_flaky_examples_report
|
85
|
+
@reporter.possibly_flaky_examples.each do |example_id|
|
86
|
+
next if @reporter.example_deleted?(example_id)
|
87
|
+
next unless @cache.flaky_examples.include?(example_id) ||
|
88
|
+
@reporter.example_passed?(example_id)
|
89
|
+
|
90
|
+
@reporter.register_flaky_example(example_id)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def generate_failed_examples_report
|
95
|
+
@cache.failed_examples.each do |example_id|
|
96
|
+
next if @reporter.example_deleted?(example_id) ||
|
97
|
+
@reporter.all_examples.key?(example_id)
|
98
|
+
|
99
|
+
@reporter.register_failed_example(example_id)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def generate_pending_examples_report
|
104
|
+
@cache.pending_examples.each do |example_id|
|
105
|
+
next if @reporter.example_deleted?(example_id) ||
|
106
|
+
@reporter.all_examples.key?(example_id)
|
107
|
+
|
108
|
+
@reporter.register_pending_example(example_id)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def generate_all_files_report
|
113
|
+
@cache.all_files.each_pair do |file_name, data|
|
114
|
+
next if @reporter.all_files.key?(file_name) ||
|
115
|
+
@reporter.file_deleted?(file_name)
|
116
|
+
|
117
|
+
@reporter.all_files[file_name] = data
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def generate_all_examples_report
|
122
|
+
@cache.all_examples.each_pair do |example_id, data|
|
123
|
+
next if @reporter.all_examples.key?(example_id) ||
|
124
|
+
@reporter.example_deleted?(example_id)
|
125
|
+
|
126
|
+
@reporter.all_examples[example_id] = data
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def generate_dependency_report
|
131
|
+
@cache.dependency.each_pair do |example_id, data|
|
132
|
+
next if @reporter.dependency.key?(example_id) ||
|
133
|
+
@reporter.example_deleted?(example_id)
|
134
|
+
|
135
|
+
@reporter.dependency[example_id] = data.reject do |file_name|
|
136
|
+
@reporter.file_deleted?(file_name)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
@reporter.dependency.transform_values!(&:to_a)
|
141
|
+
end
|
142
|
+
|
143
|
+
def generate_examples_coverage_report
|
144
|
+
@cache.cached_examples_coverage.each_pair do |example_id, data|
|
145
|
+
next if @reporter.examples_coverage.key?(example_id) ||
|
146
|
+
@reporter.example_deleted?(example_id)
|
147
|
+
|
148
|
+
@reporter.examples_coverage[example_id] = data.reject do |file_name|
|
149
|
+
@reporter.file_deleted?(file_name)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def generate_reverse_dependency_report
|
155
|
+
@reporter.reverse_dependency = reverse_dependency_report
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecTracer
|
4
|
+
class ReportMerger
|
5
|
+
attr_reader :all_examples, :duplicate_examples, :interrupted_examples,
|
6
|
+
:flaky_examples, :failed_examples, :pending_examples, :skipped_examples,
|
7
|
+
:all_files, :dependency, :reverse_dependency, :examples_coverage, :last_run
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@last_run = {}
|
11
|
+
@all_examples = {}
|
12
|
+
@duplicate_examples = {}
|
13
|
+
@interrupted_examples = Set.new
|
14
|
+
@flaky_examples = Set.new
|
15
|
+
@failed_examples = Set.new
|
16
|
+
@pending_examples = Set.new
|
17
|
+
@skipped_examples = Set.new
|
18
|
+
@all_files = {}
|
19
|
+
@dependency = Hash.new { |hash, key| hash[key] = Set.new }
|
20
|
+
@reverse_dependency = {}
|
21
|
+
@examples_coverage = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def merge(reports_dir)
|
25
|
+
reports_dir.each do |report_dir|
|
26
|
+
next unless File.directory?(report_dir)
|
27
|
+
|
28
|
+
merge_cache(load_cache(report_dir))
|
29
|
+
merge_last_run_report(File.dirname(report_dir))
|
30
|
+
end
|
31
|
+
|
32
|
+
@dependency.transform_values!(&:to_a)
|
33
|
+
|
34
|
+
@reverse_dependency = RSpecTracer::ReportGenerator.new(self, nil).reverse_dependency_report
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def load_cache(cache_dir)
|
40
|
+
cache = RSpecTracer::Cache.new
|
41
|
+
|
42
|
+
cache.send(:load_all_examples_cache, cache_dir, discard_run_reason: false)
|
43
|
+
cache.send(:load_duplicate_examples_cache, cache_dir)
|
44
|
+
cache.send(:load_interrupted_examples_cache, cache_dir)
|
45
|
+
cache.send(:load_flaky_examples_cache, cache_dir)
|
46
|
+
cache.send(:load_failed_examples_cache, cache_dir)
|
47
|
+
cache.send(:load_pending_examples_cache, cache_dir)
|
48
|
+
cache.send(:load_skipped_examples_cache, cache_dir)
|
49
|
+
cache.send(:load_all_files_cache, cache_dir)
|
50
|
+
cache.send(:load_dependency_cache, cache_dir)
|
51
|
+
cache.send(:load_examples_coverage_cache, cache_dir)
|
52
|
+
|
53
|
+
cache
|
54
|
+
end
|
55
|
+
|
56
|
+
def merge_cache(cache)
|
57
|
+
@all_examples.merge!(cache.all_examples) { |_, v1, v2| v1[:run_reason] ? v1 : v2 }
|
58
|
+
@duplicate_examples.merge!(cache.duplicate_examples) { |_, v1, v2| v1 + v2 }
|
59
|
+
@interrupted_examples.merge(cache.interrupted_examples)
|
60
|
+
@flaky_examples.merge(cache.flaky_examples)
|
61
|
+
@failed_examples.merge(cache.failed_examples)
|
62
|
+
@pending_examples.merge(cache.pending_examples)
|
63
|
+
@skipped_examples.merge(cache.skipped_examples)
|
64
|
+
@all_files.merge!(cache.all_files)
|
65
|
+
@dependency.merge!(cache.dependency) { |_, v1, v2| v1.merge(v2) }
|
66
|
+
@examples_coverage.merge!(cache.examples_coverage) do |_, v1, v2|
|
67
|
+
v1.merge(v2) { |_, v3, v4| v3.merge(v4) { |_, v5, v6| v5 + v6 } }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def merge_last_run_report(cache_dir)
|
72
|
+
file_name = File.join(cache_dir, 'last_run.json')
|
73
|
+
cached_last_run = JSON.parse(File.read(file_name), symbolize_names: true)
|
74
|
+
cached_last_run[:pid] = [cached_last_run[:pid]]
|
75
|
+
|
76
|
+
cached_last_run.delete_if { |key, _| %i[run_id timestamp].include?(key) }
|
77
|
+
|
78
|
+
@last_run.merge!(cached_last_run) { |_, v1, v2| v1 + v2 }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecTracer
|
4
|
+
class ReportWriter
|
5
|
+
def initialize(report_dir, reporter)
|
6
|
+
@report_dir = report_dir
|
7
|
+
@reporter = reporter
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_report
|
11
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
12
|
+
|
13
|
+
@run_id = Digest::MD5.hexdigest(@reporter.all_examples.keys.sort.to_json)
|
14
|
+
@cache_dir = File.join(@report_dir, @run_id)
|
15
|
+
|
16
|
+
FileUtils.mkdir_p(@cache_dir)
|
17
|
+
|
18
|
+
write_all_examples_report
|
19
|
+
write_duplicate_examples_report
|
20
|
+
write_interrupted_examples_report
|
21
|
+
write_flaky_examples_report
|
22
|
+
write_failed_examples_report
|
23
|
+
write_pending_examples_report
|
24
|
+
write_skipped_examples_report
|
25
|
+
write_all_files_report
|
26
|
+
write_dependency_report
|
27
|
+
write_reverse_dependency_report
|
28
|
+
write_examples_coverage_report
|
29
|
+
write_last_run_report
|
30
|
+
|
31
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
32
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
33
|
+
|
34
|
+
puts "RSpec tracer reports written to #{@cache_dir} (took #{elapsed})"
|
35
|
+
end
|
36
|
+
|
37
|
+
def print_duplicate_examples
|
38
|
+
return if @reporter.duplicate_examples.empty?
|
39
|
+
|
40
|
+
total = @reporter.duplicate_examples.sum { |_, examples| examples.count }
|
41
|
+
|
42
|
+
puts '=' * 80
|
43
|
+
puts ' IMPORTANT NOTICE -- RSPEC TRACER COULD NOT IDENTIFY SOME EXAMPLES UNIQUELY'
|
44
|
+
puts '=' * 80
|
45
|
+
puts "RSpec tracer could not uniquely identify the following #{total} examples:"
|
46
|
+
|
47
|
+
justify = ' ' * 2
|
48
|
+
nested_justify = justify * 3
|
49
|
+
|
50
|
+
@reporter.duplicate_examples.each_pair do |example_id, examples|
|
51
|
+
puts "#{justify}- Example ID: #{example_id} (#{examples.count} examples)"
|
52
|
+
|
53
|
+
examples.each do |example|
|
54
|
+
description = example[:full_description].strip
|
55
|
+
file_name = example[:rerun_file_name].sub(%r{^/}, '')
|
56
|
+
line_number = example[:rerun_line_number]
|
57
|
+
location = "#{file_name}:#{line_number}"
|
58
|
+
|
59
|
+
puts "#{nested_justify}* #{description} (#{location})"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
puts
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def write_all_examples_report
|
69
|
+
file_name = File.join(@cache_dir, 'all_examples.json')
|
70
|
+
|
71
|
+
File.write(file_name, JSON.pretty_generate(@reporter.all_examples))
|
72
|
+
end
|
73
|
+
|
74
|
+
def write_duplicate_examples_report
|
75
|
+
file_name = File.join(@cache_dir, 'duplicate_examples.json')
|
76
|
+
|
77
|
+
File.write(file_name, JSON.pretty_generate(@reporter.duplicate_examples))
|
78
|
+
end
|
79
|
+
|
80
|
+
def write_interrupted_examples_report
|
81
|
+
file_name = File.join(@cache_dir, 'interrupted_examples.json')
|
82
|
+
|
83
|
+
File.write(file_name, JSON.pretty_generate(@reporter.interrupted_examples.sort.to_a))
|
84
|
+
end
|
85
|
+
|
86
|
+
def write_flaky_examples_report
|
87
|
+
file_name = File.join(@cache_dir, 'flaky_examples.json')
|
88
|
+
|
89
|
+
File.write(file_name, JSON.pretty_generate(@reporter.flaky_examples.sort.to_a))
|
90
|
+
end
|
91
|
+
|
92
|
+
def write_failed_examples_report
|
93
|
+
file_name = File.join(@cache_dir, 'failed_examples.json')
|
94
|
+
|
95
|
+
File.write(file_name, JSON.pretty_generate(@reporter.failed_examples.sort.to_a))
|
96
|
+
end
|
97
|
+
|
98
|
+
def write_pending_examples_report
|
99
|
+
file_name = File.join(@cache_dir, 'pending_examples.json')
|
100
|
+
|
101
|
+
File.write(file_name, JSON.pretty_generate(@reporter.pending_examples.sort.to_a))
|
102
|
+
end
|
103
|
+
|
104
|
+
def write_skipped_examples_report
|
105
|
+
file_name = File.join(@cache_dir, 'skipped_examples.json')
|
106
|
+
|
107
|
+
File.write(file_name, JSON.pretty_generate(@reporter.skipped_examples.sort.to_a))
|
108
|
+
end
|
109
|
+
|
110
|
+
def write_all_files_report
|
111
|
+
file_name = File.join(@cache_dir, 'all_files.json')
|
112
|
+
|
113
|
+
File.write(file_name, JSON.pretty_generate(@reporter.all_files))
|
114
|
+
end
|
115
|
+
|
116
|
+
def write_dependency_report
|
117
|
+
file_name = File.join(@cache_dir, 'dependency.json')
|
118
|
+
|
119
|
+
File.write(file_name, JSON.pretty_generate(@reporter.dependency))
|
120
|
+
end
|
121
|
+
|
122
|
+
def write_reverse_dependency_report
|
123
|
+
file_name = File.join(@cache_dir, 'reverse_dependency.json')
|
124
|
+
|
125
|
+
File.write(file_name, JSON.pretty_generate(@reporter.reverse_dependency))
|
126
|
+
end
|
127
|
+
|
128
|
+
def write_examples_coverage_report
|
129
|
+
file_name = File.join(@cache_dir, 'examples_coverage.json')
|
130
|
+
|
131
|
+
File.write(file_name, JSON.pretty_generate(@reporter.examples_coverage))
|
132
|
+
end
|
133
|
+
|
134
|
+
def write_last_run_report
|
135
|
+
file_name = File.join(@report_dir, 'last_run.json')
|
136
|
+
last_run_data = @reporter.last_run.merge(run_id: @run_id, timestamp: Time.now.utc)
|
137
|
+
|
138
|
+
File.write(file_name, JSON.pretty_generate(last_run_data))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -4,8 +4,10 @@ module RSpecTracer
|
|
4
4
|
class Reporter
|
5
5
|
attr_reader :all_examples, :interrupted_examples, :duplicate_examples,
|
6
6
|
:possibly_flaky_examples, :flaky_examples, :pending_examples,
|
7
|
-
:
|
8
|
-
:
|
7
|
+
:skipped_examples, :failed_examples, :all_files, :modified_files,
|
8
|
+
:deleted_files, :dependency, :examples_coverage
|
9
|
+
|
10
|
+
attr_accessor :reverse_dependency, :last_run
|
9
11
|
|
10
12
|
def initialize
|
11
13
|
initialize_examples
|
@@ -151,92 +153,6 @@ module RSpecTracer
|
|
151
153
|
@examples_coverage = examples_coverage
|
152
154
|
end
|
153
155
|
|
154
|
-
def generate_reverse_dependency_report
|
155
|
-
@dependency.each_pair do |example_id, files|
|
156
|
-
next if @interrupted_examples.include?(example_id)
|
157
|
-
|
158
|
-
example_file = @all_examples[example_id][:rerun_file_name]
|
159
|
-
|
160
|
-
files.each do |file_name|
|
161
|
-
@reverse_dependency[file_name][:example_count] += 1
|
162
|
-
@reverse_dependency[file_name][:examples][example_file] += 1
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
format_reverse_dependency_report
|
167
|
-
end
|
168
|
-
|
169
|
-
def generate_last_run_report
|
170
|
-
@last_run = {
|
171
|
-
pid: RSpecTracer.pid,
|
172
|
-
actual_count: RSpec.world.example_count + @skipped_examples.count,
|
173
|
-
example_count: RSpec.world.example_count,
|
174
|
-
duplicate_examples: @duplicate_examples.sum { |_, examples| examples.count },
|
175
|
-
interrupted_examples: @interrupted_examples.count,
|
176
|
-
failed_examples: @failed_examples.count,
|
177
|
-
skipped_examples: @skipped_examples.count,
|
178
|
-
pending_examples: @pending_examples.count,
|
179
|
-
flaky_examples: @flaky_examples.count
|
180
|
-
}
|
181
|
-
end
|
182
|
-
|
183
|
-
def write_reports
|
184
|
-
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
185
|
-
|
186
|
-
@run_id = Digest::MD5.hexdigest(@all_examples.keys.sort.to_json)
|
187
|
-
@cache_dir = File.join(RSpecTracer.cache_path, @run_id)
|
188
|
-
|
189
|
-
FileUtils.mkdir_p(@cache_dir)
|
190
|
-
|
191
|
-
%i[
|
192
|
-
all_examples
|
193
|
-
flaky_examples
|
194
|
-
failed_examples
|
195
|
-
pending_examples
|
196
|
-
all_files
|
197
|
-
dependency
|
198
|
-
reverse_dependency
|
199
|
-
examples_coverage
|
200
|
-
last_run
|
201
|
-
].each { |report_type| send("write_#{report_type}_report") }
|
202
|
-
|
203
|
-
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
204
|
-
elpased = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
205
|
-
|
206
|
-
puts "RSpec tracer reports written to #{@cache_dir} (took #{elpased})"
|
207
|
-
end
|
208
|
-
|
209
|
-
# rubocop:disable Metrics/AbcSize
|
210
|
-
def print_duplicate_examples
|
211
|
-
return if @duplicate_examples.empty?
|
212
|
-
|
213
|
-
total = @duplicate_examples.sum { |_, examples| examples.count }
|
214
|
-
|
215
|
-
puts '=' * 80
|
216
|
-
puts ' IMPORTANT NOTICE -- RSPEC TRACER COULD NOT IDENTIFY SOME EXAMPLES UNIQUELY'
|
217
|
-
puts '=' * 80
|
218
|
-
puts "RSpec tracer could not uniquely identify the following #{total} examples:"
|
219
|
-
|
220
|
-
justify = ' ' * 2
|
221
|
-
nested_justify = justify * 3
|
222
|
-
|
223
|
-
@duplicate_examples.each_pair do |example_id, examples|
|
224
|
-
puts "#{justify}- Example ID: #{example_id} (#{examples.count} examples)"
|
225
|
-
|
226
|
-
examples.each do |example|
|
227
|
-
description = example[:full_description].strip
|
228
|
-
file_name = example[:rerun_file_name].sub(%r{^/}, '')
|
229
|
-
line_number = example[:rerun_line_number]
|
230
|
-
location = "#{file_name}:#{line_number}"
|
231
|
-
|
232
|
-
puts "#{nested_justify}* #{description} (#{location})"
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
puts
|
237
|
-
end
|
238
|
-
# rubocop:enable Metrics/AbcSize
|
239
|
-
|
240
156
|
private
|
241
157
|
|
242
158
|
def initialize_examples
|
@@ -284,75 +200,5 @@ module RSpecTracer
|
|
284
200
|
status: result.status.to_s
|
285
201
|
}
|
286
202
|
end
|
287
|
-
|
288
|
-
def format_reverse_dependency_report
|
289
|
-
@reverse_dependency.transform_values! do |data|
|
290
|
-
{
|
291
|
-
example_count: data[:example_count],
|
292
|
-
examples: data[:examples].sort_by { |file_name, count| [-count, file_name] }.to_h
|
293
|
-
}
|
294
|
-
end
|
295
|
-
|
296
|
-
report = @reverse_dependency.sort_by do |file_name, data|
|
297
|
-
[-data[:example_count], file_name]
|
298
|
-
end
|
299
|
-
|
300
|
-
@reverse_dependency = report.to_h
|
301
|
-
end
|
302
|
-
|
303
|
-
def write_all_examples_report
|
304
|
-
file_name = File.join(@cache_dir, 'all_examples.json')
|
305
|
-
|
306
|
-
File.write(file_name, JSON.pretty_generate(@all_examples))
|
307
|
-
end
|
308
|
-
|
309
|
-
def write_flaky_examples_report
|
310
|
-
file_name = File.join(@cache_dir, 'flaky_examples.json')
|
311
|
-
|
312
|
-
File.write(file_name, JSON.pretty_generate(@flaky_examples.to_a))
|
313
|
-
end
|
314
|
-
|
315
|
-
def write_failed_examples_report
|
316
|
-
file_name = File.join(@cache_dir, 'failed_examples.json')
|
317
|
-
|
318
|
-
File.write(file_name, JSON.pretty_generate(@failed_examples.to_a))
|
319
|
-
end
|
320
|
-
|
321
|
-
def write_pending_examples_report
|
322
|
-
file_name = File.join(@cache_dir, 'pending_examples.json')
|
323
|
-
|
324
|
-
File.write(file_name, JSON.pretty_generate(@pending_examples.to_a))
|
325
|
-
end
|
326
|
-
|
327
|
-
def write_all_files_report
|
328
|
-
file_name = File.join(@cache_dir, 'all_files.json')
|
329
|
-
|
330
|
-
File.write(file_name, JSON.pretty_generate(@all_files))
|
331
|
-
end
|
332
|
-
|
333
|
-
def write_dependency_report
|
334
|
-
file_name = File.join(@cache_dir, 'dependency.json')
|
335
|
-
|
336
|
-
File.write(file_name, JSON.pretty_generate(@dependency))
|
337
|
-
end
|
338
|
-
|
339
|
-
def write_reverse_dependency_report
|
340
|
-
file_name = File.join(@cache_dir, 'reverse_dependency.json')
|
341
|
-
|
342
|
-
File.write(file_name, JSON.pretty_generate(@reverse_dependency))
|
343
|
-
end
|
344
|
-
|
345
|
-
def write_examples_coverage_report
|
346
|
-
file_name = File.join(@cache_dir, 'examples_coverage.json')
|
347
|
-
|
348
|
-
File.write(file_name, JSON.pretty_generate(@examples_coverage))
|
349
|
-
end
|
350
|
-
|
351
|
-
def write_last_run_report
|
352
|
-
file_name = File.join(RSpecTracer.cache_path, 'last_run.json')
|
353
|
-
last_run_data = @last_run.merge(run_id: @run_id, timestamp: Time.now.utc)
|
354
|
-
|
355
|
-
File.write(file_name, JSON.pretty_generate(last_run_data))
|
356
|
-
end
|
357
203
|
end
|
358
204
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module RSpecTracer
|
4
4
|
module RSpecRunner
|
5
|
-
# rubocop:disable Metrics/AbcSize
|
6
5
|
def run_specs(example_groups)
|
7
6
|
actual_count = RSpec.world.example_count
|
8
7
|
RSpecTracer.no_examples = actual_count.zero?
|
@@ -23,18 +22,17 @@ module RSpecTracer
|
|
23
22
|
|
24
23
|
current_count = RSpec.world.example_count
|
25
24
|
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
26
|
-
|
25
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
27
26
|
|
28
27
|
puts
|
29
28
|
puts <<-EXAMPLES.strip.gsub(/\s+/, ' ')
|
30
29
|
RSpec tracer is running #{current_count} examples (actual: #{actual_count},
|
31
|
-
skipped: #{actual_count - current_count}) (took #{
|
30
|
+
skipped: #{actual_count - current_count}) (took #{elapsed})
|
32
31
|
EXAMPLES
|
33
32
|
|
34
33
|
RSpecTracer.running = true
|
35
34
|
|
36
35
|
super(filtered_example_groups)
|
37
36
|
end
|
38
|
-
# rubocop:enable Metrics/AbcSize
|
39
37
|
end
|
40
38
|
end
|