doggo 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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