doggo 0.0.2

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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e400910e348f37feab93f558dc22c8ccff17bb5978ac0466827274f7b568a3cc
4
+ data.tar.gz: db85734f689ef749c06ad135ce24bc5e36e92b3a749178da187cbddb95cfbe3c
5
+ SHA512:
6
+ metadata.gz: c8f448cde211ab681a0057c1bfbeb56c3ae80aad416078c39fc1b12714ad81e7d934680ff77eaf71076fba55b67abe8f5839bf11ea31088bc352feca69c92964
7
+ data.tar.gz: e4561e754671832aab4f1afea408c2c06613b848387d7239679385e0ebe8ce684926ccbb279beb579cd032ec4e1c425142dabc833388be4e5f4d9a39759b6d09
@@ -0,0 +1,165 @@
1
+ require 'rspec/core'
2
+ require 'rspec/core/formatters/base_text_formatter'
3
+ require 'rspec/core/formatters/console_codes'
4
+
5
+ class Doggo < RSpec::Core::Formatters::BaseTextFormatter
6
+
7
+ RSpec::Core::Formatters.register(
8
+ self,
9
+ :start,
10
+ :example_started,
11
+ :example_group_started,
12
+ :example_group_finished,
13
+ :example_passed,
14
+ :example_pending,
15
+ :example_failed
16
+ )
17
+
18
+ attr_accessor(
19
+ :outstr,
20
+
21
+ :example_running,
22
+ :current_example_index,
23
+ :group_level,
24
+ :messages,
25
+
26
+ :total_count,
27
+ :pad,
28
+ :passed_count,
29
+ :pending_count,
30
+ :failed_count
31
+ )
32
+
33
+ def initialize(output)
34
+ @outstr = output
35
+
36
+ @example_running = false
37
+ @current_example_index = 0
38
+ @group_level = 0
39
+ @messages = []
40
+
41
+ @total_count = 0
42
+ @pad = nil
43
+ @passed_count = 0
44
+ @pending_count = 0
45
+ @failed_count = 0
46
+
47
+ super
48
+ end
49
+
50
+ def start(notification)
51
+ self.total_count = notification.count
52
+ self.pad = notification.count.to_s.size
53
+ super
54
+ end
55
+
56
+ def example_started(_notification)
57
+ self.example_running = true
58
+ self.current_example_index += 1
59
+ end
60
+
61
+ def example_group_started(notification)
62
+ self.outstr.puts() if self.group_level == 0
63
+ self.outstr.puts("#{group_progress()}#{current_indentation}#{notification.group.description.strip}")
64
+
65
+ self.group_level += 1
66
+ end
67
+
68
+ def example_group_finished(_notification)
69
+ self.group_level -= 1 if self.group_level > 0
70
+ end
71
+
72
+ def example_passed(passed)
73
+ self.outstr.puts(passed_output(passed.example))
74
+ flush_messages
75
+
76
+ self.passed_count += 1
77
+ self.example_running = false
78
+ end
79
+
80
+ def example_pending(pending)
81
+ self.outstr.puts(
82
+ pending_output(
83
+ pending.example,
84
+ pending.example.execution_result.pending_message
85
+ )
86
+ )
87
+
88
+ flush_messages
89
+
90
+ self.pending_count += 1
91
+ self.example_running = false
92
+ end
93
+
94
+ def example_failed(failure)
95
+ self.outstr.puts(failure_output(failure.example))
96
+ flush_messages
97
+
98
+ self.failed_count += 1
99
+ self.example_running = false
100
+ end
101
+
102
+ def message(notification)
103
+ if self.example_running
104
+ self.messages << notification.message
105
+ else
106
+ self.outstr.puts("#{group_progress()}#{current_indentation}#{notification.message}")
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ def flush_messages
113
+ self.messages.each do |message|
114
+ self.outstr.puts("#{group_progress()}#{current_indentation(1)}#{message}")
115
+ end
116
+
117
+ self.messages.clear
118
+ end
119
+
120
+ def passed_output(example)
121
+ RSpec::Core::Formatters::ConsoleCodes.wrap(
122
+ "#{example_progress()} #{current_indentation}#{example.description.strip}",
123
+ :success
124
+ )
125
+ end
126
+
127
+ def pending_output(example, message)
128
+ message = nil if message.downcase == 'temporarily skipped with xit'
129
+ message = " (#{message})" unless message.nil? || message.empty?
130
+
131
+ RSpec::Core::Formatters::ConsoleCodes.wrap(
132
+ "#{example_progress()} #{current_indentation}PENDING#{message} - #{example.description.strip}",
133
+ :pending
134
+ )
135
+ end
136
+
137
+ def failure_output(example)
138
+ RSpec::Core::Formatters::ConsoleCodes.wrap(
139
+ "#{example_progress()} #{current_indentation}FAILED (#{next_failure_index}) - #{example.description.strip}",
140
+ :failure
141
+ )
142
+ end
143
+
144
+ def group_progress
145
+ if self.pad.nil?
146
+ ''
147
+ else
148
+ "[#{' ' * self.pad} #{self.total_count}] "
149
+ end
150
+ end
151
+
152
+ def example_progress
153
+ "[#{self.current_example_index.to_s.rjust(self.pad, '0')}/#{self.total_count}]"
154
+ end
155
+
156
+ def next_failure_index
157
+ @next_failure_index ||= 0
158
+ @next_failure_index += 1
159
+ end
160
+
161
+ def current_indentation(offset = 0)
162
+ ' ' * (self.group_level + offset)
163
+ end
164
+
165
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Doggo examples', for_example_output: true do
4
+ context 'in a context' do
5
+ context 'with a nested context' do
6
+
7
+ it 'passes' do
8
+ expect(true).to eql(true)
9
+ end
10
+
11
+ it 'fails' do
12
+ expect(true).to eql(false)
13
+ end
14
+
15
+ xit 'is pending with xit' do
16
+ end
17
+
18
+ it 'is pending with a custom message' do
19
+ pending('custom message')
20
+ end
21
+ end
22
+ end
23
+
24
+ it 'outer passes' do
25
+ expect(true).to eql(true)
26
+ end
27
+
28
+ it 'outer fails' do
29
+ expect(true).to eql(false)
30
+ end
31
+
32
+ xit 'outer is pending with xit' do
33
+ end
34
+
35
+ it 'outer is pending with a custom message' do
36
+ pending('custom message')
37
+ end
38
+
39
+ context 'test count' do
40
+ it 'is taken to 9' do
41
+ expect(true).to eql(true)
42
+ end
43
+
44
+ it 'is taken to 10, showing leading zero pad formatting' do
45
+ expect(true).to eql(true)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,261 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Doggo do
4
+ before :each do
5
+ @bork = StringIO.new
6
+ @dog = Doggo.new(@bork)
7
+ end
8
+
9
+ context '#start' do
10
+ before :each do
11
+ @notification = double('Notification', count: 4)
12
+ end
13
+
14
+ it 'sets total count from notification' do
15
+ expect(@dog.total_count).to eql(0)
16
+ @dog.start(@notification)
17
+ expect(@dog.total_count).to eql(@notification.count)
18
+ @dog.start(@notification)
19
+ expect(@dog.total_count).to eql(@notification.count) # I.e. it was set, not incremented
20
+ end
21
+ end # "context '#start' do"
22
+
23
+ context 'individual examples' do
24
+ before :each do
25
+ @notification = double('Notification', count: 4)
26
+ @example_description = 'Example description'
27
+ @pending_message = 'Custom pending message'
28
+ @example = double(
29
+ 'Example',
30
+ description: @example_description,
31
+ execution_result: double(
32
+ 'Execution result',
33
+ pending_message: @pending_message
34
+ )
35
+ )
36
+ end
37
+
38
+ context '#example_started' do
39
+ it 'notes an example is running' do
40
+ expect(@dog.example_running).to eq(false)
41
+ @dog.example_started(@notification)
42
+ expect(@dog.example_running).to eq(true)
43
+ end
44
+
45
+ it 'increments the example index' do
46
+ expect(@dog.current_example_index).to eql(0)
47
+ @dog.example_started(@notification)
48
+ expect(@dog.current_example_index).to eql(1)
49
+ @dog.example_started(@notification)
50
+ expect(@dog.current_example_index).to eql(2)
51
+ end
52
+ end # "context '#example_started' do"
53
+
54
+ context '#example_passed' do
55
+ before :each do
56
+ @dog.start(@notification)
57
+ @passed = double('Passing test', example: @example)
58
+ end
59
+
60
+ it 'notes an example is no longer running' do
61
+ expect(@dog.example_running).to eq(false)
62
+
63
+ @dog.example_started(@notification)
64
+ expect(@dog.example_running).to eq(true)
65
+
66
+ @dog.example_passed(@passed)
67
+ expect(@dog.example_running).to eq(false)
68
+ end
69
+
70
+ it 'increments the "passed" count' do
71
+ expect(@dog.passed_count).to eql(0)
72
+
73
+ @dog.example_started(@notification)
74
+ @dog.example_passed(@passed)
75
+ expect(@dog.passed_count).to eql(1)
76
+
77
+ @dog.example_started(@notification)
78
+ @dog.example_passed(@passed)
79
+ expect(@dog.passed_count).to eql(2)
80
+ end
81
+
82
+ it 'logs the success' do
83
+ @dog.example_started(@notification)
84
+ @dog.example_passed(@passed)
85
+
86
+ expect(@bork.string).to include("[1/#{@notification.count}]")
87
+ expect(@bork.string).to include(@example_description)
88
+ end
89
+ end # "context '#example_passed' do"
90
+
91
+ context '#example_failed' do
92
+ before :each do
93
+ @dog.start(@notification)
94
+ @failed = double('Failing test', example: @example)
95
+ end
96
+
97
+ it 'notes an example is no longer running' do
98
+ expect(@dog.example_running).to eq(false)
99
+
100
+ @dog.example_started(@notification)
101
+ expect(@dog.example_running).to eq(true)
102
+
103
+ @dog.example_failed(@failed)
104
+ expect(@dog.example_running).to eq(false)
105
+ end
106
+
107
+ it 'increments the "failed" count' do
108
+ expect(@dog.failed_count).to eql(0)
109
+
110
+ @dog.example_started(@notification)
111
+ @dog.example_failed(@failed)
112
+ expect(@dog.failed_count).to eql(1)
113
+
114
+ @dog.example_started(@notification)
115
+ @dog.example_failed(@failed)
116
+ expect(@dog.failed_count).to eql(2)
117
+ end
118
+
119
+ it 'logs the failure' do
120
+ @dog.example_started(@notification)
121
+ @dog.example_failed(@failed)
122
+
123
+ expect(@bork.string).to include("[1/#{@notification.count}]")
124
+ expect(@bork.string).to include('FAILED')
125
+ expect(@bork.string).to include(@example_description)
126
+ end
127
+ end # "context '#example_failed' do"
128
+
129
+ context '#example_pending' do
130
+ before :each do
131
+ @dog.start(@notification)
132
+ @pending = double('Pending test', example: @example)
133
+ end
134
+
135
+ it 'notes an example is no longer running' do
136
+ expect(@dog.example_running).to eq(false)
137
+
138
+ @dog.example_started(@notification)
139
+ expect(@dog.example_running).to eq(true)
140
+
141
+ @dog.example_pending(@pending)
142
+ expect(@dog.example_running).to eq(false)
143
+ end
144
+
145
+ it 'increments the "pending" count' do
146
+ expect(@dog.pending_count).to eql(0)
147
+
148
+ @dog.example_started(@notification)
149
+ @dog.example_pending(@pending)
150
+ expect(@dog.pending_count).to eql(1)
151
+
152
+ @dog.example_started(@notification)
153
+ @dog.example_pending(@pending)
154
+ expect(@dog.pending_count).to eql(2)
155
+ end
156
+
157
+ it 'logs the custom message' do
158
+ @dog.example_started(@notification)
159
+ @dog.example_pending(@pending)
160
+
161
+ expect(@bork.string).to include("[1/#{@notification.count}]")
162
+ expect(@bork.string).to include('PENDING')
163
+ expect(@bork.string).to include(@pending_message)
164
+ expect(@bork.string).to include(@example_description)
165
+ end
166
+ end # "context '#example_pending' do"
167
+ end # "context 'individual examples' do"
168
+
169
+ context 'example groups' do
170
+ before :each do
171
+ @group_description = 'Group description'
172
+ @group_notification = double(
173
+ 'Group notification',
174
+ group: double(
175
+ 'RSpec group',
176
+ description: @group_description
177
+ )
178
+ )
179
+ end
180
+
181
+ context '#example_group_started' do
182
+ it 'increments group level' do
183
+ expect(@dog.group_level).to eql(0)
184
+ @dog.example_group_started(@group_notification)
185
+ expect(@dog.group_level).to eql(1)
186
+ @dog.example_group_started(@group_notification)
187
+ expect(@dog.group_level).to eql(2)
188
+ end
189
+
190
+ it 'outputs an indication of group progress' do
191
+ @dog.example_group_started(@group_notification)
192
+ expect(@bork.string).to include(@group_description)
193
+ end
194
+
195
+ it 'outputs a separator at top level' do
196
+ @dog.example_group_started(@group_notification)
197
+ expect(@bork.string).to start_with("\n")
198
+ end
199
+
200
+ it 'does not output a separator below top level' do
201
+ @dog.example_group_started(@group_notification)
202
+ expect(@bork.string).to start_with("\n")
203
+ @bork.truncate(0)
204
+
205
+ @dog.example_group_started(@group_notification)
206
+ expect(@bork.string).to_not start_with("\n")
207
+ end
208
+ end # "context '#example_group_started' do"
209
+
210
+ context '#example_group_finished' do
211
+ it 'derements group level' do
212
+ @dog.example_group_started(@group_notification)
213
+ @dog.example_group_started(@group_notification)
214
+ expect(@dog.group_level).to eql(2)
215
+ @dog.example_group_finished(@group_notification)
216
+ expect(@dog.group_level).to eql(1)
217
+ @dog.example_group_finished(@group_notification)
218
+ expect(@dog.group_level).to eql(0)
219
+ end
220
+
221
+ it 'does not decrement below zero' do
222
+ expect(@dog.group_level).to eql(0)
223
+ @dog.example_group_finished(@group_notification)
224
+ expect(@dog.group_level).to eql(0)
225
+ end
226
+ end # "context '#example_group_finished' do"
227
+ end # "context 'example groups' do"
228
+
229
+ context '#message' do
230
+ before :each do
231
+ @message = 'A message'
232
+ @message_notification = double(
233
+ 'Message notification',
234
+ message: @message
235
+ )
236
+ end
237
+
238
+ it 'logs directly with no example running' do
239
+ @dog.message(@message_notification)
240
+ expect(@bork.string.strip).to eql(@message)
241
+ end
242
+
243
+ it 'logs directly if an example-start occurs unexpectedly' do
244
+ notification = double('Notification', count: 4)
245
+ @dog.example_started(notification)
246
+ @dog.message(@message_notification)
247
+ @dog.send(:flush_messages)
248
+ expect(@bork.string.strip).to eql(@message)
249
+ end
250
+
251
+ it 'logs in context if an example is running' do
252
+ notification = double('Notification', count: 4)
253
+ @dog.start(notification)
254
+ @dog.example_started(notification)
255
+ @dog.message(@message_notification)
256
+ @dog.send(:flush_messages)
257
+ expect(@bork.string.strip).to start_with('[')
258
+ expect(@bork.string.strip).to end_with(@message)
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,36 @@
1
+ require 'doggo'
2
+
3
+ RSpec.configure do | config |
4
+ config.color = true
5
+ config.tty = true
6
+ config.order = :random
7
+
8
+ config.add_formatter 'Doggo'
9
+
10
+ if ENV['FOR_EXAMPLE']
11
+ config.filter_run_including for_example_output: true
12
+ else
13
+ config.filter_run_excluding for_example_output: true
14
+ end
15
+
16
+ Kernel.srand config.seed
17
+ end
18
+
19
+ def spec_helper_capture_stdout( &block )
20
+ result = ''
21
+
22
+ begin
23
+ old_stdout = $stdout
24
+ $stdout = StringIO.new
25
+
26
+ yield
27
+
28
+ result = $stdout.string
29
+
30
+ ensure
31
+ $stdout = old_stdout
32
+
33
+ end
34
+
35
+ return result
36
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: doggo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - RIP Global
8
+ - Andrew David Hodgkinson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-04-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec-core
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '3.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.7'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.7'
42
+ description: Similar to RSpec -f d, but adds indication of test number and total tests
43
+ on each line
44
+ email:
45
+ - andrew@ripglobal.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - lib/doggo.rb
51
+ - spec/example/doggo_spec.rb
52
+ - spec/internal_spec.rb
53
+ - spec/spec_helper.rb
54
+ homepage: https://ripglobal.com/
55
+ licenses:
56
+ - MIT
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.6.5
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubygems_version: 3.0.3
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: RSpec formatter - documentation, with progress indication
77
+ test_files:
78
+ - spec/spec_helper.rb
79
+ - spec/internal_spec.rb
80
+ - spec/example/doggo_spec.rb