rspec-tap-formatters 0.1.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.
@@ -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