rspec-tap-formatters 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module TAP
5
+ module Formatters
6
+ # Test stats calculator
7
+ class TestStats
8
+ # @!attribute
9
+ # @return [Hash<Integer, Array<Integer, 4>>] example stats
10
+ attr_reader :data
11
+
12
+ # Constructor
13
+ def initialize
14
+ @data = {}
15
+ end
16
+
17
+ # Populates total number of examples and one of
18
+ # passing, failing, and, pending example.
19
+ # Traverses bottom up to populate each of the parent example group
20
+ # stats.
21
+ #
22
+ # @param notification [ExampleNotification] example notification
23
+ # @param index [Integer] the example status index
24
+ # (1 - Passing, 2 - Failing, 3 - Pending)
25
+ def populate(notification, index)
26
+ metadata = notification.example.metadata[:example_group]
27
+ increment(metadata[:line_number], index)
28
+
29
+ while (parent_metadata = metadata[:parent_example_group])
30
+ metadata = parent_metadata
31
+ increment(metadata[:line_number], index)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ # Increments the stats for a line number and example status.
38
+ #
39
+ # @param line_number [Integer] the example or group line number
40
+ # @param index [Integer] the example status index
41
+ # (1 - Passing, 2 - Failing, 3 - Pending)
42
+ def increment(line_number, index)
43
+ @data[line_number] ||= [0, 0, 0, 0]
44
+ @data[line_number][0] += 1
45
+ @data[line_number][index] += 1
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Namespace for the parent module.
4
+ module RSpec
5
+ # Namespace for the submodule TAP.
6
+ module TAP
7
+ # Namespace for all the formatters code.
8
+ module Formatters
9
+ # Namespace for the version.
10
+ module Version
11
+ # The current version
12
+ STRING = '0.1.0'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,399 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ RSpec.describe RSpec::TAP::Formatters::Compact do
6
+ subject(:formatter) { described_class.new(report_output) }
7
+
8
+ let(:report_output) { StringIO.new }
9
+ let(:report_printer) { RSpec::TAP::Formatters::Printer.new(report_output) }
10
+ let(:report_test_stats) { RSpec::TAP::Formatters::TestStats.new }
11
+
12
+ before do
13
+ formatter.instance_variable_set(:@printer, report_printer)
14
+ formatter.instance_variable_set(:@test_stats, report_test_stats)
15
+ formatter.instance_variable_set(:@seed, nil)
16
+ formatter.instance_variable_set(:@level, 0)
17
+ formatter.instance_variable_set(:@example_number, 0)
18
+ end
19
+
20
+ describe '#seed' do
21
+ let(:seed) { SecureRandom.random_number(10_000) }
22
+
23
+ context 'with seed used' do
24
+ let(:notification) { OpenStruct.new(seed: seed, seed_used?: true) }
25
+
26
+ it 'updates instance variable' do
27
+ expect { formatter.seed(notification) }
28
+ .to change { formatter.instance_variable_get(:@seed) }
29
+ .from(nil)
30
+ .to(seed)
31
+ end
32
+ end
33
+
34
+ context 'without seed used' do
35
+ let(:notification) { OpenStruct.new(seed: seed, seed_used?: false) }
36
+
37
+ it 'does not update instance variable' do
38
+ expect { formatter.seed(notification) }
39
+ .not_to change { formatter.instance_variable_get(:@seed) }
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#start' do
45
+ let(:count) { 1 + SecureRandom.random_number(5) }
46
+ let(:notification) { OpenStruct.new(count: count) }
47
+
48
+ it 'delegates to printer' do
49
+ allow(report_printer).to receive(:start_output)
50
+
51
+ formatter.start(notification)
52
+
53
+ expect(report_printer).to have_received(:start_output).with(no_args)
54
+ end
55
+ end
56
+
57
+ describe '#start_dump' do
58
+ it 'delegates to printer' do
59
+ allow(report_printer).to receive(:example_progress_dump)
60
+
61
+ formatter.start_dump(OpenStruct.new)
62
+
63
+ expect(report_printer).to have_received(:example_progress_dump)
64
+ .with(no_args)
65
+ end
66
+ end
67
+
68
+ describe '#example_group_started' do
69
+ let(:level) { 1 + SecureRandom.random_number(5) }
70
+ let(:example_number) { 1 + SecureRandom.random_number(5) }
71
+
72
+ let(:description) { 'test-or-group-foo' }
73
+ let(:group) { OpenStruct.new(description: description) }
74
+ let(:notification) { OpenStruct.new(group: group) }
75
+
76
+ before do
77
+ formatter.instance_variable_set(:@level, level)
78
+ formatter.instance_variable_set(:@example_number, example_number)
79
+ end
80
+
81
+ it 'delegates to printer' do
82
+ allow(report_printer).to receive(:group_start_output)
83
+
84
+ formatter.example_group_started(notification)
85
+
86
+ expect(report_printer).to have_received(:group_start_output)
87
+ .with(notification, level)
88
+ end
89
+
90
+ it 'increments level by one' do
91
+ expect { formatter.example_group_started(notification) }
92
+ .to change { formatter.instance_variable_get(:@level) }
93
+ .by(1)
94
+ end
95
+
96
+ it 'resets example number to zero' do
97
+ expect { formatter.example_group_started(notification) }
98
+ .to change { formatter.instance_variable_get(:@example_number) }
99
+ .from(example_number)
100
+ .to(0)
101
+ end
102
+ end
103
+
104
+ describe '#example_group_finished' do
105
+ let(:passed) { 1 + SecureRandom.random_number(5) }
106
+ let(:failed) { 1 + SecureRandom.random_number(5) }
107
+ let(:pending) { 1 + SecureRandom.random_number(5) }
108
+ let(:tests) { passed + failed + pending }
109
+ let(:stats_data) { { line_number => [tests, passed, failed, pending] } }
110
+
111
+ let(:group) { OpenStruct.new(metadata: { line_number: line_number }) }
112
+ let(:notification) { OpenStruct.new(group: group) }
113
+
114
+ before do
115
+ formatter.instance_variable_set(:@level, level)
116
+ formatter.instance_variable_get(:@test_stats)
117
+ .instance_variable_set(:@data, stats_data)
118
+ end
119
+
120
+ context 'when root level test' do
121
+ let(:level) { 0 }
122
+ let(:line_number) { 1 + SecureRandom.random_number(5) }
123
+
124
+ it 'delegates to printer' do
125
+ allow(report_printer).to receive(:group_finished_output)
126
+
127
+ formatter.example_group_finished(notification)
128
+
129
+ expect(report_printer).to have_received(:group_finished_output)
130
+ .with(stats_data[line_number], level)
131
+ end
132
+
133
+ it 'does not decrement level' do
134
+ expect { formatter.example_group_finished(notification) }
135
+ .not_to change { formatter.instance_variable_get(:@level) }
136
+ end
137
+
138
+ it 'instantiates test stats object' do
139
+ expect { formatter.example_group_finished(notification) }
140
+ .to change {
141
+ formatter.instance_variable_get(:@test_stats).object_id
142
+ }
143
+ end
144
+ end
145
+
146
+ context 'when non-root level test' do
147
+ let(:level) { 2 }
148
+ let(:line_number) { 1 + SecureRandom.random_number(5) }
149
+
150
+ it 'delegates to printer' do
151
+ allow(report_printer).to receive(:group_finished_output)
152
+
153
+ formatter.example_group_finished(notification)
154
+
155
+ expect(report_printer).to have_received(:group_finished_output)
156
+ .with(stats_data[line_number], level)
157
+ end
158
+
159
+ it 'decrements level' do
160
+ expect { formatter.example_group_finished(notification) }
161
+ .to change { formatter.instance_variable_get(:@level) }
162
+ .by(-1)
163
+ end
164
+
165
+ it 'does not instantiate test stats object' do
166
+ expect { formatter.example_group_finished(notification) }
167
+ .not_to change {
168
+ formatter.instance_variable_get(:@test_stats).object_id
169
+ }
170
+ end
171
+ end
172
+ end
173
+
174
+ describe '#example_started' do
175
+ let(:example_number) { 1 + SecureRandom.random_number(5) }
176
+
177
+ it 'increments example number by one' do
178
+ expect { formatter.example_started(OpenStruct.new) }
179
+ .to change { formatter.instance_variable_get(:@example_number) }
180
+ .by(1)
181
+ end
182
+ end
183
+
184
+ describe '#example_passed' do
185
+ let(:level) { 1 + SecureRandom.random_number(5) }
186
+ let(:example_number) { 1 + SecureRandom.random_number(5) }
187
+ let(:example_status) { :success }
188
+ let(:example_status_index) { 1 }
189
+
190
+ let(:description) { 'example-foo' }
191
+ let(:example) { OpenStruct.new(description: description) }
192
+ let(:notification) { OpenStruct.new(example: example) }
193
+
194
+ before do
195
+ formatter.instance_variable_set(:@level, level)
196
+ formatter.instance_variable_set(:@example_number, example_number)
197
+
198
+ allow(report_test_stats).to receive(:populate)
199
+ end
200
+
201
+ it 'populates test stats' do
202
+ formatter.example_passed(notification)
203
+
204
+ expect(report_test_stats).to have_received(:populate)
205
+ .with(notification, example_status_index)
206
+ end
207
+
208
+ it 'delegates progress report to printer' do
209
+ allow(report_printer).to receive(:example_progress_output)
210
+
211
+ formatter.example_passed(notification)
212
+
213
+ expect(report_printer).to have_received(:example_progress_output)
214
+ .with(example_status)
215
+ end
216
+
217
+ it 'delegates status report to printer' do
218
+ allow(report_printer).to receive(:success_output)
219
+
220
+ formatter.example_passed(notification)
221
+
222
+ expect(report_printer).to have_received(:success_output)
223
+ .with(description, example_number, level)
224
+ end
225
+ end
226
+
227
+ describe '#example_failed' do
228
+ let(:level) { 1 + SecureRandom.random_number(5) }
229
+ let(:example_number) { 1 + SecureRandom.random_number(5) }
230
+ let(:example_status) { :failure }
231
+ let(:example_status_index) { 2 }
232
+
233
+ let(:description) { 'example-foo' }
234
+ let(:example) { OpenStruct.new(description: description) }
235
+ let(:notification) { OpenStruct.new(example: example) }
236
+
237
+ before do
238
+ formatter.instance_variable_set(:@level, level)
239
+ formatter.instance_variable_set(:@example_number, example_number)
240
+
241
+ allow(report_test_stats).to receive(:populate)
242
+ end
243
+
244
+ it 'populates test stats' do
245
+ formatter.example_failed(notification)
246
+
247
+ expect(report_test_stats).to have_received(:populate)
248
+ .with(notification, example_status_index)
249
+ end
250
+
251
+ it 'delegates progress report to printer' do
252
+ allow(report_printer).to receive(:example_progress_output)
253
+
254
+ formatter.example_failed(notification)
255
+
256
+ expect(report_printer).to have_received(:example_progress_output)
257
+ .with(example_status)
258
+ end
259
+
260
+ it 'delegates status report to printer' do
261
+ allow(report_printer).to receive(:failure_output)
262
+
263
+ formatter.example_failed(notification)
264
+
265
+ expect(report_printer).to have_received(:failure_output)
266
+ .with(description, example_number, level)
267
+ end
268
+ end
269
+
270
+ describe '#example_pending' do
271
+ let(:level) { 1 + SecureRandom.random_number(5) }
272
+ let(:example_number) { 1 + SecureRandom.random_number(5) }
273
+ let(:example_status) { :pending }
274
+ let(:example_status_index) { 3 }
275
+
276
+ let(:description) { 'example-foo' }
277
+ let(:example) do
278
+ OpenStruct.new(
279
+ description: description,
280
+ execution_result: execution_result
281
+ )
282
+ end
283
+ let(:notification) { OpenStruct.new(example: example) }
284
+
285
+ before do
286
+ formatter.instance_variable_set(:@level, level)
287
+ formatter.instance_variable_set(:@example_number, example_number)
288
+
289
+ allow(report_test_stats).to receive(:populate)
290
+ end
291
+
292
+ shared_examples_for 'pending example' do
293
+ it 'populates test stats' do
294
+ formatter.example_pending(notification)
295
+
296
+ expect(report_test_stats).to have_received(:populate)
297
+ .with(notification, example_status_index)
298
+ end
299
+
300
+ it 'delegates progress report to printer' do
301
+ allow(report_printer).to receive(:example_progress_output)
302
+
303
+ formatter.example_pending(notification)
304
+
305
+ expect(report_printer).to have_received(:example_progress_output)
306
+ .with(example_status)
307
+ end
308
+
309
+ it 'delegates status report to printer' do
310
+ allow(report_printer).to receive(:pending_output)
311
+
312
+ formatter.example_pending(notification)
313
+
314
+ expect(report_printer).to have_received(:pending_output)
315
+ .with(notification, description, example_number, level)
316
+ end
317
+ end
318
+
319
+ context 'with pending' do
320
+ let(:pending_message) { "pending-#{SecureRandom.hex}" }
321
+ let(:directive) { "TODO: #{pending_message}" }
322
+ let(:execution_result) do
323
+ OpenStruct.new(
324
+ pending_message: pending_message,
325
+ example_skipped?: false
326
+ )
327
+ end
328
+
329
+ include_examples('pending example')
330
+ end
331
+
332
+ context 'with skipped' do
333
+ let(:pending_message) { "skip-#{SecureRandom.hex}" }
334
+ let(:directive) { "SKIP: #{pending_message}" }
335
+ let(:execution_result) do
336
+ OpenStruct.new(
337
+ pending_message: pending_message,
338
+ example_skipped?: true
339
+ )
340
+ end
341
+
342
+ include_examples('pending example')
343
+ end
344
+ end
345
+
346
+ describe '#message' do
347
+ let(:notification) { OpenStruct.new }
348
+
349
+ it 'delegates to printer' do
350
+ allow(report_printer).to receive(:message_output)
351
+
352
+ formatter.message(notification)
353
+
354
+ expect(report_printer).to have_received(:message_output)
355
+ .with(notification)
356
+ end
357
+ end
358
+
359
+ describe '#dump_failures' do
360
+ let(:notification) { OpenStruct.new }
361
+
362
+ it 'delegates to printer' do
363
+ allow(report_printer).to receive(:store_failed_examples_summary)
364
+
365
+ formatter.dump_failures(notification)
366
+
367
+ expect(report_printer).to have_received(:store_failed_examples_summary)
368
+ .with(notification)
369
+ end
370
+ end
371
+
372
+ describe '#dump_pending' do
373
+ let(:notification) { OpenStruct.new }
374
+
375
+ it 'delegates to printer' do
376
+ allow(report_printer).to receive(:store_pending_examples_summary)
377
+
378
+ formatter.dump_pending(notification)
379
+
380
+ expect(report_printer).to have_received(:store_pending_examples_summary)
381
+ .with(notification)
382
+ end
383
+ end
384
+
385
+ describe '#dump_summary' do
386
+ let(:seed) { 1 + SecureRandom.random_number(10_000) }
387
+ let(:notification) { OpenStruct.new }
388
+
389
+ it 'delegates to printer' do
390
+ allow(report_printer).to receive(:summary_output)
391
+
392
+ formatter.instance_variable_set(:@seed, seed)
393
+ formatter.dump_summary(notification)
394
+
395
+ expect(report_printer).to have_received(:summary_output)
396
+ .with(notification, seed)
397
+ end
398
+ end
399
+ end