test_bench 1.0.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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/lib/test_bench.rb +37 -0
  3. data/lib/test_bench/cli.rb +43 -0
  4. data/lib/test_bench/cli/parse_arguments.rb +168 -0
  5. data/lib/test_bench/controls.rb +22 -0
  6. data/lib/test_bench/controls/caller_location.rb +5 -0
  7. data/lib/test_bench/controls/depth.rb +21 -0
  8. data/lib/test_bench/controls/device.rb +27 -0
  9. data/lib/test_bench/controls/directory.rb +15 -0
  10. data/lib/test_bench/controls/error.rb +35 -0
  11. data/lib/test_bench/controls/fixture.rb +29 -0
  12. data/lib/test_bench/controls/output/escape_code.rb +23 -0
  13. data/lib/test_bench/controls/output/newline_character.rb +11 -0
  14. data/lib/test_bench/controls/output/print_error.rb +19 -0
  15. data/lib/test_bench/controls/output/styling.rb +29 -0
  16. data/lib/test_bench/controls/output/summary/error.rb +44 -0
  17. data/lib/test_bench/controls/output/summary/run.rb +59 -0
  18. data/lib/test_bench/controls/path.rb +15 -0
  19. data/lib/test_bench/controls/pattern.rb +29 -0
  20. data/lib/test_bench/controls/result.rb +5 -0
  21. data/lib/test_bench/controls/test_file.rb +5 -0
  22. data/lib/test_bench/controls/time.rb +61 -0
  23. data/lib/test_bench/deactivation_variants.rb +21 -0
  24. data/lib/test_bench/environment/boolean.rb +40 -0
  25. data/lib/test_bench/fixtures.rb +3 -0
  26. data/lib/test_bench/fixtures/configure_receiver.rb +80 -0
  27. data/lib/test_bench/output.rb +9 -0
  28. data/lib/test_bench/output/build.rb +57 -0
  29. data/lib/test_bench/output/levels/debug.rb +229 -0
  30. data/lib/test_bench/output/levels/failure.rb +31 -0
  31. data/lib/test_bench/output/levels/none.rb +13 -0
  32. data/lib/test_bench/output/levels/pass.rb +274 -0
  33. data/lib/test_bench/output/levels/summary.rb +21 -0
  34. data/lib/test_bench/output/print_error.rb +163 -0
  35. data/lib/test_bench/output/summary/error.rb +77 -0
  36. data/lib/test_bench/output/summary/run.rb +102 -0
  37. data/lib/test_bench/output/summary/run/print.rb +98 -0
  38. data/lib/test_bench/output/timer.rb +75 -0
  39. data/lib/test_bench/output/timer/substitute.rb +45 -0
  40. data/lib/test_bench/output/writer.rb +192 -0
  41. data/lib/test_bench/output/writer/dependency.rb +12 -0
  42. data/lib/test_bench/output/writer/sgr.rb +54 -0
  43. data/lib/test_bench/output/writer/substitute.rb +38 -0
  44. data/lib/test_bench/run.rb +103 -0
  45. data/lib/test_bench/run/substitute.rb +36 -0
  46. data/lib/test_bench/test_bench.rb +76 -0
  47. data/script/bench +19 -0
  48. metadata +117 -0
@@ -0,0 +1,9 @@
1
+ module TestBench
2
+ module Output
3
+ def self.build(**args)
4
+ Build.(**args)
5
+ end
6
+
7
+ Substitute = Fixture::Output::Substitute
8
+ end
9
+ end
@@ -0,0 +1,57 @@
1
+ module TestBench
2
+ module Output
3
+ module Build
4
+ Error = Class.new(RuntimeError)
5
+
6
+ def self.call(level: nil, **args)
7
+ level ||= Defaults.level
8
+
9
+ level_setting = level
10
+
11
+ cls = level_class(level_setting)
12
+
13
+ cls.build(**args)
14
+ end
15
+
16
+ def self.level_class(level_setting)
17
+ assure_level(level_setting)
18
+
19
+ levels.fetch(level_setting)
20
+ end
21
+
22
+ def self.levels
23
+ {
24
+ :none => Levels::None,
25
+ :summary => Levels::Summary,
26
+ :failure => Levels::Failure,
27
+ :pass => Levels::Pass,
28
+ :debug => Levels::Debug
29
+ }
30
+ end
31
+
32
+ def self.level_settings
33
+ levels.keys
34
+ end
35
+
36
+ def self.assure_level(level_setting)
37
+ unless level_settings.include?(level_setting)
38
+ raise Error, "Unknown output level #{level_setting.inspect} (Valid levels: #{level_settings.map(&:inspect) * ', '})"
39
+ end
40
+ end
41
+
42
+ module Defaults
43
+ def self.level
44
+ verbose = Environment::Boolean.fetch('VERBOSE')
45
+
46
+ if verbose.nil?
47
+ level_text = ENV.fetch('TEST_BENCH_OUTPUT_LEVEL', 'pass')
48
+
49
+ level_text.to_sym
50
+ else
51
+ :debug
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,229 @@
1
+ module TestBench
2
+ module Output
3
+ module Levels
4
+ class Debug
5
+ include TestBench::Fixture::Output
6
+
7
+ include Writer::Dependency
8
+
9
+ include PrintError
10
+
11
+ include Output::Summary::Error
12
+ include Output::Summary::Run
13
+
14
+ def previous_byte_offset
15
+ @previous_byte_offset ||= 0
16
+ end
17
+ attr_writer :previous_byte_offset
18
+
19
+ def self.build(omit_backtrace_pattern: nil, reverse_backtraces: nil, writer: nil, styling: nil, device: nil)
20
+ instance = new
21
+
22
+ instance.omit_backtrace_pattern = omit_backtrace_pattern unless omit_backtrace_pattern.nil?
23
+ instance.reverse_backtraces = reverse_backtraces unless reverse_backtraces.nil?
24
+
25
+ Writer.configure(instance, writer: writer, styling: styling, device: device)
26
+ Timer.configure(instance)
27
+
28
+ instance
29
+ end
30
+
31
+ def comment(text)
32
+ writer
33
+ .indent
34
+ .text(text)
35
+ .newline
36
+ end
37
+
38
+ def error(error)
39
+ print_error(error)
40
+ end
41
+
42
+ def finish_test(title, result)
43
+ writer.decrease_indentation
44
+
45
+ fg_color = result ? :green : :red
46
+
47
+ writer.indent
48
+
49
+ writer
50
+ .escape_code(fg_color)
51
+ .text("Finished test")
52
+
53
+ unless title.nil?
54
+ writer
55
+ .text(' ')
56
+ .escape_code(:bold)
57
+ .text(title.inspect)
58
+ .escape_code(:reset_intensity)
59
+ end
60
+
61
+ writer
62
+ .text(" (Result: #{result ? 'pass' : 'failure'})")
63
+ .escape_code(:reset_fg)
64
+ .newline
65
+ end
66
+
67
+ def skip_test(title)
68
+ writer.indent
69
+
70
+ writer
71
+ .escape_code(:yellow)
72
+ .text("Skipped test")
73
+
74
+ unless title.nil?
75
+ writer
76
+ .text(' ')
77
+ .escape_code(:bold)
78
+ .text(title.inspect)
79
+ .escape_code(:reset_intensity)
80
+ end
81
+
82
+ writer
83
+ .escape_code(:reset_fg)
84
+ .newline
85
+ end
86
+
87
+ def start_test(title)
88
+ if title.nil?
89
+ text = "Starting test"
90
+ else
91
+ text = "Starting test #{title.inspect}"
92
+ end
93
+
94
+ writer
95
+ .indent
96
+ .escape_code(:cyan)
97
+ .text(text)
98
+ .escape_code(:reset_fg)
99
+ .newline
100
+
101
+ writer.increase_indentation
102
+ end
103
+
104
+ def enter_context(title)
105
+ return if title.nil?
106
+
107
+ writer
108
+ .indent
109
+ .escape_code(:green)
110
+ .text(title)
111
+ .escape_code(:reset_fg)
112
+ .newline
113
+
114
+ writer.increase_indentation
115
+ end
116
+
117
+ def exit_context(title, result)
118
+ return if title.nil?
119
+
120
+ writer.decrease_indentation
121
+
122
+ fg_color = result ? :green : :red
123
+
124
+ text = "Finished context #{title.inspect} (Result: #{result ? 'pass' : 'failure'})"
125
+
126
+ writer
127
+ .indent
128
+ .escape_code(:faint)
129
+ .escape_code(:italic)
130
+ .escape_code(fg_color)
131
+ .text(text)
132
+ .escape_code(:reset_fg)
133
+ .escape_code(:reset_italic)
134
+ .escape_code(:reset_intensity)
135
+ .newline
136
+
137
+ writer.newline if writer.indentation_depth.zero?
138
+ end
139
+
140
+ def skip_context(title)
141
+ return if title.nil?
142
+
143
+ writer
144
+ .indent
145
+ .escape_code(:yellow)
146
+ .text(title)
147
+ .escape_code(:reset_fg)
148
+ .newline
149
+
150
+ writer.newline if writer.indentation_depth.zero?
151
+ end
152
+
153
+ def start_fixture(fixture)
154
+ fixture_class = fixture.class.inspect
155
+
156
+ writer
157
+ .indent
158
+ .escape_code(:blue)
159
+ .text("Starting fixture (Fixture: #{fixture_class})")
160
+ .escape_code(:reset_fg)
161
+ .newline
162
+
163
+ writer.increase_indentation
164
+ end
165
+
166
+ def finish_fixture(fixture, result)
167
+ fixture_class = fixture.class.inspect
168
+
169
+ writer.decrease_indentation
170
+
171
+ writer
172
+ .indent
173
+ .escape_code(:magenta)
174
+ .text("Finished fixture (Fixture: #{fixture_class}, Result: #{result ? 'pass' : 'failure'})")
175
+ .escape_code(:reset_fg)
176
+ .newline
177
+
178
+ writer.newline if writer.indentation_depth.zero?
179
+ end
180
+
181
+ def enter_file(file)
182
+ text = "Running #{file}"
183
+
184
+ writer.text(text).newline
185
+
186
+ self.previous_byte_offset = writer.byte_offset
187
+ end
188
+
189
+ def exit_file(file, _)
190
+ unless writer.byte_offset > previous_byte_offset
191
+ writer
192
+ .escape_code(:faint)
193
+ .text("(Nothing written)")
194
+ .escape_code(:reset_intensity)
195
+ .newline
196
+
197
+ writer.newline
198
+ end
199
+ end
200
+
201
+ def enter_assert_block(caller_location)
202
+ text = "Entered assert block (Caller Location: #{caller_location})"
203
+
204
+ writer
205
+ .indent
206
+ .escape_code(:blue)
207
+ .text(text)
208
+ .escape_code(:reset_fg)
209
+ .newline
210
+
211
+ writer.increase_indentation
212
+ end
213
+
214
+ def exit_assert_block(caller_location, result)
215
+ writer.decrease_indentation
216
+
217
+ text = "Exited assert block (Caller Location: #{caller_location}, Result: #{result ? 'pass' : 'failure'})"
218
+
219
+ writer
220
+ .indent
221
+ .escape_code(:cyan)
222
+ .text(text)
223
+ .escape_code(:reset_fg)
224
+ .newline
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,31 @@
1
+ module TestBench
2
+ module Output
3
+ module Levels
4
+ class Failure
5
+ include TestBench::Fixture::Output
6
+
7
+ include Output::PrintError
8
+ include Output::Summary::Error
9
+
10
+ def self.build(omit_backtrace_pattern: nil, reverse_backtraces: nil, writer: nil, styling: nil, device: nil)
11
+ warn "Warning: #{self} is deprecated. It will remain in the TestBench v2 series, but will be removed from TestBench v3"
12
+
13
+ instance = new
14
+
15
+ instance.omit_backtrace_pattern = omit_backtrace_pattern unless omit_backtrace_pattern.nil?
16
+ instance.reverse_backtraces = reverse_backtraces unless reverse_backtraces.nil?
17
+
18
+ Writer.configure(instance, writer: writer, styling: styling, device: device)
19
+
20
+ instance
21
+ end
22
+
23
+ def error(error)
24
+ print_error(error)
25
+
26
+ writer.newline
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module TestBench
2
+ module Output
3
+ module Levels
4
+ class None < Fixture::Output::Null
5
+ def self.build
6
+ warn "Warning: #{self} is deprecated. It will remain in the TestBench v2 series, but will be removed from TestBench v3"
7
+
8
+ new
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,274 @@
1
+ module TestBench
2
+ module Output
3
+ module Levels
4
+ class Pass
5
+ include TestBench::Fixture::Output
6
+
7
+ include Writer::Dependency
8
+
9
+ include PrintError
10
+
11
+ include Output::Summary::Error
12
+ include Output::Summary::Run
13
+
14
+ attr_accessor :previous_error
15
+
16
+ def previous_byte_offset
17
+ @previous_byte_offset ||= 0
18
+ end
19
+ attr_writer :previous_byte_offset
20
+
21
+ def assert_block_stack
22
+ @assert_block_stack ||= AssertBlockStack.new(writer)
23
+ end
24
+ attr_writer :assert_block_stack
25
+
26
+ def test_stack
27
+ @test_stack ||= []
28
+ end
29
+ attr_writer :test_stack
30
+
31
+ def self.build(omit_backtrace_pattern: nil, reverse_backtraces: nil, writer: nil, styling: nil, device: nil)
32
+ instance = new
33
+
34
+ instance.omit_backtrace_pattern = omit_backtrace_pattern unless omit_backtrace_pattern.nil?
35
+ instance.reverse_backtraces = reverse_backtraces unless reverse_backtraces.nil?
36
+
37
+ Writer.configure(instance, writer: writer, styling: styling, device: device)
38
+ Timer.configure(instance)
39
+
40
+ instance
41
+ end
42
+
43
+ def comment(text)
44
+ writer
45
+ .indent
46
+ .text(text)
47
+ .newline
48
+ end
49
+
50
+ def error(error)
51
+ self.previous_error = error
52
+ end
53
+
54
+ def print_previous_error
55
+ print_error(previous_error)
56
+
57
+ self.previous_error = nil
58
+ end
59
+
60
+ def start_test(_)
61
+ test_stack.push(true)
62
+ end
63
+
64
+ def finish_test(title, result)
65
+ test_stack.pop
66
+
67
+ unless result && title.nil?
68
+ writer.indent
69
+
70
+ writer.escape_code(:bold) unless result
71
+
72
+ fg_color = result ? :green : :red
73
+
74
+ writer
75
+ .escape_code(fg_color)
76
+ .text(title || 'Test')
77
+ .escape_code(:reset_fg)
78
+
79
+ writer.escape_code(:reset_intensity) unless result
80
+
81
+ writer.newline
82
+ end
83
+
84
+ unless previous_error.nil?
85
+ writer.increase_indentation
86
+
87
+ print_previous_error
88
+
89
+ writer.decrease_indentation
90
+ end
91
+
92
+ unless result
93
+ assert_block_stack.print_captured_text
94
+ end
95
+ end
96
+
97
+ def skip_test(title)
98
+ writer.indent
99
+
100
+ writer
101
+ .escape_code(:yellow)
102
+ .text(title || 'Test')
103
+ .escape_code(:reset_fg)
104
+
105
+ writer.newline
106
+ end
107
+
108
+ def enter_context(title)
109
+ test_stack.push(false)
110
+
111
+ return if title.nil?
112
+
113
+ writer
114
+ .indent
115
+ .escape_code(:green)
116
+ .text(title)
117
+ .escape_code(:reset_fg)
118
+ .newline
119
+
120
+ writer.increase_indentation
121
+ end
122
+
123
+ def exit_context(title, result)
124
+ test_stack.pop
125
+
126
+ print_previous_error unless previous_error.nil?
127
+
128
+ unless result
129
+ assert_block_stack.print_captured_text
130
+ end
131
+
132
+ return if title.nil?
133
+
134
+ writer.decrease_indentation
135
+
136
+ writer.newline if writer.indentation_depth.zero?
137
+ end
138
+
139
+ def skip_context(title)
140
+ return if title.nil?
141
+
142
+ writer
143
+ .indent
144
+ .escape_code(:yellow)
145
+ .text(title)
146
+ .escape_code(:reset_fg)
147
+ .newline
148
+
149
+ writer.newline if writer.indentation_depth.zero?
150
+ end
151
+
152
+ def enter_file(file)
153
+ text = "Running #{file}"
154
+
155
+ writer.text(text).newline
156
+
157
+ self.previous_byte_offset = writer.byte_offset
158
+ end
159
+
160
+ def exit_file(file, result)
161
+ print_previous_error unless previous_error.nil?
162
+
163
+ unless result
164
+ assert_block_stack.print_captured_text
165
+ end
166
+
167
+ unless writer.byte_offset > previous_byte_offset
168
+ writer
169
+ .escape_code(:faint)
170
+ .text("(Nothing written)")
171
+ .escape_code(:reset_intensity)
172
+ .newline
173
+
174
+ writer.newline
175
+ end
176
+ end
177
+
178
+ def finish_fixture(_, result)
179
+ print_previous_error unless previous_error.nil?
180
+
181
+ unless result
182
+ assert_block_stack.print_captured_text
183
+ end
184
+ end
185
+
186
+ def enter_assert_block(_)
187
+ inside_test = inside_test?
188
+
189
+ test_stack.push(false)
190
+
191
+ assert_block_stack.push
192
+
193
+ writer.increase_indentation
194
+ writer.increase_indentation if inside_test
195
+ end
196
+
197
+ def exit_assert_block(_, result)
198
+ test_stack.pop
199
+
200
+ print_previous_error unless previous_error.nil?
201
+
202
+ unless result
203
+ assert_block_stack.print_captured_text
204
+ end
205
+
206
+ discard_captured_text = result
207
+
208
+ assert_block_stack.pop(discard_captured_text)
209
+
210
+ writer.decrease_indentation if inside_test?
211
+ writer.decrease_indentation
212
+ end
213
+
214
+ def inside_test?
215
+ test_stack[-1]
216
+ end
217
+
218
+ class AssertBlockStack
219
+ def stack
220
+ @stack ||= []
221
+ end
222
+
223
+ attr_accessor :captured_text
224
+
225
+ attr_reader :writer
226
+
227
+ def initialize(writer)
228
+ @writer = writer
229
+ end
230
+
231
+ def push
232
+ capture_text = String.new
233
+
234
+ previous_device = writer.device
235
+
236
+ writer.device = StringIO.new(capture_text)
237
+
238
+ entry = Entry.new(capture_text, previous_device)
239
+
240
+ stack.push(entry)
241
+
242
+ entry
243
+ end
244
+
245
+ def pop(discard)
246
+ entry = stack.pop
247
+
248
+ writer.device = entry.previous_device
249
+
250
+ unless discard
251
+ self.captured_text = entry.capture_text
252
+ end
253
+
254
+ entry
255
+ end
256
+
257
+ def print_captured_text
258
+ return if captured_text.nil?
259
+
260
+ writer.text(captured_text)
261
+
262
+ self.captured_text = nil
263
+ end
264
+
265
+ def inside_test?
266
+ test_stack[-1]
267
+ end
268
+
269
+ Entry = Struct.new(:capture_text, :previous_device)
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end