test_bench 1.0.0.0

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