turn 0.8.2 → 0.9.7
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.
- data/CONTRIBUTING.md +40 -0
- data/History.txt +81 -1
- data/Index.rb +34 -0
- data/LICENSE.txt +21 -0
- data/NOTICE.md +12 -0
- data/README.md +176 -0
- data/Release.txt +21 -1
- data/Version.txt +1 -1
- data/bin/turn +8 -2
- data/lib/turn/autoload.rb +6 -0
- data/lib/turn/autorun.rb +4 -0
- data/lib/turn/bin.rb +8 -2
- data/lib/turn/colorize.rb +50 -19
- data/lib/turn/command.rb +102 -39
- data/lib/turn/components/case.rb +7 -2
- data/lib/turn/components/method.rb +13 -2
- data/lib/turn/components/suite.rb +15 -6
- data/lib/turn/components.rb +4 -0
- data/lib/turn/configuration.rb +271 -0
- data/lib/turn/controller.rb +18 -176
- data/lib/turn/decorators/topten_decorator.rb +67 -0
- data/lib/turn/minitest.rb +25 -0
- data/lib/turn/reporter.rb +75 -13
- data/lib/turn/reporters/cue_reporter.rb +27 -11
- data/lib/turn/reporters/dot_reporter.rb +24 -28
- data/lib/turn/reporters/outline_reporter.rb +76 -39
- data/lib/turn/reporters/pretty_reporter.rb +110 -129
- data/lib/turn/reporters/progress_reporter.rb +70 -33
- data/lib/turn/runners/crossrunner.rb +2 -2
- data/lib/turn/runners/isorunner.rb +12 -10
- data/lib/turn/runners/minirunner.rb +51 -81
- data/lib/turn/runners/solorunner.rb +0 -1
- data/lib/turn/runners/testrunner.rb +12 -15
- data/lib/turn/testunit.rb +24 -0
- data/lib/turn/version.rb +1 -1
- data/lib/turn.rb +10 -15
- data/test/helper.rb +81 -5
- data/test/reporter_test.rb +35 -0
- data/test/test_framework.rb +81 -38
- data/test/test_reporters.rb +14 -14
- data/test/test_runners.rb +57 -19
- data/{demo → try}/test_autorun_minitest.rb +5 -4
- data/{demo → try}/test_autorun_testunit.rb +1 -2
- metadata +135 -112
- data/README.txt +0 -116
- data/Rakefile +0 -39
- data/lib/turn/autorun/minitest.rb +0 -173
- data/lib/turn/autorun/testunit.rb +0 -116
- data/turn.gemspec +0 -49
- /data/{demo → try}/test_counts.rb +0 -0
- /data/{demo → try}/test_sample.rb +0 -0
- /data/{demo → try}/test_sample2.rb +0 -0
data/lib/turn/controller.rb
CHANGED
|
@@ -1,198 +1,45 @@
|
|
|
1
|
-
require 'fileutils'
|
|
2
|
-
|
|
3
1
|
module Turn
|
|
4
|
-
require 'turn/version'
|
|
5
|
-
require 'turn/components/suite.rb'
|
|
6
|
-
require 'turn/components/case.rb'
|
|
7
|
-
require 'turn/components/method.rb'
|
|
8
2
|
|
|
9
|
-
#
|
|
3
|
+
# Controls execution of test run.
|
|
10
4
|
#
|
|
11
|
-
#--
|
|
12
|
-
# TODO: Add support to test run loggging.
|
|
13
|
-
#++
|
|
14
5
|
class Controller
|
|
15
6
|
|
|
16
|
-
# List of if file names or glob pattern of tests to run.
|
|
17
|
-
attr_accessor :tests
|
|
18
|
-
|
|
19
|
-
# List of file names or globs to exclude from +tests+ list.
|
|
20
|
-
attr_accessor :exclude
|
|
21
|
-
|
|
22
|
-
# Regexp pattern that all test name's must
|
|
23
|
-
# match to be eligible to run.
|
|
24
|
-
attr_accessor :pattern
|
|
25
|
-
|
|
26
|
-
# Regexp pattern that all test cases must
|
|
27
|
-
# match to be eligible to run.
|
|
28
|
-
attr_accessor :matchcase
|
|
29
|
-
|
|
30
|
-
# Add these folders to the $LOAD_PATH.
|
|
31
|
-
attr_accessor :loadpath
|
|
32
|
-
|
|
33
|
-
# Libs to require when running tests.
|
|
34
|
-
attr_accessor :requires
|
|
35
|
-
|
|
36
|
-
# Reporter type.
|
|
37
|
-
attr_accessor :format
|
|
38
|
-
|
|
39
|
-
# Run mode.
|
|
40
|
-
attr_accessor :runmode
|
|
41
|
-
|
|
42
|
-
# Test against live install (i.e. Don't use loadpath option)
|
|
43
|
-
attr_accessor :live
|
|
44
|
-
|
|
45
|
-
# Log results? May be true/false or log file name. (TODO)
|
|
46
|
-
attr_accessor :log
|
|
47
|
-
|
|
48
|
-
# Verbose output?
|
|
49
|
-
attr_accessor :verbose
|
|
50
|
-
|
|
51
|
-
# Test framework, either :minitest or :testunit
|
|
52
|
-
attr_accessor :framework
|
|
53
|
-
|
|
54
|
-
def verbose? ; @verbose ; end
|
|
55
|
-
def live? ; @live ; end
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
def initialize
|
|
60
|
-
yield(self) if block_given?
|
|
61
|
-
initialize_defaults
|
|
62
|
-
end
|
|
63
|
-
|
|
64
7
|
#
|
|
65
|
-
def
|
|
66
|
-
@
|
|
67
|
-
@tests ||= ["test/**/{test,}*{,test}.rb"]
|
|
68
|
-
@exclude ||= []
|
|
69
|
-
@requires ||= []
|
|
70
|
-
@live ||= false
|
|
71
|
-
@log ||= true
|
|
72
|
-
#@format ||= nil
|
|
73
|
-
#@runner ||= RUBY_VERSION >= "1.9" ? MiniRunner : TestRunner
|
|
74
|
-
@pattern ||= /.*/
|
|
8
|
+
def initialize(config=Turn.config)
|
|
9
|
+
@config = config
|
|
75
10
|
end
|
|
76
11
|
|
|
77
|
-
# Collect test configuation.
|
|
78
|
-
#def test_configuration(options={})
|
|
79
|
-
# #options = configure_options(options, 'test')
|
|
80
|
-
# #options['loadpath'] ||= metadata.loadpath
|
|
81
|
-
# options['tests'] ||= self.tests
|
|
82
|
-
# options['loadpath'] ||= self.loadpath
|
|
83
|
-
# options['requires'] ||= self.requires
|
|
84
|
-
# options['live'] ||= self.live
|
|
85
|
-
# options['exclude'] ||= self.exclude
|
|
86
|
-
# #options['tests'] = list_option(options['tests'])
|
|
87
|
-
# options['loadpath'] = list_option(options['loadpath'])
|
|
88
|
-
# options['exclude'] = list_option(options['exclude'])
|
|
89
|
-
# options['require'] = list_option(options['require'])
|
|
90
|
-
# return options
|
|
91
|
-
#end
|
|
92
|
-
|
|
93
12
|
#
|
|
94
|
-
|
|
95
|
-
case list
|
|
96
|
-
when nil
|
|
97
|
-
[]
|
|
98
|
-
when Array
|
|
99
|
-
list
|
|
100
|
-
else
|
|
101
|
-
list.split(/[:;]/)
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
public
|
|
106
|
-
|
|
107
|
-
def tests=(paths)
|
|
108
|
-
@tests = list_option(paths)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def loadpath=(paths)
|
|
112
|
-
@loadpath = list_option(paths)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def exclude=(paths)
|
|
116
|
-
@exclude = list_option(paths)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def requires=(paths)
|
|
120
|
-
@requires = list_option(paths)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Test files.
|
|
124
|
-
def files
|
|
125
|
-
@files ||= (
|
|
126
|
-
fs = tests.map do |t|
|
|
127
|
-
File.directory?(t) ? Dir[File.join(t, '**', '*')] : Dir[t]
|
|
128
|
-
end
|
|
129
|
-
fs = fs.flatten.reject{ |f| File.directory?(f) }
|
|
130
|
-
|
|
131
|
-
ex = exclude.map do |x|
|
|
132
|
-
File.directory?(x) ? Dir[File.join(x, '**', '*')] : Dir[x]
|
|
133
|
-
end
|
|
134
|
-
ex = ex.flatten.reject{ |f| File.directory?(f) }
|
|
135
|
-
|
|
136
|
-
(fs - ex).uniq.map{ |f| File.expand_path(f) }
|
|
137
|
-
)
|
|
138
|
-
end
|
|
13
|
+
attr :config
|
|
139
14
|
|
|
15
|
+
#
|
|
140
16
|
def start
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if files.empty?
|
|
17
|
+
if config.files.empty?
|
|
144
18
|
$stderr.puts "No tests."
|
|
145
19
|
return
|
|
146
20
|
end
|
|
147
21
|
|
|
148
|
-
|
|
22
|
+
setup
|
|
149
23
|
|
|
24
|
+
testrun = runner.new
|
|
150
25
|
testrun.start
|
|
151
26
|
end
|
|
152
27
|
|
|
153
|
-
#
|
|
154
|
-
def
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
require 'turn/reporters/marshal_reporter'
|
|
159
|
-
Turn::MarshalReporter.new($stdout)
|
|
160
|
-
when :progress
|
|
161
|
-
require 'turn/reporters/progress_reporter'
|
|
162
|
-
Turn::ProgressReporter.new($stdout)
|
|
163
|
-
when :dotted
|
|
164
|
-
require 'turn/reporters/dot_reporter'
|
|
165
|
-
Turn::DotReporter.new($stdout)
|
|
166
|
-
when :pretty
|
|
167
|
-
require 'turn/reporters/pretty_reporter'
|
|
168
|
-
Turn::PrettyReporter.new($stdout)
|
|
169
|
-
when :cue
|
|
170
|
-
require 'turn/reporters/cue_reporter'
|
|
171
|
-
Turn::CueReporter.new($stdout)
|
|
172
|
-
else
|
|
173
|
-
require 'turn/reporters/outline_reporter'
|
|
174
|
-
Turn::OutlineReporter.new($stdout)
|
|
175
|
-
end
|
|
176
|
-
)
|
|
28
|
+
#
|
|
29
|
+
def setup
|
|
30
|
+
config.loadpath.each{ |path| $: << path } unless config.live?
|
|
31
|
+
config.requires.each{ |path| require(path) }
|
|
32
|
+
config.files.each{ |path| require(path) }
|
|
177
33
|
end
|
|
178
34
|
|
|
179
|
-
#
|
|
35
|
+
# Insatance of Runner, selected based on format and runmode.
|
|
180
36
|
def runner
|
|
181
37
|
@runner ||= (
|
|
182
|
-
|
|
183
|
-
when :minitest
|
|
184
|
-
require 'turn/runners/minirunner'
|
|
185
|
-
else
|
|
186
|
-
require 'turn/runners/testrunner'
|
|
187
|
-
end
|
|
38
|
+
require 'turn/runners/minirunner'
|
|
188
39
|
|
|
189
|
-
case runmode
|
|
40
|
+
case config.runmode
|
|
190
41
|
when :marshal
|
|
191
|
-
|
|
192
|
-
Turn::MiniRunner
|
|
193
|
-
else
|
|
194
|
-
Turn::TestRunner
|
|
195
|
-
end
|
|
42
|
+
Turn::MiniRunner
|
|
196
43
|
when :solo
|
|
197
44
|
require 'turn/runners/solorunner'
|
|
198
45
|
Turn::SoloRunner
|
|
@@ -200,11 +47,7 @@ module Turn
|
|
|
200
47
|
require 'turn/runners/crossrunner'
|
|
201
48
|
Turn::CrossRunner
|
|
202
49
|
else
|
|
203
|
-
|
|
204
|
-
Turn::MiniRunner
|
|
205
|
-
else
|
|
206
|
-
Turn::TestRunner
|
|
207
|
-
end
|
|
50
|
+
Turn::MiniRunner
|
|
208
51
|
end
|
|
209
52
|
)
|
|
210
53
|
end
|
|
@@ -212,4 +55,3 @@ module Turn
|
|
|
212
55
|
end
|
|
213
56
|
|
|
214
57
|
end
|
|
215
|
-
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module Turn
|
|
2
|
+
|
|
3
|
+
class ToptenDecorator
|
|
4
|
+
|
|
5
|
+
def initialize(reporter)
|
|
6
|
+
@reporter = reporter
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def method_missing(m,*args,&block)
|
|
10
|
+
@reporter.send(m,*args,&block)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start_case(kase)
|
|
14
|
+
@reporter.start_case(kase)
|
|
15
|
+
@top_ten_current_case = kase
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def start_test(test)
|
|
19
|
+
@reporter.start_test(test)
|
|
20
|
+
test_time_data[test_key(test)] = {:start => Time.now}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def finish_test(test)
|
|
24
|
+
@reporter.finish_test(test)
|
|
25
|
+
test_time_data[test_key(test)][:end] = Time.now
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def finish_suite(suite)
|
|
29
|
+
@reporter.finish_suite(suite)
|
|
30
|
+
io.puts
|
|
31
|
+
io.puts Colorize.bold("Top 10 Longest Running Tests")
|
|
32
|
+
top_ten_times.each do |(test_name, time)|
|
|
33
|
+
io.print format_time(time)
|
|
34
|
+
io.puts format_test_name(test_name, time)
|
|
35
|
+
end
|
|
36
|
+
io.puts
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def test_key(test)
|
|
42
|
+
"#{@top_ten_current_case.name} #{test}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def top_ten_times
|
|
46
|
+
test_times.sort_by {|(_, time)| -time}.take(10)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_times
|
|
50
|
+
test_time_data.map {|(test, times)| [test, times[:end] - times[:start]]}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_time_data
|
|
54
|
+
@test_time_data ||= {}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def format_time(time)
|
|
58
|
+
Colorize.blue(time)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def format_test_name(test_name, time)
|
|
62
|
+
test_name.tabto(11-time.to_s.length)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# make sure latest verison is used, rather than ruby's built-in
|
|
2
|
+
begin
|
|
3
|
+
gem 'minitest', '< 5.0.0'
|
|
4
|
+
rescue Gem::LoadError
|
|
5
|
+
warn "gem install minitest"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# we save the developer the trouble of having to load these (TODO: should we?)
|
|
9
|
+
require 'minitest/unit'
|
|
10
|
+
require 'minitest/spec'
|
|
11
|
+
|
|
12
|
+
# compatability with old Test::Unit
|
|
13
|
+
#Test = MiniTest unless defined?(Test)
|
|
14
|
+
|
|
15
|
+
# load Turn's minitest runner
|
|
16
|
+
require 'turn/runners/minirunner'
|
|
17
|
+
|
|
18
|
+
# set MiniTest's runner to Turn::MiniRunner instance
|
|
19
|
+
if MiniTest::Unit.respond_to?(:runner=)
|
|
20
|
+
MiniTest::Unit.runner = Turn::MiniRunner.new
|
|
21
|
+
else
|
|
22
|
+
raise "MiniTest v#{MiniTest::Unit::VERSION} is out of date.\n" \
|
|
23
|
+
"Please update to a newer version, but version 5.0.0 or above will not work. ."
|
|
24
|
+
#MiniTest::Unit = Turn::MiniRunner
|
|
25
|
+
end
|
data/lib/turn/reporter.rb
CHANGED
|
@@ -2,8 +2,6 @@ module Turn
|
|
|
2
2
|
require 'turn/colorize'
|
|
3
3
|
require 'turn/core_ext'
|
|
4
4
|
|
|
5
|
-
# = Reporter
|
|
6
|
-
#
|
|
7
5
|
# There are two distinct way in which a report may be utilized
|
|
8
6
|
# by a Runner: per-call or per-file. The method #pass, #fail
|
|
9
7
|
# and #error are generic, and will be used in either case.
|
|
@@ -16,54 +14,118 @@ module Turn
|
|
|
16
14
|
|
|
17
15
|
include Colorize
|
|
18
16
|
|
|
17
|
+
# Where to send report, defaults to `$stdout`.
|
|
19
18
|
attr :io
|
|
20
19
|
|
|
21
|
-
def initialize(io)
|
|
22
|
-
@io
|
|
20
|
+
def initialize(io, opts={})
|
|
21
|
+
@io = io || $stdout
|
|
22
|
+
@trace = opts[:trace]
|
|
23
|
+
@natural = opts[:natural]
|
|
24
|
+
@verbose = opts[:verbose]
|
|
25
|
+
@mark = opts[:mark].to_i
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
# These methods are called in the process of running the tests.
|
|
26
29
|
|
|
30
|
+
# At the very start, before any testcases are run, this is called.
|
|
27
31
|
def start_suite(test_suite)
|
|
28
32
|
end
|
|
29
33
|
|
|
34
|
+
# Invoked before a testcase is run.
|
|
30
35
|
def start_case(test_case)
|
|
31
36
|
end
|
|
32
37
|
|
|
38
|
+
# Invoked before a test is run.
|
|
33
39
|
def start_test(test)
|
|
34
40
|
end
|
|
35
41
|
|
|
42
|
+
# Invoked when a test passes.
|
|
36
43
|
def pass(message=nil)
|
|
37
44
|
end
|
|
38
45
|
|
|
46
|
+
# Invoked when a test raises an assertion.
|
|
39
47
|
def fail(assertion, message=nil)
|
|
40
48
|
end
|
|
41
49
|
|
|
50
|
+
# Invoked when a test raises an exception.
|
|
42
51
|
def error(exception, message=nil)
|
|
43
52
|
end
|
|
44
53
|
|
|
54
|
+
# Invoked when a test is skipped.
|
|
55
|
+
def skip(exception, message=nil)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Invoked after a test has been run.
|
|
45
59
|
def finish_test(test)
|
|
46
60
|
end
|
|
47
61
|
|
|
62
|
+
# Invoked after all tests in a testcase have ben run.
|
|
48
63
|
def finish_case(test_case)
|
|
49
64
|
end
|
|
50
65
|
|
|
66
|
+
# After all tests are run, this is the last observable action.
|
|
51
67
|
def finish_suite(test_suite)
|
|
52
68
|
end
|
|
53
69
|
|
|
54
70
|
private
|
|
55
71
|
|
|
56
|
-
#
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
# Apply filter_backtrace and limit_backtrace in one go.
|
|
73
|
+
def clean_backtrace(backtrace)
|
|
74
|
+
limit_backtrace(filter_backtrace(backtrace))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# TODO: Is the text/unit line needed any more now that Dir.pwd is excluded
|
|
78
|
+
# from filtering?
|
|
79
|
+
|
|
80
|
+
$RUBY_IGNORE_CALLERS ||= []
|
|
81
|
+
$RUBY_IGNORE_CALLERS.concat([
|
|
82
|
+
/\/lib\/turn.*\.rb/,
|
|
83
|
+
/\/bin\/turn/,
|
|
84
|
+
/\/lib\/minitest.*\.rb/,
|
|
85
|
+
/\/test\/unit(?!(\/.*\_test.rb)|.*\/test_.*).*\.rb.*/
|
|
86
|
+
])
|
|
87
|
+
|
|
88
|
+
# Filter backtrace of unimportant entries, and applies count limit if set in
|
|
89
|
+
# configuration. Setting $DEBUG to true will deactivate filter, or if the filter
|
|
90
|
+
# happens to remove all backtrace entries it will revert to the full backtrace,
|
|
91
|
+
# as that probably means there was an issue with the test harness itself.
|
|
92
|
+
def filter_backtrace(backtrace)
|
|
93
|
+
return [] unless backtrace
|
|
94
|
+
bt, pwd = backtrace.dup, Dir.pwd
|
|
95
|
+
unless $DEBUG
|
|
96
|
+
bt = bt.reject do |line|
|
|
97
|
+
$RUBY_IGNORE_CALLERS.any?{|re| re =~ line} unless line.start_with?(pwd)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
bt = backtrace if bt.empty? # if empty just dump the whole thing
|
|
101
|
+
bt.map{ |line| line.sub(pwd+'/', '') }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Limit backtrace to number of lines if `trace` configuration option is set.
|
|
105
|
+
def limit_backtrace(backtrace)
|
|
106
|
+
return [] unless backtrace
|
|
107
|
+
@trace ? backtrace[0, @trace.to_i] : backtrace
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns a more readable test name with spaces instead of underscores
|
|
111
|
+
def naturalized_name(test)
|
|
112
|
+
if @natural
|
|
113
|
+
test.name.gsub("test_", "").gsub(/_/, " ")
|
|
114
|
+
else
|
|
115
|
+
test.name
|
|
116
|
+
end
|
|
64
117
|
end
|
|
65
118
|
|
|
119
|
+
#
|
|
120
|
+
def ticktock
|
|
121
|
+
t = Time.now - @time
|
|
122
|
+
h, t = t.divmod(3600)
|
|
123
|
+
m, t = t.divmod(60)
|
|
124
|
+
s = t.truncate
|
|
125
|
+
f = ((t - s) * 1000).to_i
|
|
126
|
+
|
|
127
|
+
"%01d:%02d:%02d.%03d" % [h,m,s,f]
|
|
128
|
+
end
|
|
66
129
|
end
|
|
67
130
|
|
|
68
131
|
end
|
|
69
|
-
|
|
@@ -27,7 +27,8 @@ module Turn
|
|
|
27
27
|
# @file = test.file
|
|
28
28
|
# io.puts(test.file)
|
|
29
29
|
#end
|
|
30
|
-
|
|
30
|
+
name = naturalized_name(test)
|
|
31
|
+
io.print Colorize.blue(" %-69s" % name)
|
|
31
32
|
$stdout = @stdout
|
|
32
33
|
$stderr = @stderr
|
|
33
34
|
$stdout.rewind
|
|
@@ -67,6 +68,15 @@ module Turn
|
|
|
67
68
|
prompt
|
|
68
69
|
end
|
|
69
70
|
|
|
71
|
+
def skip(exception, message=nil)
|
|
72
|
+
message = message || exception.to_s
|
|
73
|
+
io.puts("#{SKIP}")
|
|
74
|
+
io.puts(message) #if message
|
|
75
|
+
|
|
76
|
+
#prompt
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
|
|
70
80
|
def finish_test(test)
|
|
71
81
|
$stdout = STDOUT
|
|
72
82
|
$stderr = STDERR
|
|
@@ -99,22 +109,26 @@ module Turn
|
|
|
99
109
|
#end
|
|
100
110
|
|
|
101
111
|
def finish_suite(suite)
|
|
102
|
-
total
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
total = suite.count_tests
|
|
113
|
+
passes = suite.count_passes
|
|
114
|
+
assertions = suite.count_assertions
|
|
115
|
+
failures = suite.count_failures
|
|
116
|
+
errors = suite.count_errors
|
|
117
|
+
skips = suite.count_skips
|
|
106
118
|
|
|
107
119
|
bar = '=' * 78
|
|
108
|
-
|
|
120
|
+
# @FIXME: Remove this, since Colorize already take care of colorize?
|
|
121
|
+
if colorize?
|
|
109
122
|
bar = if pass == total then Colorize.green(bar)
|
|
110
123
|
else Colorize.red(bar) end
|
|
111
124
|
end
|
|
112
125
|
|
|
113
|
-
|
|
126
|
+
# @FIXME: Should we add suite.runtime, instead if this lame time calculations?
|
|
127
|
+
tally = [total, assertions, (Time.new - @time)]
|
|
114
128
|
|
|
115
129
|
io.puts bar
|
|
116
|
-
io.puts " pass: %d, fail: %d, error: %d" % [
|
|
117
|
-
io.puts " total: %d tests with %d assertions in
|
|
130
|
+
io.puts " pass: %d, fail: %d, error: %d, skip: %d" % [passes, failures, errors, skips]
|
|
131
|
+
io.puts " total: %d tests with %d assertions in %f seconds" % tally
|
|
118
132
|
io.puts bar
|
|
119
133
|
end
|
|
120
134
|
|
|
@@ -130,9 +144,11 @@ module Turn
|
|
|
130
144
|
when 'c', ''
|
|
131
145
|
when 'r'
|
|
132
146
|
# how to reload and start over?
|
|
147
|
+
io.puts "restart has not been implemented yet"
|
|
133
148
|
when 'i'
|
|
134
149
|
# how to drop into an interactive console?
|
|
135
|
-
|
|
150
|
+
io.puts "irb support has not been implemented yet"
|
|
151
|
+
when 'b', 't'
|
|
136
152
|
io.puts $@
|
|
137
153
|
raise ArgumentError
|
|
138
154
|
when /^\d+$/
|
|
@@ -155,7 +171,7 @@ module Turn
|
|
|
155
171
|
c continue
|
|
156
172
|
r restart
|
|
157
173
|
i irb
|
|
158
|
-
|
|
174
|
+
b backtrace
|
|
159
175
|
# backtrace lines
|
|
160
176
|
q quit
|
|
161
177
|
? help
|
|
@@ -22,14 +22,18 @@ module Turn
|
|
|
22
22
|
io.print Colorize.pass('.'); io.flush
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def fail(message=nil)
|
|
25
|
+
def fail(assertion, message=nil)
|
|
26
26
|
io.print Colorize.fail('F'); io.flush
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
def error(message=nil)
|
|
29
|
+
def error(exception, message=nil)
|
|
30
30
|
io.print Colorize.error('E'); io.flush
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def skip(exception, message=nil)
|
|
34
|
+
io.print Colorize.skip('S'); io.flush
|
|
35
|
+
end
|
|
36
|
+
|
|
33
37
|
def finish_test(test)
|
|
34
38
|
end
|
|
35
39
|
|
|
@@ -53,41 +57,33 @@ module Turn
|
|
|
53
57
|
unless list.empty? # or verbose?
|
|
54
58
|
#report << "\n\n-- Failures and Errors --\n\n"
|
|
55
59
|
list.uniq.each do |testunit|
|
|
56
|
-
message =
|
|
57
|
-
message
|
|
58
|
-
message <<
|
|
59
|
-
|
|
60
|
+
message = []
|
|
61
|
+
message << (testunit.fail? ? FAIL : ERROR)
|
|
62
|
+
message << testunit.message.tabto(2)
|
|
63
|
+
message << clean_backtrace(testunit.backtrace).join("\n").tabto(2)
|
|
64
|
+
report << "\n" << message.join("\n") << "\n"
|
|
60
65
|
end
|
|
61
66
|
report << "\n"
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
io.puts report
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
io.puts tally
|
|
77
|
-
end
|
|
71
|
+
# @TODO: Add something like suite.count(:tests, :passes) or
|
|
72
|
+
# suite.count(tests: "%d tests", passes: "%d passes")
|
|
73
|
+
# to cleanup, which will return something handy
|
|
74
|
+
# (suite.count(:test, :passes).test proxy maybe?)
|
|
75
|
+
total = "%d tests" % suite.count_tests
|
|
76
|
+
passes = "%d passed" % suite.count_passes
|
|
77
|
+
assertions = "%d assertions" % suite.count_assertions
|
|
78
|
+
failures = "%s failures" % suite.count_failures
|
|
79
|
+
errors = "%s errors" % suite.count_errors
|
|
80
|
+
skips = "%s skips" % suite.count_skips
|
|
78
81
|
|
|
79
|
-
|
|
82
|
+
tally = [total, passes, assertions, failures, errors, skips].join(", ")
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
counts = suite.collect{ |tr| tr.counts }
|
|
83
|
-
tally = [0,0,0,0]
|
|
84
|
-
counts.each do |count|
|
|
85
|
-
4.times{ |i| tally[i] += count[i] }
|
|
86
|
-
end
|
|
87
|
-
return tally
|
|
84
|
+
io.puts suite.passed? ? Colorize.green(tally) : Colorize.red(tally)
|
|
88
85
|
end
|
|
89
86
|
|
|
90
87
|
end
|
|
91
88
|
|
|
92
|
-
end
|
|
93
|
-
|
|
89
|
+
end
|