test_bench-session 2.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 (41) hide show
  1. checksums.yaml +7 -0
  2. data/lib/test_bench/session/controls/capture_sink/event.rb +9 -0
  3. data/lib/test_bench/session/controls/capture_sink/path.rb +30 -0
  4. data/lib/test_bench/session/controls/capture_sink/record.rb +19 -0
  5. data/lib/test_bench/session/controls/comment.rb +16 -0
  6. data/lib/test_bench/session/controls/detail.rb +16 -0
  7. data/lib/test_bench/session/controls/events/aborted.rb +29 -0
  8. data/lib/test_bench/session/controls/events/commented.rb +29 -0
  9. data/lib/test_bench/session/controls/events/context_finished.rb +32 -0
  10. data/lib/test_bench/session/controls/events/context_skipped.rb +29 -0
  11. data/lib/test_bench/session/controls/events/context_started.rb +29 -0
  12. data/lib/test_bench/session/controls/events/detailed.rb +29 -0
  13. data/lib/test_bench/session/controls/events/failed.rb +35 -0
  14. data/lib/test_bench/session/controls/events/file_finished.rb +32 -0
  15. data/lib/test_bench/session/controls/events/file_started.rb +29 -0
  16. data/lib/test_bench/session/controls/events/finished.rb +32 -0
  17. data/lib/test_bench/session/controls/events/fixture_finished.rb +32 -0
  18. data/lib/test_bench/session/controls/events/fixture_started.rb +29 -0
  19. data/lib/test_bench/session/controls/events/started.rb +29 -0
  20. data/lib/test_bench/session/controls/events/test_finished.rb +32 -0
  21. data/lib/test_bench/session/controls/events/test_skipped.rb +29 -0
  22. data/lib/test_bench/session/controls/events/test_started.rb +29 -0
  23. data/lib/test_bench/session/controls/events.rb +27 -0
  24. data/lib/test_bench/session/controls/exception.rb +27 -0
  25. data/lib/test_bench/session/controls/failure.rb +30 -0
  26. data/lib/test_bench/session/controls/file.rb +58 -0
  27. data/lib/test_bench/session/controls/fixture.rb +16 -0
  28. data/lib/test_bench/session/controls/process_id.rb +7 -0
  29. data/lib/test_bench/session/controls/random.rb +7 -0
  30. data/lib/test_bench/session/controls/result.rb +12 -0
  31. data/lib/test_bench/session/controls/time.rb +7 -0
  32. data/lib/test_bench/session/controls/title.rb +27 -0
  33. data/lib/test_bench/session/controls.rb +36 -0
  34. data/lib/test_bench/session/events.rb +32 -0
  35. data/lib/test_bench/session/session.rb +232 -0
  36. data/lib/test_bench/session/substitute.rb +93 -0
  37. data/lib/test_bench/session/telemetry/capture_sink/path.rb +65 -0
  38. data/lib/test_bench/session/telemetry/capture_sink/record.rb +39 -0
  39. data/lib/test_bench/session/telemetry/capture_sink.rb +63 -0
  40. data/lib/test_bench/session.rb +11 -0
  41. metadata +109 -0
@@ -0,0 +1,30 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ module Failure
5
+ module Message
6
+ def self.example(suffix=nil)
7
+ suffix = " #{suffix}" if not suffix.nil?
8
+
9
+ "Some failure message#{suffix}"
10
+ end
11
+ def self.random = example(Controls::Random.string)
12
+ end
13
+
14
+ module Path
15
+ def self.example(suffix=nil)
16
+ suffix = "_#{suffix}" if not suffix.nil?
17
+
18
+ "path/to/some_file#{suffix}.rb"
19
+ end
20
+ def self.random = example(Controls::Random.string)
21
+ end
22
+
23
+ module LineNumber
24
+ def self.example = 11
25
+ def self.random = Controls::Random.integer % 1111
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,58 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ module File
5
+ def self.example(contents=nil)
6
+ contents ||= self.contents
7
+
8
+ path = TestBench::Telemetry::Controls::File::Temporary.example
9
+
10
+ ::File.write(path, contents)
11
+
12
+ path
13
+ end
14
+
15
+ def self.contents = Pass.contents
16
+
17
+ module Failure
18
+ def self.example(session: nil)
19
+ contents = contents(session:)
20
+
21
+ File.example(contents)
22
+ end
23
+
24
+ def self.contents(session: nil)
25
+ session ||= Session.new
26
+
27
+ <<~RUBY
28
+ session = ObjectSpace._id2ref(#{session.object_id})
29
+ session.assert(false, __FILE__, __LINE__)
30
+ RUBY
31
+ end
32
+ end
33
+
34
+ module Pass
35
+ def self.example
36
+ File.example(contents)
37
+ end
38
+
39
+ def self.contents
40
+ ''
41
+ end
42
+ end
43
+
44
+ module Path
45
+ def self.example(suffix=nil)
46
+ extension = '.rb'
47
+
48
+ filename = TestBench::Telemetry::Controls::File::Name.example(suffix, extension:)
49
+
50
+ ::File.join('some_dir', 'some_other_dir', filename)
51
+ end
52
+
53
+ def self.random = example(Random.string)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,16 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ module Fixture
5
+ module Name
6
+ def self.example(suffix=nil)
7
+ suffix = "_#{suffix}" if not suffix.nil?
8
+
9
+ "SomeNamespace::SomeFixture#{suffix}"
10
+ end
11
+ def self.random = example(Random.string)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ ProcessID = TestBench::Telemetry::Controls::ProcessID
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ Random = TestBench::Telemetry::Controls::Random
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ module Result
5
+ def self.example = pass
6
+ def self.pass = true
7
+ def self.failure = false
8
+ def self.random = Random.boolean
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ Time = TestBench::Telemetry::Controls::Time
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module TestBench
2
+ class Session
3
+ module Controls
4
+ module Title
5
+ module Test
6
+ def self.example(suffix=nil)
7
+ suffix = " #{suffix}" if not suffix.nil?
8
+
9
+ "Some test#{suffix}"
10
+ end
11
+ def self.other_example = "Some other test"
12
+ def self.random = example(Random.string)
13
+ end
14
+
15
+ module Context
16
+ def self.example(suffix=nil)
17
+ suffix = " #{suffix}" if not suffix.nil?
18
+
19
+ "Some Context#{suffix}"
20
+ end
21
+ def self.other_example = "Some Other Context"
22
+ def self.random = example(Random.string)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_bench/telemetry/controls'
2
+
3
+ require 'test_bench/session/controls/random'
4
+ require 'test_bench/session/controls/time'
5
+ require 'test_bench/session/controls/process_id'
6
+ require 'test_bench/session/controls/result'
7
+ require 'test_bench/session/controls/exception'
8
+
9
+ require 'test_bench/session/controls/failure'
10
+ require 'test_bench/session/controls/title'
11
+ require 'test_bench/session/controls/comment'
12
+ require 'test_bench/session/controls/detail'
13
+ require 'test_bench/session/controls/fixture'
14
+ require 'test_bench/session/controls/file'
15
+
16
+ require 'test_bench/session/controls/events/failed'
17
+ require 'test_bench/session/controls/events/test_started'
18
+ require 'test_bench/session/controls/events/test_finished'
19
+ require 'test_bench/session/controls/events/test_skipped'
20
+ require 'test_bench/session/controls/events/context_started'
21
+ require 'test_bench/session/controls/events/context_finished'
22
+ require 'test_bench/session/controls/events/context_skipped'
23
+ require 'test_bench/session/controls/events/commented'
24
+ require 'test_bench/session/controls/events/detailed'
25
+ require 'test_bench/session/controls/events/fixture_started'
26
+ require 'test_bench/session/controls/events/fixture_finished'
27
+ require 'test_bench/session/controls/events/file_started'
28
+ require 'test_bench/session/controls/events/file_finished'
29
+ require 'test_bench/session/controls/events/started'
30
+ require 'test_bench/session/controls/events/aborted'
31
+ require 'test_bench/session/controls/events/finished'
32
+ require 'test_bench/session/controls/events'
33
+
34
+ require 'test_bench/session/controls/capture_sink/path'
35
+ require 'test_bench/session/controls/capture_sink/event'
36
+ require 'test_bench/session/controls/capture_sink/record'
@@ -0,0 +1,32 @@
1
+ module TestBench
2
+ class Session
3
+ module Events
4
+ def self.each_type(&block)
5
+ constants(false).each(&block)
6
+ end
7
+
8
+ Failed = TestBench::Telemetry::Event.define(:message, :path, :line_number)
9
+
10
+ TestStarted = TestBench::Telemetry::Event.define(:title)
11
+ TestFinished = TestBench::Telemetry::Event.define(:title, :result)
12
+ TestSkipped = TestBench::Telemetry::Event.define(:title)
13
+
14
+ ContextStarted = TestBench::Telemetry::Event.define(:title)
15
+ ContextFinished = TestBench::Telemetry::Event.define(:title, :result)
16
+ ContextSkipped = TestBench::Telemetry::Event.define(:title)
17
+
18
+ Commented = TestBench::Telemetry::Event.define(:text)
19
+ Detailed = TestBench::Telemetry::Event.define(:text)
20
+
21
+ FixtureStarted = TestBench::Telemetry::Event.define(:name)
22
+ FixtureFinished = TestBench::Telemetry::Event.define(:name, :result)
23
+
24
+ FileStarted = TestBench::Telemetry::Event.define(:path)
25
+ FileFinished = TestBench::Telemetry::Event.define(:path, :result)
26
+
27
+ Started = TestBench::Telemetry::Event.define(:process_count)
28
+ Aborted = TestBench::Telemetry::Event.define(:abort_process_id)
29
+ Finished = TestBench::Telemetry::Event.define(:result, :process_count)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,232 @@
1
+ module TestBench
2
+ class Session
3
+ Failure = Class.new(RuntimeError)
4
+ Abort = Class.new(Failure)
5
+
6
+ def telemetry
7
+ @telemetry ||= TestBench::Telemetry::Substitute.build
8
+ end
9
+ attr_writer :telemetry
10
+
11
+ def failure_sequence
12
+ @failure_sequence ||= 0
13
+ end
14
+ attr_writer :failure_sequence
15
+
16
+ def assertion_sequence
17
+ @assertion_sequence ||= 0
18
+ end
19
+ attr_writer :assertion_sequence
20
+
21
+ def skip_sequence
22
+ @skip_sequence ||= 0
23
+ end
24
+ attr_writer :skip_sequence
25
+
26
+ def self.build(*sinks)
27
+ instance = new
28
+ TestBench::Telemetry.configure(instance, *sinks)
29
+ instance
30
+ end
31
+
32
+ def self.configure(receiver, *sinks, attr_name: nil)
33
+ attr_name ||= :test_session
34
+
35
+ instance = build(*sinks)
36
+ receiver.public_send(:"#{attr_name}=", instance)
37
+ end
38
+
39
+ def start(process_count)
40
+ telemetry.record(Events::Started.new(process_count))
41
+ end
42
+
43
+ def abort(abort_process_id)
44
+ record_failure
45
+
46
+ telemetry.record(Events::Aborted.new(abort_process_id))
47
+ end
48
+
49
+ def finish(process_count)
50
+ result = !failed?
51
+
52
+ telemetry.record(Events::Finished.new(result, process_count))
53
+ end
54
+
55
+ def file(path)
56
+ original_failure_sequence = failure_sequence
57
+
58
+ telemetry.record(Events::FileStarted.new(path))
59
+
60
+ source = File.read(path)
61
+
62
+ begin
63
+ TOPLEVEL_BINDING.eval(source, path)
64
+ rescue Failure
65
+ end
66
+
67
+ result = !failed?(original_failure_sequence)
68
+
69
+ telemetry.record(Events::FileFinished.new(path, result))
70
+
71
+ result
72
+ end
73
+
74
+ def fixture(name, &block)
75
+ original_failure_sequence = failure_sequence
76
+
77
+ telemetry.record(Events::FixtureStarted.new(name))
78
+
79
+ begin
80
+ block.()
81
+ rescue Failure
82
+ end
83
+
84
+ result = !failed?(original_failure_sequence)
85
+
86
+ telemetry.record(Events::FixtureFinished.new(name, result))
87
+
88
+ result
89
+ end
90
+
91
+ def detail(text)
92
+ telemetry.record(Events::Detailed.new(text))
93
+ end
94
+
95
+ def comment(comment)
96
+ telemetry.record(Events::Commented.new(comment))
97
+ end
98
+
99
+ def context!(...)
100
+ if context(...) == false
101
+ message = Session.abort_message
102
+ raise Abort, message
103
+ end
104
+ end
105
+
106
+ def context(title=nil, &block)
107
+ if block.nil?
108
+ telemetry.record(Events::ContextSkipped.new(title))
109
+ return
110
+ end
111
+
112
+ original_failure_sequence = failure_sequence
113
+
114
+ telemetry.record(Events::ContextStarted.new(title))
115
+
116
+ begin
117
+ block.()
118
+
119
+ rescue Failure
120
+
121
+ ensure
122
+ result = !failed?(original_failure_sequence)
123
+
124
+ telemetry.record(Events::ContextFinished.new(title, result))
125
+ end
126
+
127
+ result
128
+ end
129
+
130
+ def test!(...)
131
+ if test(...) == false
132
+ message = Session.abort_message
133
+ raise Abort, message
134
+ end
135
+ end
136
+
137
+ def test(path, line_number, title=nil, &block)
138
+ if block.nil?
139
+ telemetry.record(Events::TestSkipped.new(title))
140
+ return
141
+ end
142
+
143
+ original_failure_sequence = failure_sequence
144
+ original_assertion_sequence = assertion_sequence
145
+
146
+ telemetry.record(Events::TestStarted.new(title))
147
+
148
+ begin
149
+ block.()
150
+
151
+ result = !failed?(original_failure_sequence)
152
+
153
+ if result
154
+ if not asserted?(original_assertion_sequence)
155
+ failure_message = Session.no_assertion_message
156
+ fail(failure_message, path, line_number)
157
+ end
158
+ end
159
+
160
+ rescue Failure
161
+ result = false
162
+
163
+ ensure
164
+ telemetry.record(Events::TestFinished.new(title, result))
165
+ end
166
+
167
+ result
168
+ end
169
+
170
+ def assert(result, path, line_number)
171
+ failure_message = Session.assertion_failure_message
172
+
173
+ if result != true && result != false
174
+ raise TypeError, "Value #{result.inspect} isn't a boolean"
175
+ end
176
+
177
+ record_assertion
178
+
179
+ if result == false
180
+ fail(failure_message, path, line_number)
181
+ end
182
+ end
183
+
184
+ def fail(message, path, line_number)
185
+ record_failure
186
+
187
+ telemetry.record(Events::Failed.new(message, path, line_number))
188
+
189
+ raise Failure, message
190
+ end
191
+
192
+ def asserted?(compare_sequence=nil)
193
+ compare_sequence ||= 0
194
+
195
+ compare_sequence != assertion_sequence
196
+ end
197
+
198
+ def record_assertion
199
+ self.assertion_sequence += 1
200
+ end
201
+
202
+ def failed?(compare_sequence=nil)
203
+ compare_sequence ||= 0
204
+
205
+ compare_sequence != failure_sequence
206
+ end
207
+
208
+ def record_failure
209
+ self.failure_sequence += 1
210
+ end
211
+
212
+ def skipped?
213
+ skip_sequence != 0
214
+ end
215
+
216
+ def record_skip
217
+ self.skip_sequence += 1
218
+ end
219
+
220
+ def self.assertion_failure_message
221
+ "Assertion failed"
222
+ end
223
+
224
+ def self.no_assertion_message
225
+ "Test didn't perform an assertion"
226
+ end
227
+
228
+ def self.abort_message
229
+ "Abort"
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,93 @@
1
+ module TestBench
2
+ class Session
3
+ module Substitute
4
+ def self.build
5
+ Session.build
6
+ end
7
+
8
+ class Session < Session
9
+ attr_accessor :result
10
+
11
+ def self.build
12
+ instance = new
13
+
14
+ telemetry = instance.telemetry
15
+ Telemetry::CaptureSink.configure(telemetry, attr_name: :sink)
16
+
17
+ telemetry.register(telemetry.sink)
18
+
19
+ instance
20
+ end
21
+
22
+ def file(path)
23
+ telemetry.record(Events::FileStarted.new(path))
24
+
25
+ telemetry.record(Events::FileFinished.new(path, result))
26
+
27
+ result
28
+ end
29
+
30
+ Events.each_type do |event_type|
31
+ event_type_method_cased = TestBench::Telemetry::Event::Type.method_cased(event_type)
32
+
33
+ event_class = Events.const_get(event_type, false)
34
+
35
+ module_eval(<<~RUBY, __FILE__, __LINE__)
36
+ def one_#{event_type_method_cased}_event?(...)
37
+ one_event?(#{event_class}, ...)
38
+ end
39
+
40
+ def one_#{event_type_method_cased}_event(...)
41
+ one_event(#{event_class}, ...)
42
+ end
43
+
44
+ def any_#{event_type_method_cased}_event?(...)
45
+ any_event?(#{event_class}, ...)
46
+ end
47
+ alias :#{event_type_method_cased}_event? :any_#{event_type_method_cased}_event?
48
+
49
+ def #{event_type_method_cased}_events(...)
50
+ events(#{event_class}, ...)
51
+ end
52
+ RUBY
53
+ end
54
+
55
+ def one_event?(...) = telemetry.one_event?(...)
56
+ def one_event(...) = telemetry.one_event(...)
57
+ def any_event?(...) = telemetry.any_event?(...)
58
+ alias :event? :any_event?
59
+ def events(...) = telemetry.events(...)
60
+
61
+ alias :failure? :failed_event?
62
+ alias :one_failure? :one_failed_event?
63
+
64
+ alias :test? :test_finished_event?
65
+ alias :one_test? :one_test_finished_event?
66
+
67
+ alias :context? :context_finished_event?
68
+ alias :one_context? :one_context_finished_event?
69
+
70
+ alias :comment? :commented_event?
71
+ alias :one_comment? :one_commented_event?
72
+
73
+ alias :detail? :detailed_event?
74
+ alias :one_detail? :one_detailed_event?
75
+
76
+ alias :fixture? :fixture_finished_event?
77
+ alias :one_fixture? :one_fixture_finished_event?
78
+
79
+ alias :file? :file_finished_event?
80
+ alias :one_file? :one_file_finished_event?
81
+
82
+ alias :started? :started_event?
83
+ alias :one_started? :one_started_event?
84
+
85
+ alias :finished? :finished_event?
86
+ alias :one_finished? :one_finished_event?
87
+
88
+ alias :aborted? :aborted_event?
89
+ alias :one_aborted? :one_aborted_event?
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,65 @@
1
+ module TestBench
2
+ class Session
3
+ module Telemetry
4
+ class CaptureSink
5
+ class Path
6
+ def segments
7
+ @segments ||= []
8
+ end
9
+ attr_writer :segments
10
+
11
+ def match?(*segments, segment)
12
+ if not segment == self.segments.last
13
+ return false
14
+ end
15
+
16
+ segment_iterator = self.segments.to_enum
17
+
18
+ control_segments = [*segments, segment]
19
+
20
+ control_segments.all? do |control_segment|
21
+ begin
22
+ next_segment = segment_iterator.next
23
+ end until next_segment == control_segment
24
+ true
25
+
26
+ rescue StopIteration
27
+ false
28
+ end
29
+ end
30
+
31
+ def push_segment(segment)
32
+ segments << segment
33
+ end
34
+ alias :push :push_segment
35
+ alias :<< :push
36
+
37
+ def pop_segment(compare_segment=nil)
38
+ segments.pop
39
+ end
40
+ alias :pop :pop_segment
41
+
42
+ def copy(receiver)
43
+ path = self.class.new
44
+
45
+ segments.each do |segment|
46
+ path << segment
47
+ end
48
+
49
+ receiver.path = path
50
+ path
51
+ end
52
+
53
+ def eql?(compare)
54
+ if compare.is_a?(self.class)
55
+ segments == compare.segments
56
+ else
57
+ false
58
+ end
59
+ end
60
+ alias :== :eql?
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,39 @@
1
+ module TestBench
2
+ class Session
3
+ module Telemetry
4
+ class CaptureSink
5
+ Record = Struct.new(:event, :path) do
6
+ def match?(*path_segments, &block)
7
+ if not path_segments?(*path_segments)
8
+ false
9
+ elsif not block?(&block)
10
+ false
11
+ else
12
+ true
13
+ end
14
+ end
15
+
16
+ def path_segments_match?(*segments)
17
+ if segments.empty?
18
+ true
19
+ else
20
+ path.match?(*segments)
21
+ end
22
+ end
23
+ alias :path_segments? :path_segments_match?
24
+
25
+ def block_match?(&block)
26
+ if block.nil?
27
+ true
28
+ elsif block.(event.event_type, *event.values)
29
+ true
30
+ else
31
+ false
32
+ end
33
+ end
34
+ alias :block? :block_match?
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end