probatio 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+
2
+ #
3
+ # probatio/plug.rb
4
+
5
+
6
+ module Probatio; class << self
7
+
8
+ def plugins; @plugins; end
9
+
10
+ def plug(x, position=:last)
11
+
12
+ @plugins.insert(determine_plugin_pos(position), x)
13
+ @plugouts = nil
14
+ end
15
+
16
+ def unplug(old)
17
+
18
+ i =
19
+ plug_index(old) ||
20
+ fail(ArgumentError.new("Cannot locate plugin to remove"))
21
+
22
+ @plugins.delete_at(i)
23
+ @plugouts = nil
24
+ end
25
+
26
+ def replug(old, new)
27
+
28
+ i =
29
+ plug_index(old) ||
30
+ fail(ArgumentError.new("Cannot locate plugin to replace"))
31
+
32
+ @plugins[i] = new
33
+ @plugouts = nil
34
+ end
35
+
36
+ protected
37
+
38
+ def plugin_index(x)
39
+
40
+ return x \
41
+ if x.is_a?(Integer)
42
+ return @plugins.index { |pl| pl.respond_to?(x) } \
43
+ if x.is_a?(Symbol) || x.is_a?(String)
44
+
45
+ i = @plugins.index(x); return i if i
46
+
47
+ return @plugins.index { |pl| pl.is_a?(x) } if x.is_a?(Module)
48
+
49
+ nil
50
+ end
51
+
52
+ def determine_plugin_pos(pos)
53
+
54
+ return pos if pos.is_a?(Integer)
55
+
56
+ return 0 if pos == :first
57
+ #return @plugins.length if pos == :last
58
+
59
+ h = pos.is_a?(Hash) ? pos : {}
60
+
61
+ l = @plugins.length
62
+
63
+ if af = h[:after]
64
+ (@plugins.index { |pl| pl == af || (pl.is_a?(af) rescue nil) } || l) + 1
65
+ elsif bf = h[:before]
66
+ (@plugins.index { |pl| pl == bf || (pl.is_a?(bf) rescue nil) } || l)
67
+ else
68
+ l # last resort, put at the end...
69
+ end
70
+ end
71
+ end; end
72
+
@@ -0,0 +1,253 @@
1
+
2
+ #
3
+ # probatio/plugins.rb
4
+
5
+ module Probatio::Colours
6
+
7
+ protected
8
+
9
+ def c; Probatio.c; end # colours or not...
10
+ end
11
+
12
+ class Probatio::Recorder
13
+
14
+ attr_reader :events
15
+
16
+ def record(ev)
17
+
18
+ (@events ||= []) << ev
19
+ end
20
+
21
+ def failures; @events.select { |ev| ev.name == 'test_fail' }; end
22
+ def successes; @events.select { |ev| ev.name == 'test_succeed' }; end
23
+
24
+ def test_leave_event(test_node)
25
+
26
+ @events.find { |e|
27
+ e.name == 'test_leave' &&
28
+ e.node_full_name == test_node.full_name }
29
+ end
30
+
31
+ def total_duration
32
+
33
+ @events.last.tstamp - @events.first.tstamp
34
+ end
35
+
36
+ def failed_tests; @events.select { |e| e.name == 'test_fail' }; end
37
+
38
+ def test_count; @events.count { |e| e.name == 'test_leave' }; end
39
+ def assertion_count; @events.count { |e| e.name == 'assertion_leave' }; end
40
+ def failure_count; @events.count { |e| e.name == 'test_fail' }; end
41
+ def pending_count; @events.count { |e| e.name == 'test_pending' }; end
42
+
43
+ def file_count
44
+
45
+ @events.map(&:path).compact.uniq.count
46
+ end
47
+ end
48
+
49
+ module Probatio
50
+
51
+ class << self
52
+
53
+ def recorder_plugin
54
+
55
+ @plugins.find { |pl| pl.respond_to?(:events) }
56
+ end
57
+ end
58
+ end
59
+
60
+ class Probatio::Chronometer
61
+
62
+ def record(ev)
63
+
64
+ # compute ev.leave_delta if ev is a "leave"
65
+
66
+ if ev.enter?
67
+
68
+ (@enters ||= []) << ev
69
+
70
+ elsif ev.leave?
71
+
72
+ e = @enters.pop
73
+
74
+ fail "ev mismatch #{ev.name} vs #{e.name}" \
75
+ if ( ! e) || (ev.type != e.type)
76
+
77
+ ev.leave_delta = ev.tstamp - e.tstamp
78
+ end
79
+ end
80
+ end
81
+
82
+ module Probatio::SeedReporter
83
+
84
+ def on_start(ev)
85
+
86
+ puts
87
+ puts "Run options: --seed #{Probatio.seed}"
88
+ puts
89
+ end
90
+ end
91
+
92
+ class Probatio::DotReporter
93
+
94
+ include Probatio::Colours
95
+ include Probatio::SeedReporter
96
+
97
+ def on_test_succeed(ev)
98
+
99
+ print c.dark_grey + '·' + c.reset
100
+ end
101
+
102
+ def on_test_fail(ev)
103
+
104
+ print c.red + 'x' + c.reset
105
+ end
106
+
107
+ def on_test_pending(ev)
108
+
109
+ print c.yellow + '.' + c.reset
110
+ end
111
+ end
112
+
113
+ class Probatio::VanillaSummarizer
114
+
115
+ def on_over(ev)
116
+
117
+ c = Probatio.c # colours or not
118
+
119
+ recorder = Probatio.plugins.find { |pl| pl.respond_to?(:failures) }
120
+ return unless recorder
121
+
122
+ if recorder.test_count == 0
123
+ puts c.dark_grey(" ¯\\_(ツ)_/¯")
124
+ else
125
+ puts
126
+ end
127
+
128
+ recorder.failures.each do |ev|
129
+
130
+ #puts
131
+ puts '-' * [ Probatio.term_width, 80 ].min
132
+ #puts ev.leaf.parent.to_s
133
+ #puts ev.leaf.head
134
+ #puts ev.leaf.trail
135
+ puts ev.error.trail
136
+ puts
137
+ #puts "%4d %s" % [ ev.error.line, c.dark_grey(ev.error.source_line) ]
138
+ #puts c.dark_grey(ev.error.path)
139
+ ev.error.source_lines.each do |i, l|
140
+ puts "%4s %s" % [
141
+ i == ev.error.line ? c.underlined(i.to_s) :
142
+ i % 5 == 0 ? c.dark_grey(i.to_s) :
143
+ c.white(i.to_s),
144
+ i == ev.error.line ? c.yellow(l) : c.dark_grey(l) ]
145
+ end
146
+ puts; puts c.dark_grey(ev.error.summary(' '))
147
+ #puts ev.error.inspect
148
+ #puts '.'
149
+ #puts ev.to_s
150
+ #puts
151
+ end
152
+ #puts '-' * 80 if recorder.failures.any?
153
+
154
+ r = Probatio.recorder_plugin
155
+
156
+ d = r.total_duration
157
+
158
+ tc = r.test_count
159
+ ac = r.assertion_count
160
+
161
+ fc = r.failure_count; fc = Probatio.c.red(fc.to_s) if fc > 0
162
+ pc = r.pending_count; pc = Probatio.c.yellow(pc.to_s) if pc > 0
163
+
164
+ tpc = tc / d
165
+ apc = ac / d
166
+
167
+ fic = r.file_count
168
+
169
+ puts
170
+ puts
171
+ print "Finished in #{Probatio.to_time_s(d)}, "
172
+ print "%0.3f tests/s, %0.3f assertions/s." % [ tpc, apc ]
173
+ puts
174
+ puts
175
+ print "#{tc} test#{s(tc)}, #{ac} assertion#{s(ac)}, "
176
+ print "#{fc} failure#{s(fc)}, #{pc} pending, "
177
+ print "#{fic} file#{s(fic)}."
178
+ puts
179
+ puts
180
+ end
181
+
182
+ protected
183
+
184
+ def s(count); count == 1 ? '' : 's'; end
185
+ end
186
+
187
+ class Probatio::ProbaOutputter
188
+
189
+ require 'rbconfig'
190
+
191
+ def on_over(ev)
192
+
193
+ # TODO unplug if --mute or some switch like that...
194
+ r = Probatio.recorder_plugin
195
+
196
+ flh = r.failed_tests.collect(&:to_h).each { |h| h.delete(:n) }
197
+ fls = Cerata.table_to_s(flh, ' ')
198
+
199
+ rb = {}
200
+ #
201
+ rv =
202
+ File.exist?('.ruby-version') &&
203
+ File.readlines('.ruby-version').find { |l| ! l.strip.start_with?('#') }
204
+ #
205
+ rb[:v] = ".ruby-version:#{rv.strip}" if rv
206
+ rb[:p] = File.join(
207
+ RbConfig::CONFIG['bindir'],
208
+ RbConfig::CONFIG['ruby_install_name'])
209
+ rb[:d] = RUBY_DESCRIPTION
210
+ rb[:l] = RUBY_PATCHLEVEL
211
+ #
212
+ #rb = Cerata.horizontal_h_to_s(rb)
213
+ rb = Cerata.vertical_h_to_s(rb, ' ')
214
+
215
+ env = Cerata.vertical_h_to_s(
216
+ ENV.filter { |k, _|
217
+ k.match?(/^(RUBY_|GEM_|(HOME|PATH|USER|SHELL|PWD)$)/) },
218
+ ' ')
219
+
220
+ File.open(Probatio.opath, 'wb') do |o|
221
+ o << '# ' << Probatio.opath << "\n"
222
+ o << "{\n"
223
+ o << "argv: " << Cerata.horizontal_a_to_s(ARGV) << ",\n"
224
+ o << "failures:\n"
225
+ #o << " [\n"
226
+ #fls.each { |fl| o << ' ' << fl << ",\n" }
227
+ #o << " ],\n"
228
+ o << fls << ",\n"
229
+ o << "duration: #{Probatio.to_time_s(r.total_duration).inspect},\n"
230
+ o << "probatio: { v: #{Probatio::VERSION.inspect} },\n"
231
+ o << "ruby:\n#{rb},\n"
232
+ o << "some_env:\n#{env},\n"
233
+ o << "}\n"
234
+ end
235
+ end
236
+ end
237
+
238
+ class Probatio::Exitter
239
+
240
+ def on_exit(ev)
241
+
242
+ exit 1 if Probatio.recorder_plugin.failure_count > 0
243
+ exit 0
244
+ end
245
+ end
246
+
247
+ Probatio.plug(Probatio::Recorder.new)
248
+ Probatio.plug(Probatio::Chronometer.new)
249
+ Probatio.plug(Probatio::DotReporter.new)
250
+ Probatio.plug(Probatio::VanillaSummarizer.new)
251
+ Probatio.plug(Probatio::ProbaOutputter.new)
252
+ Probatio.plug(Probatio::Exitter.new)
253
+
@@ -0,0 +1,44 @@
1
+
2
+ #
3
+ # probatio/waiters.rb
4
+
5
+ module Probatio::Waiters
6
+
7
+ def wait_until(opts={}, &block)
8
+
9
+ timeout = opts[:timeout] || 14
10
+ frequency = opts[:frequency] || 0.1
11
+
12
+ start = Probatio.monow
13
+
14
+ loop do
15
+
16
+ sleep(frequency)
17
+
18
+ #return if block.call == true
19
+ r = block.call
20
+ return r if r
21
+
22
+ break if Probatio.monow - start > timeout
23
+ end
24
+
25
+ fail "timeout after #{timeout}s"
26
+ end
27
+ alias wait_for wait_until
28
+
29
+ def monow
30
+
31
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
32
+ end
33
+ end
34
+
35
+ class Probatio::Section
36
+
37
+ include Probatio::Waiters
38
+ end
39
+
40
+ class Probatio::Context
41
+
42
+ include Probatio::Waiters
43
+ end
44
+