rubytest 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,145 @@
1
+ # encoding: UTF-8
2
+
3
+ module Test::Reporters
4
+
5
+ # Summary Reporter
6
+ class Summary < Abstract
7
+
8
+ #
9
+ SEP = ' '
10
+
11
+ #
12
+ def begin_suite(suite)
13
+ timer_reset
14
+ @tc = []
15
+ end
16
+
17
+ #
18
+ def begin_case(tc)
19
+ @tc << tc.to_s.split("\n").first
20
+ end
21
+
22
+ #
23
+ #def report_instance(instance)
24
+ # puts
25
+ # puts instance #"== #{concern.description}\n\n" unless concern.description.empty?
26
+ # #timer_reset
27
+ #end
28
+
29
+ #
30
+ #def begin_test(test)
31
+ # context = test.context
32
+ # if @instance != context
33
+ # @context = context
34
+ # puts
35
+ # puts " #{context}"
36
+ # puts
37
+ # end
38
+ #end
39
+
40
+ #
41
+ def pass(test)
42
+ print "PASS ".ansi(:green, :bold)
43
+ e = @tc + [test.to_s]
44
+ puts e.join(SEP).ansi(:green)
45
+ end
46
+
47
+ #
48
+ def fail(test, exception)
49
+ print "FAIL ".ansi(:red, :bold)
50
+ e = @tc + [test.to_s]
51
+ puts e.join(SEP).ansi(:red)
52
+ end
53
+
54
+ #
55
+ def error(test, exception)
56
+ print "ERROR ".ansi(:red, :bold)
57
+ e = @tc + [test.to_s]
58
+ puts e.join(SEP).ansi(:red)
59
+ end
60
+
61
+ #
62
+ def todo(test, exception)
63
+ print "TODO ".ansi(:yellow, :bold)
64
+ e = @tc + [test.to_s]
65
+ puts e.join(SEP).ansi(:yellow)
66
+ end
67
+
68
+ #
69
+ def omit(test)
70
+ print "OMIT ".ansi(:cyan, :bold)
71
+ e = @tc + [test.to_s]
72
+ puts e.join(SEP).ansi(:cyan)
73
+ end
74
+
75
+ #
76
+ def skip_test(test)
77
+ print "SKIP ".ansi(:blue, :bold)
78
+ e = @tc + [test.to_s]
79
+ puts e.join(SEP).ansi(:blue)
80
+ end
81
+
82
+ #
83
+ def end_case(test_case)
84
+ @tc.pop
85
+ end
86
+
87
+ #
88
+ def end_suite(suite)
89
+ puts
90
+
91
+ unless record[:pending].empty?
92
+ puts "PENDING:\n\n"
93
+ record[:pending].each do |test, exception|
94
+ puts " #{test}"
95
+ puts " #{file_and_line(exception)}"
96
+ puts
97
+ end
98
+ end
99
+
100
+ unless record[:fail].empty?
101
+ puts "FAILURES:\n\n"
102
+ record[:fail].each do |test, exception|
103
+ puts " #{test}"
104
+ puts " #{file_and_line(exception)}"
105
+ puts " #{exception}"
106
+ puts code(exception).to_s
107
+ #puts " #{exception.backtrace[0]}"
108
+ puts
109
+ end
110
+ end
111
+
112
+ unless record[:error].empty?
113
+ puts "ERRORS:\n\n"
114
+ record[:error].each do |test, exception|
115
+ puts " #{test}"
116
+ puts " #{file_and_line(exception)}"
117
+ puts " #{exception}"
118
+ puts code(exception).to_s
119
+ #puts " #{exception.backtrace[0]}"
120
+ puts
121
+ end
122
+ end
123
+
124
+ puts timestamp
125
+ puts
126
+ puts tally
127
+ end
128
+
129
+ private
130
+
131
+ #
132
+ def timer
133
+ secs = Time.now - @time
134
+ @time = Time.now
135
+ return "%0.5fs" % [secs.to_s]
136
+ end
137
+
138
+ #
139
+ def timer_reset
140
+ @time = Time.now
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+
3
+ module Test::Reporters
4
+
5
+ # Classic TAP Reporter
6
+ #
7
+ # This reporter conforms to v12 of TAP. It could do with some
8
+ # imporvements yet, and eventually upgraded to v13 of standard.
9
+ class Tap < Abstract
10
+
11
+ #
12
+ def begin_suite(suite)
13
+ @start_time = Time.now
14
+ @i = 0
15
+ @n = total_count(suite)
16
+ puts "1..#{@n}"
17
+ end
18
+
19
+ def begin_test(test)
20
+ @i += 1
21
+ end
22
+
23
+ #
24
+ def pass(test)
25
+ puts "ok #{@i} - #{test}"
26
+ end
27
+
28
+ #
29
+ def fail(test, exception)
30
+ puts "not ok #{@i} - #{test}"
31
+ puts " FAIL #{exception.class}"
32
+ puts " #{exception}"
33
+ puts " #{clean_backtrace(exception)[0]}"
34
+ end
35
+
36
+ #
37
+ def error(test, exception)
38
+ puts "not ok #{@i} - #{test}"
39
+ puts " ERROR #{exception.class}"
40
+ puts " #{exception}"
41
+ puts " " + clean_backtrace(exception).join("\n ")
42
+ end
43
+
44
+ #
45
+ def todo(test, exception)
46
+ puts "not ok #{@i} - #{test}"
47
+ puts " PENDING"
48
+ puts " #{clean_backtrace(exception)[1]}"
49
+ end
50
+
51
+ #
52
+ def omit(test, exception)
53
+ puts "ok #{@i} - #{test}"
54
+ puts " OMIT"
55
+ puts " #{clean_backtrace(exception)[1]}"
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+
3
+ module Test::Reporters
4
+
5
+ # TAP-J Reporter
6
+ #
7
+ class Tapj < AbstractHash
8
+
9
+ #
10
+ def initialize(runner)
11
+ require 'json'
12
+ super(runner)
13
+ end
14
+
15
+ #
16
+ def begin_suite(suite)
17
+ puts super(suite).to_json
18
+ end
19
+
20
+ #
21
+ def begin_case(test_case)
22
+ puts super(test_case).to_json
23
+ end
24
+
25
+ #
26
+ def pass(test) #, backtrace=nil)
27
+ puts super(test).to_json
28
+ end
29
+
30
+ #
31
+ def fail(test, exception)
32
+ puts super(test, exception).to_json
33
+ end
34
+
35
+ #
36
+ def error(test, exception)
37
+ puts super(test, exception).to_json
38
+ end
39
+
40
+ #
41
+ def todo(test, exception)
42
+ puts super(test, exception).to_json
43
+ end
44
+
45
+ #
46
+ def end_suite(suite)
47
+ puts super(suite).to_json
48
+ puts "..."
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: UTF-8
2
+
3
+ module Test::Reporters
4
+
5
+ # TAP-Y Reporter
6
+ #
7
+ class Tapy < AbstractHash
8
+
9
+ #
10
+ def initialize(runner)
11
+ require 'json'
12
+ super(runner)
13
+ end
14
+
15
+ #
16
+ def begin_suite(suite)
17
+ puts super(suite).to_yaml
18
+ end
19
+
20
+ #
21
+ def begin_case(test_case)
22
+ puts super(test_case).to_yaml
23
+ end
24
+
25
+ #
26
+ def pass(test) #, backtrace=nil)
27
+ puts super(test).to_yaml
28
+ end
29
+
30
+ #
31
+ def fail(test, exception)
32
+ puts super(test, exception).to_yaml
33
+ end
34
+
35
+ #
36
+ def error(test, exception)
37
+ puts super(test, exception).to_yaml
38
+ end
39
+
40
+ #
41
+ def todo(test, exception)
42
+ puts super(test, exception).to_yaml
43
+ end
44
+
45
+ #
46
+ def omit(test, exception)
47
+ puts super(test, exception).to_yaml
48
+ end
49
+
50
+ #
51
+ def end_suite(suite)
52
+ puts super(suite).to_yaml
53
+ puts "..."
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ module Test::Reporters
4
+
5
+ # Test Reporter is used to test Ruby Test itself.
6
+ #
7
+ class Test < AbstractHash
8
+
9
+ #
10
+ def initialize(runner)
11
+ super(runner)
12
+ end
13
+
14
+ #
15
+ def begin_suite(suite)
16
+ super(suite)
17
+ end
18
+
19
+ #
20
+ def begin_case(test_case)
21
+ super(test_case)
22
+ end
23
+
24
+ #
25
+ def pass(test) #, backtrace=nil)
26
+ super(test)
27
+ end
28
+
29
+ #
30
+ def fail(test, exception)
31
+ super(test, exception)
32
+ end
33
+
34
+ #
35
+ def error(test, exception)
36
+ super(test, exception)
37
+ end
38
+
39
+ #
40
+ def todo(test, exception)
41
+ super(test, exception)
42
+ end
43
+
44
+ #
45
+ def end_suite(suite)
46
+ super(suite)
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,349 @@
1
+ module Test
2
+
3
+ # The Test::Runner class handles the execution of tests.
4
+ #
5
+ class Runner
6
+
7
+ # Default report is in the old "dot-progress" format.
8
+ DEFAULT_FORMAT = 'dotprogress'
9
+
10
+ # Exceptions that are not caught by test runner.
11
+ OPEN_ERRORS = [NoMemoryError, SignalException, Interrupt, SystemExit]
12
+
13
+ # / / / D E F A U L T S / / /
14
+
15
+ # Default test suite ($TEST_SUITE).
16
+ def self.suite
17
+ $TEST_SUITE
18
+ end
19
+
20
+ # Default list of test files to load.
21
+ def self.files
22
+ @files ||= []
23
+ end
24
+
25
+ #
26
+ def self.format
27
+ @format || DEFAULT_FORMAT
28
+ end
29
+
30
+ #
31
+ def self.format=(format)
32
+ @format = format
33
+ end
34
+
35
+ #
36
+ def self.verbose
37
+ @verbose
38
+ end
39
+
40
+ #
41
+ def self.verbose=(boolean)
42
+ @verbose = !!boolean
43
+ end
44
+
45
+ # Default description match for filtering tests.
46
+ def self.match
47
+ @match ||= []
48
+ end
49
+
50
+ # Default selection of tags for filtering tests.
51
+ def self.tags
52
+ @tags ||= []
53
+ end
54
+
55
+ # Default selection of units for filtering tests.
56
+ def self.units
57
+ @unit ||= []
58
+ end
59
+
60
+ #
61
+ def self.hard
62
+ @hard
63
+ end
64
+
65
+ #
66
+ def self.hard=(boolean)
67
+ @hard = !!boolean
68
+ end
69
+
70
+ # / / / A T T R I B U T E S / / /
71
+
72
+ # Test suite to run. This is a list of compliant test units and test cases.
73
+ attr :suite
74
+
75
+ # Test files to load.
76
+ attr :files
77
+
78
+ # Reporter format name, or name fragment, used to look up reporter class.
79
+ attr :format
80
+
81
+ #
82
+ def format=(name)
83
+ @format = name.to_s
84
+ end
85
+
86
+ # Matching text used to filter which tests are run.
87
+ attr :match
88
+
89
+ # Selected tags used to filter which tests are run.
90
+ attr :tags
91
+
92
+ # List of units with which to filter tests. It is an array of strings
93
+ # which are matched against module, class and method names.
94
+ attr :units
95
+
96
+ # Show extra details in reports.
97
+ def verbose?
98
+ @verbose
99
+ end
100
+
101
+ #
102
+ def verbose=(boolean)
103
+ @verbose = !!boolean
104
+ end
105
+
106
+ # Use "hard" test mode?
107
+ def hard?
108
+ @hard
109
+ end
110
+
111
+ #
112
+ def hard=(boolean)
113
+ @hard = !!boolean
114
+ end
115
+
116
+ # New Runner.
117
+ #
118
+ # @param [Array] suite
119
+ # A list of compliant tests/testcases.
120
+ #
121
+ def initialize(options={}, &block)
122
+ @suite = options[:suite] || self.class.suite
123
+ @files = options[:files] || self.class.files
124
+ @format = options[:format] || self.class.format
125
+ @tags = options[:tags] || self.class.tags
126
+ @units = options[:units] || self.class.units
127
+ @match = options[:match] || self.class.match
128
+ @verbose = options[:verbose] || self.class.verbose
129
+ @hard = options[:hard] || self.class.hard
130
+
131
+ block.call(self) if block
132
+ end
133
+
134
+ # The reporter to use for ouput.
135
+ attr :reporter
136
+
137
+ # Record pass, fail, error, pending and omitted tests.
138
+ attr :recorder
139
+
140
+ # Array of observers, typically this just contains the recorder and
141
+ # reporter instances.
142
+ attr :observers
143
+
144
+ # Run test suite.
145
+ #
146
+ # @return [Boolean]
147
+ # That the tests ran without error or failure.
148
+ #
149
+ def run
150
+ ignore_callers
151
+
152
+ files_resolved.each do |file|
153
+ require file
154
+ end
155
+
156
+ @reporter = reporter_load(format)
157
+ @recorder = Recorder.new
158
+ @observers = [@reporter, @recorder]
159
+
160
+ #cd_tmp do
161
+ observers.each{ |o| o.begin_suite(suite) }
162
+ run_thru(suite)
163
+ observers.each{ |o| o.end_suite(suite) }
164
+ #end
165
+
166
+ recorder.success?
167
+ end
168
+
169
+ private
170
+
171
+ # Add to RUBY_IGNORE_CALLERS.
172
+ #
173
+ # @todo Improve on this!
174
+ def ignore_callers
175
+ ignore_path = File.expand_path(File.join(__FILE__, '../../..'))
176
+ ignore_regexp = Regexp.new(Regexp.escape(ignore_path))
177
+
178
+ ::RUBY_IGNORE_CALLERS << ignore_regexp
179
+ ::RUBY_IGNORE_CALLERS << /bin\/rubytest/
180
+ end
181
+
182
+ #
183
+ def run_thru(list)
184
+ list.each do |t|
185
+ if t.respond_to?(:each)
186
+ run_case(t)
187
+ elsif t.respond_to?(:call)
188
+ run_test(t)
189
+ else
190
+ #run_note(t) ?
191
+ end
192
+ end
193
+ end
194
+
195
+ # Run a test case.
196
+ #
197
+ def run_case(tcase)
198
+ if tcase.respond_to?(:skip?) && tcase.skip?
199
+ return observers.each{ |o| o.skip_case(tcase) }
200
+ end
201
+
202
+ observers.each{ |o| o.begin_case(tcase) }
203
+
204
+ if tcase.respond_to?(:call)
205
+ tcase.call do
206
+ run_thru( select(tcase) )
207
+ end
208
+ else
209
+ run_thru( select(tcase) )
210
+ end
211
+
212
+ observers.each{ |o| o.end_case(tcase) }
213
+ end
214
+
215
+ # Run a test.
216
+ #
217
+ # @param [Object] test
218
+ # The test to run, must repsond to #call.
219
+ #
220
+ def run_test(test)
221
+ if test.respond_to?(:skip?) && test.skip?
222
+ return observers.each{ |o| o.skip_test(test) }
223
+ end
224
+
225
+ observers.each{ |o| o.begin_test(test) }
226
+ begin
227
+ success = test.call
228
+ if hard? && !success # TODO: separate run_test method to speed things up?
229
+ raise Assertion, "failure of #{test}"
230
+ else
231
+ observers.each{ |o| o.pass(test) }
232
+ end
233
+ rescue *OPEN_ERRORS => exception
234
+ raise exception
235
+ rescue NotImplementedError => exception
236
+ if exception.assertion?
237
+ observers.each{ |o| o.omit(test, exception) }
238
+ else
239
+ observers.each{ |o| o.todo(test, exception) }
240
+ end
241
+ rescue Exception => exception
242
+ if exception.assertion?
243
+ observers.each{ |o| o.fail(test, exception) }
244
+ else
245
+ observers.each{ |o| o.error(test, exception) }
246
+ end
247
+ end
248
+ observers.each{ |o| o.end_test(test) }
249
+ end
250
+
251
+ # TODO: Make sure this filtering code is correct for the complex
252
+ # condition that that ordered testcases can't have their tests
253
+ # filtered individually (since they may depend on one another).
254
+
255
+ # Filter cases based on selection criteria.
256
+ #
257
+ # @return [Array] selected test cases
258
+ def select(cases)
259
+ selected = []
260
+ if cases.respond_to?(:ordered?) && cases.ordered?
261
+ cases.each do |tc|
262
+ selected << tc
263
+ end
264
+ else
265
+ cases.each do |tc|
266
+ next if tc.respond_to?(:skip?) && tc.skip?
267
+ next if !match.empty? && !match.any?{ |m| m =~ tc.to_s }
268
+
269
+ if !units.empty?
270
+ next unless tc.respond_to?(:unit)
271
+ next unless units.find{ |u| tc.unit.start_with?(u) }
272
+ end
273
+
274
+ if !tags.empty?
275
+ next unless tc.respond_to?(:tags)
276
+ tc_tags = [tc.tags].flatten.map{ |t| t.to_s }
277
+ next if (tags & tc_tags).empty?
278
+ end
279
+
280
+ selected << tc
281
+ end
282
+ end
283
+ selected
284
+ end
285
+
286
+ # Get a reporter instance be name fragment.
287
+ #
288
+ # @return [Reporter::Abstract]
289
+ # The test reporter instance.
290
+ #
291
+ def reporter_load(format)
292
+ format = DEFAULT_REPORT_FORMAT unless format
293
+ format = format.to_s.downcase
294
+ name = reporter_list.find{ |r| /^#{format}/ =~ r }
295
+
296
+ raise "unsupported report format" unless format
297
+
298
+ if RUBY_VERSION < '1.9'
299
+ require "rubytest/reporters/#{name}"
300
+ else
301
+ require_relative "reporters/#{name}"
302
+ end
303
+
304
+ reporter = Test::Reporters.const_get(name.capitalize)
305
+ reporter.new(self)
306
+ end
307
+
308
+ # Returns a list of available report types.
309
+ #
310
+ # @return [Array<String>]
311
+ # The names of available reporters.
312
+ #
313
+ def reporter_list
314
+ list = Dir[File.dirname(__FILE__) + '/reporters/*.rb']
315
+ list = list.map{ |r| File.basename(r).chomp('.rb') }
316
+ list = list.reject{ |r| /^abstract/ =~ r }
317
+ list.sort
318
+ end
319
+
320
+ # Files can be globs and directories which need to be
321
+ # resolved to a list of files.
322
+ #
323
+ def files_resolved
324
+ list = files.flatten
325
+ list = list.map{ |f| Dir[f] }.flatten
326
+ list = list.map{ |f| File.directory?(f) ? Dir[File.join(f, '**/*.rb')] : f }
327
+ list = list.flatten.uniq
328
+ list = list.map{ |f| File.expand_path(f) }
329
+ list
330
+ end
331
+
332
+ =begin
333
+ # TODO ?
334
+ def cd_tmp(&block)
335
+ dir = Test::Config.root + '/tmp'
336
+ if Directory.exist?(dir)
337
+ dir = File.join(dir, 'test')
338
+ FileUtils.mkdir(dir) unless File.exist?(dir)
339
+ else
340
+ dir = File.join(Dir.tmpdir)
341
+ end
342
+
343
+ Dir.chdir(dir, &block)
344
+ end
345
+ =end
346
+
347
+ end
348
+
349
+ end