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.
Files changed (52) hide show
  1. data/CONTRIBUTING.md +40 -0
  2. data/History.txt +81 -1
  3. data/Index.rb +34 -0
  4. data/LICENSE.txt +21 -0
  5. data/NOTICE.md +12 -0
  6. data/README.md +176 -0
  7. data/Release.txt +21 -1
  8. data/Version.txt +1 -1
  9. data/bin/turn +8 -2
  10. data/lib/turn/autoload.rb +6 -0
  11. data/lib/turn/autorun.rb +4 -0
  12. data/lib/turn/bin.rb +8 -2
  13. data/lib/turn/colorize.rb +50 -19
  14. data/lib/turn/command.rb +102 -39
  15. data/lib/turn/components/case.rb +7 -2
  16. data/lib/turn/components/method.rb +13 -2
  17. data/lib/turn/components/suite.rb +15 -6
  18. data/lib/turn/components.rb +4 -0
  19. data/lib/turn/configuration.rb +271 -0
  20. data/lib/turn/controller.rb +18 -176
  21. data/lib/turn/decorators/topten_decorator.rb +67 -0
  22. data/lib/turn/minitest.rb +25 -0
  23. data/lib/turn/reporter.rb +75 -13
  24. data/lib/turn/reporters/cue_reporter.rb +27 -11
  25. data/lib/turn/reporters/dot_reporter.rb +24 -28
  26. data/lib/turn/reporters/outline_reporter.rb +76 -39
  27. data/lib/turn/reporters/pretty_reporter.rb +110 -129
  28. data/lib/turn/reporters/progress_reporter.rb +70 -33
  29. data/lib/turn/runners/crossrunner.rb +2 -2
  30. data/lib/turn/runners/isorunner.rb +12 -10
  31. data/lib/turn/runners/minirunner.rb +51 -81
  32. data/lib/turn/runners/solorunner.rb +0 -1
  33. data/lib/turn/runners/testrunner.rb +12 -15
  34. data/lib/turn/testunit.rb +24 -0
  35. data/lib/turn/version.rb +1 -1
  36. data/lib/turn.rb +10 -15
  37. data/test/helper.rb +81 -5
  38. data/test/reporter_test.rb +35 -0
  39. data/test/test_framework.rb +81 -38
  40. data/test/test_reporters.rb +14 -14
  41. data/test/test_runners.rb +57 -19
  42. data/{demo → try}/test_autorun_minitest.rb +5 -4
  43. data/{demo → try}/test_autorun_testunit.rb +1 -2
  44. metadata +135 -112
  45. data/README.txt +0 -116
  46. data/Rakefile +0 -39
  47. data/lib/turn/autorun/minitest.rb +0 -173
  48. data/lib/turn/autorun/testunit.rb +0 -116
  49. data/turn.gemspec +0 -49
  50. /data/{demo → try}/test_counts.rb +0 -0
  51. /data/{demo → try}/test_sample.rb +0 -0
  52. /data/{demo → try}/test_sample2.rb +0 -0
data/lib/turn/command.rb CHANGED
@@ -1,34 +1,40 @@
1
1
  require 'optparse'
2
2
 
3
3
  module Turn
4
- require 'turn/controller'
5
4
 
6
5
  # Turn - Pretty Unit Test Runner for Ruby
7
- #
6
+ #
8
7
  # SYNOPSIS
9
- # turn [OPTIONS] [RUN MODE] [OUTPUT MODE] [test globs...]
10
- #
11
- # OPTIONS
12
- # -h --help display this help information
13
- # --live don't use loadpath
14
- # --log log results to a file
15
- # -n --name=PATTERN only run tests that match regexp PATTERN
16
- # -I --loadpath=PATHS add given PATHS to the $LOAD_PATH
17
- # -r --requires=LIBS require given LIBS before running tests
18
- # -m --minitest Force use of MiniTest framework.
19
- #
8
+ # turn [OPTIONS] [RUN MODE] [OUTPUT MODE] [TEST GLOBS ...]
9
+ #
10
+ # GENERAL OPTIONS
11
+ # -I, --loadpath=PATHS add paths to $LOAD_PATH
12
+ # -r, --require=LIBS require libraries
13
+ # -n, --name=PATTERN only run tests that match PATTERN
14
+ # -c, --case=PATTERN only run test cases that match PATTERN
15
+ # -b, --backtrace, --trace INT Limit the number of lines of backtrace.
16
+ # --natural Show natualized test names.
17
+ # --[no-]ansi Force use of ANSI codes on or off.
18
+ # --log log results to a file
19
+ # --live do not use local load path
20
+ #
20
21
  # RUN MODES
21
- # --normal run all tests in a single process [default]
22
- # --solo run each test in a separate process
23
- # --cross run each pair of test files in a separate process
24
- #
22
+ # --normal run all tests in a single process [default]
23
+ # --solo run each test in a separate process
24
+ # --cross run each pair of test files in a separate process
25
+ #
25
26
  # OUTPUT MODES
26
- # -O --outline turn's original case/test outline mode [default]
27
- # -P --progress indicates progress with progress bar
28
- # -D --dotted test/unit's traditonal dot-progress mode
29
- # --pretty new pretty reporter
30
- # -M --marshal dump output as YAML (normal run mode only)
31
- # -Q --queued interactive testing
27
+ # -O, --outline turn's original case/test outline mode
28
+ # -P, --progress indicates progress with progress bar
29
+ # -D, --dot, --dotted test-unit's traditonal dot-progress mode
30
+ # -R, -T, --pretty new pretty output mode [default]
31
+ # -C, --cue cue for action on each failure/error
32
+ # -M, --marshal dump output as YAML (normal run mode only)
33
+ #
34
+ # COMMAND OPTIONS
35
+ # --debug turn debug mode on
36
+ # --version display version
37
+ # -h, --help display this help information
32
38
  #
33
39
  class Command
34
40
 
@@ -56,7 +62,7 @@ module Turn
56
62
  attr :requires
57
63
 
58
64
  # Framework to use, :minitest or :testunit.
59
- attr :framework
65
+ #attr :framework
60
66
 
61
67
  # Run mode.
62
68
  attr :runmode
@@ -64,6 +70,24 @@ module Turn
64
70
  # Output mode.
65
71
  attr :outmode
66
72
 
73
+ # Decorator mode.
74
+ attr :decmode
75
+
76
+ # Enable full backtrace
77
+ attr :trace
78
+
79
+ # Use natural test case names.
80
+ attr :natural
81
+
82
+ # Show extra information.
83
+ attr :verbose
84
+
85
+ # Show extra information.
86
+ attr :mark
87
+
88
+ # Force ANSI use on or off.
89
+ attr :ansi
90
+
67
91
  #
68
92
  def initialize
69
93
  @live = nil
@@ -74,7 +98,12 @@ module Turn
74
98
  @requires = []
75
99
  @runmode = nil
76
100
  @outmode = nil
77
- @framework = RUBY_VERSION >= "1.9" ? :minitest : :testunit
101
+ @decmode = nil
102
+ @trace = nil
103
+ @natural = false
104
+ @verbose = false
105
+ @mark = nil
106
+ @ansi = nil
78
107
  end
79
108
 
80
109
  #
@@ -106,7 +135,7 @@ module Turn
106
135
  end
107
136
  end
108
137
 
109
- opts.on('-t', '--testcase=PATTERN', "only run testcases that match PATTERN") do |pattern|
138
+ opts.on('-c', '--case=PATTERN', "only run test cases that match PATTERN") do |pattern|
110
139
  if pattern =~ /\/(.*)\//
111
140
  @matchcase = Regexp.new($1)
112
141
  else
@@ -114,8 +143,24 @@ module Turn
114
143
  end
115
144
  end
116
145
 
117
- opts.on('-m', '--minitest', "Force use of MiniTest framework") do
118
- @framework = :minitest
146
+ opts.on('-m', '--mark=SECONDS', "Mark test if it exceeds runtime threshold.") do |int|
147
+ @mark = int.to_i
148
+ end
149
+
150
+ opts.on('-b', '--backtrace', '--trace INT', "Limit the number of lines of backtrace.") do |int|
151
+ @trace = int
152
+ end
153
+
154
+ opts.on('--natural', "Show natualized test names.") do |bool|
155
+ @natural = bool
156
+ end
157
+
158
+ opts.on('-v', '--verbose', "Show extra information.") do |bool|
159
+ @verbose = bool
160
+ end
161
+
162
+ opts.on('--[no-]ansi', "Force use of ANSI codes on or off.") do |bool|
163
+ @ansi = bool
119
164
  end
120
165
 
121
166
  # Turn does not support Test::Unit 2.0+
@@ -152,7 +197,7 @@ module Turn
152
197
  opts.separator " "
153
198
  opts.separator "OUTPUT MODES"
154
199
 
155
- opts.on('--outline', '-O', "turn's original case/test outline mode [default]") do
200
+ opts.on('--outline', '-O', "turn's original case/test outline mode") do
156
201
  @outmode = :outline
157
202
  end
158
203
 
@@ -160,11 +205,11 @@ module Turn
160
205
  @outmode = :progress
161
206
  end
162
207
 
163
- opts.on('--dotted', '-D', "test-unit's traditonal dot-progress mode") do
164
- @outmode = :dotted
208
+ opts.on('--dot', '--dotted', '-D', "test-unit's traditonal dot-progress mode") do
209
+ @outmode = :dot
165
210
  end
166
211
 
167
- opts.on('--pretty', '-T', "new pretty output mode") do
212
+ opts.on('--pretty', '-R', '-T', "new pretty output mode [default]") do
168
213
  @outmode = :pretty
169
214
  end
170
215
 
@@ -177,12 +222,22 @@ module Turn
177
222
  @outmode = :marshal
178
223
  end
179
224
 
225
+ opts.separator " "
226
+ opts.separator "DECORATOR MODES"
227
+
228
+ opts.on('--topten', "show only top ten slowest tests") do
229
+ @decmode = :topten
230
+ end
231
+
180
232
  opts.separator " "
181
233
  opts.separator "COMMAND OPTIONS"
182
234
 
183
235
  opts.on('--debug', "turn debug mode on") do
236
+ $DEBUG = true
237
+ end
238
+
239
+ opts.on('--warn', "turn warnings on") do
184
240
  $VERBOSE = true
185
- $DEBUG = true
186
241
  end
187
242
 
188
243
  opts.on_tail('--version', "display version") do
@@ -190,7 +245,7 @@ module Turn
190
245
  exit
191
246
  end
192
247
 
193
- opts.on_tail('--help', '-h', "display this help information") do
248
+ opts.on_tail('-h', '--help', "display this help information") do
194
249
  puts opts
195
250
  exit
196
251
  end
@@ -203,9 +258,10 @@ module Turn
203
258
 
204
259
  @loadpath = ['lib'] if loadpath.empty?
205
260
 
206
- tests = ARGV.empty? ? nil : ARGV.dup
261
+ tests = ARGV.empty? ? nil : argv.dup
207
262
 
208
- controller = Turn::Controller.new do |c|
263
+ #config = Turn::Configuration.new do |c|
264
+ config = Turn.config do |c|
209
265
  c.live = live
210
266
  c.log = log
211
267
  c.loadpath = loadpath
@@ -213,17 +269,24 @@ module Turn
213
269
  c.tests = tests
214
270
  c.runmode = runmode
215
271
  c.format = outmode
272
+ c.mode = decmode
216
273
  c.pattern = pattern
217
274
  c.matchcase = matchcase
218
- c.framework = framework
275
+ c.trace = trace
276
+ c.natural = natural
277
+ c.verbose = verbose
278
+ c.mark = mark
279
+ c.ansi = ansi unless ansi.nil?
219
280
  end
220
281
 
282
+ controller = Turn::Controller.new(config)
283
+
221
284
  result = controller.start
222
285
 
223
286
  if result
224
- exit result.passed?
287
+ exit (result.passed? ? 0 : -1)
225
288
  else # no tests
226
- exit
289
+ exit -1
227
290
  end
228
291
  end
229
292
 
@@ -23,7 +23,7 @@ module Turn
23
23
  attr_accessor :count_assertions
24
24
 
25
25
  # Holds dump of test output (optional depending on runner).
26
- attr_accessor :message
26
+ attr_writer :message
27
27
 
28
28
  # Command used to run test (optional depending on runner).
29
29
  #attr_accessor :command
@@ -86,9 +86,14 @@ module Turn
86
86
  sum = 0; tests.each{ |t| sum += 1 if t.pass? }; sum
87
87
  end
88
88
 
89
+ def count_skips
90
+ # Why not use tests.select(&:skip?).size ?
91
+ sum = 0; tests.each{ |t| sum += 1 if t.skip? }; sum
92
+ end
93
+
89
94
  #
90
95
  def counts
91
- return count_tests, count_assertions, count_failures, count_errors
96
+ return count_tests, count_assertions, count_failures, count_errors, count_skips
92
97
  end
93
98
 
94
99
  def message
@@ -12,27 +12,38 @@ module Turn
12
12
  @name = name
13
13
  @fail = false
14
14
  @error = false
15
+ @skip = false
15
16
  @raised = nil
16
17
  @message = nil
17
18
  @backtrace = []
18
19
  end
19
20
 
20
21
  def fail!(assertion)
21
- @fail, @error = true, false
22
+ @fail, @error, @skip = true, false, false
22
23
  @raised = assertion
23
24
  @message = assertion.message
24
25
  @backtrace = assertion.backtrace
25
26
  end
26
27
 
27
28
  def error!(exception)
28
- @fail, @error = false, true
29
+ @fail, @error, @skip = false, true, false
29
30
  @raised = exception
30
31
  @message = exception.message
31
32
  @backtrace = exception.backtrace
32
33
  end
33
34
 
35
+ def skip!(assertion)
36
+ @fail, @error, @skip = false, false, true
37
+ @raised = assertion
38
+ @message = assertion.message
39
+ @backtrace = assertion.backtrace
40
+ end
41
+
34
42
  def fail? ; @fail ; end
35
43
  def error? ; @error ; end
44
+ def skip? ; @skip ; end
45
+
46
+ # TODO: should this include `or @skip`?
36
47
  def pass? ; !(@fail or @error) ; end
37
48
 
38
49
  def to_s ; name ; end
@@ -6,18 +6,19 @@ module Turn
6
6
  include Enumerable
7
7
 
8
8
  attr_accessor :name
9
- attr_accessor :size
10
9
  attr_accessor :cases
10
+ attr_accessor :seed
11
11
 
12
12
  # This one can be set manually since it
13
13
  # is not calculatable (beyond the case level).
14
- attr_accessor :count_assertions
14
+ attr_writer :count_assertions
15
15
 
16
16
  #
17
17
  def initialize(name=nil)
18
18
  @name = name
19
- @size = nil
20
19
  @cases = []
20
+ @size = nil
21
+ @seed = nil
21
22
 
22
23
  #@count_tests = nil
23
24
  #@count_assertions = nil
@@ -63,9 +64,13 @@ module Turn
63
64
  #)
64
65
  end
65
66
 
67
+ def count_skips
68
+ sum = 0; each{ |c| sum += c.count_skips }; sum
69
+ end
70
+
66
71
  # Convenience methods --this is what is typcially wanted.
67
72
  def counts
68
- return count_tests, count_assertions, count_failures, count_errors #,count_skips
73
+ return count_tests, count_assertions, count_failures, count_errors ,count_skips
69
74
  end
70
75
 
71
76
  def each(&block)
@@ -76,10 +81,14 @@ module Turn
76
81
  @size ||= @cases.size
77
82
  end
78
83
 
84
+ # Why the size would ever have to overridden... well who can say.
85
+ def size=(number)
86
+ @size = number.to_i
87
+ end
88
+
79
89
  def passed?
80
90
  (count_failures == 0 && count_errors == 0)
81
91
  end
82
92
  end
83
93
 
84
- end
85
-
94
+ end
@@ -0,0 +1,4 @@
1
+ require 'turn/components/suite'
2
+ require 'turn/components/case'
3
+ require 'turn/components/method'
4
+
@@ -0,0 +1,271 @@
1
+ module Turn
2
+
3
+ # Configure Turn
4
+ def self.config(&block)
5
+ @config ||= Configuration.new
6
+ block.call(@config) if block
7
+ @config
8
+ end
9
+
10
+ # TODO: Support for test run loggging ?
11
+
12
+ # Central interface for Turn configuration.
13
+ #
14
+ class Configuration
15
+
16
+ # List of if file names or glob pattern of tests to run.
17
+ attr_reader :tests
18
+
19
+ # List of file names or globs to exclude from +tests+ list.
20
+ attr_reader :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_reader :loadpath
32
+
33
+ # Libs to require when running tests.
34
+ attr_reader :requires
35
+
36
+ # Reporter type.
37
+ attr_accessor :format
38
+
39
+ # Report modifier. These act as decorators on the reporter class.
40
+ attr_accessor :mode
41
+
42
+ # Run mode, which defaults to `nil`, but can also be `:solo`,
43
+ # `:cross` or `:marshal`.
44
+ attr_accessor :runmode
45
+
46
+ # Test against live install (i.e. Don't use loadpath option)
47
+ attr_accessor :live
48
+
49
+ # Log results? May be true/false or log file name. (TODO)
50
+ attr_accessor :log
51
+
52
+ # Verbose output?
53
+ attr_accessor :verbose
54
+
55
+ # Runtime threshold.
56
+ attr_accessor :mark
57
+
58
+ # Test framework, either `:minitest` or `:testunit`.
59
+ # TODO: Is this used any more?
60
+ attr_accessor :framework
61
+
62
+ # Enable full backtrace
63
+ attr_accessor :trace
64
+
65
+ # Use natural language case names.
66
+ attr_accessor :natural
67
+
68
+ #
69
+ def verbose?
70
+ @verbose
71
+ end
72
+
73
+ #
74
+ def live?
75
+ @live
76
+ end
77
+
78
+ #
79
+ def natural?
80
+ @natural
81
+ end
82
+
83
+ #
84
+ def ansi?
85
+ @ansi
86
+ end
87
+
88
+ private
89
+
90
+ #
91
+ def initialize
92
+ yield(self) if block_given?
93
+ initialize_defaults
94
+ end
95
+
96
+ #
97
+ def initialize_defaults
98
+ @loadpath ||= ['lib']
99
+ @tests ||= ["test/**/{test,}*{,test}.rb"]
100
+ @exclude ||= []
101
+ @requires ||= []
102
+ @live ||= false
103
+ @log ||= true
104
+ #@runner ||= RUBY_VERSION >= "1.9" ? MiniRunner : TestRunner
105
+ @matchcase ||= nil
106
+ @pattern ||= /.*/
107
+ @natural ||= false
108
+ @verbose ||= false
109
+ @format ||= environment_format
110
+ @mode ||= environment_mode
111
+ @trace ||= environment_trace
112
+ @ansi ||= environment_ansi
113
+
114
+ @files = nil # reset files just in case
115
+ end
116
+
117
+ # Collect test configuation.
118
+ #def test_configuration(options={})
119
+ # #options = configure_options(options, 'test')
120
+ # #options['loadpath'] ||= metadata.loadpath
121
+ # options['tests'] ||= self.tests
122
+ # options['loadpath'] ||= self.loadpath
123
+ # options['requires'] ||= self.requires
124
+ # options['live'] ||= self.live
125
+ # options['exclude'] ||= self.exclude
126
+ # #options['tests'] = list_option(options['tests'])
127
+ # options['loadpath'] = list_option(options['loadpath'])
128
+ # options['exclude'] = list_option(options['exclude'])
129
+ # options['require'] = list_option(options['require'])
130
+ # return options
131
+ #end
132
+
133
+ #
134
+ def list_option(list)
135
+ case list
136
+ when nil
137
+ []
138
+ when Array
139
+ list
140
+ else
141
+ list.split(/[:;]/)
142
+ end
143
+ end
144
+
145
+ public
146
+
147
+ def ansi=(boolean)
148
+ @ansi = boolean ? true : false
149
+ end
150
+
151
+ def tests=(paths)
152
+ @tests = list_option(paths)
153
+ end
154
+
155
+ def loadpath=(paths)
156
+ @loadpath = list_option(paths)
157
+ end
158
+
159
+ def exclude=(paths)
160
+ @exclude = list_option(paths)
161
+ end
162
+
163
+ def requires=(paths)
164
+ @requires = list_option(paths)
165
+ end
166
+
167
+ # Test files.
168
+ def files
169
+ @files ||= (
170
+ fs = tests.map do |t|
171
+ File.directory?(t) ? Dir[File.join(t, '**', '*')] : Dir[t]
172
+ end
173
+ fs = fs.flatten.reject{ |f| File.directory?(f) }
174
+
175
+ ex = exclude.map do |x|
176
+ File.directory?(x) ? Dir[File.join(x, '**', '*')] : Dir[x]
177
+ end
178
+ ex = ex.flatten.reject{ |f| File.directory?(f) }
179
+
180
+ (fs - ex).uniq.map{ |f| File.expand_path(f) }
181
+ ).flatten
182
+ end
183
+
184
+ # TODO: Better name ?
185
+ def suite_name
186
+ files.map{ |path| File.dirname(path).sub(Dir.pwd+'/','') }.uniq.join(',')
187
+ end
188
+
189
+ # Get selected reporter with any mode decorator.
190
+ def reporter
191
+ @reporter ||= decorate_reporter(reporter_class.new($stdout, reporter_options))
192
+ end
193
+
194
+ # Load reporter based on output mode and return its class.
195
+ def reporter_class
196
+ rpt_format = format || :pretty
197
+ class_name = rpt_format.to_s.capitalize + "Reporter"
198
+
199
+ path = "turn/reporters/#{rpt_format}_reporter"
200
+
201
+ [File.expand_path('~'), Dir.pwd].each do |dir|
202
+ file = File.join(dir, ".turn", "reporters", "#{rpt_format}_reporter.rb")
203
+ path = file if File.exist?(file)
204
+ end
205
+
206
+ require path
207
+
208
+ Turn.const_get(class_name)
209
+ end
210
+
211
+ #
212
+ def decorate_reporter(reporter)
213
+ if mode
214
+ decorator_class.new(reporter)
215
+ else
216
+ reporter
217
+ end
218
+ end
219
+
220
+ #
221
+ def decorator_class
222
+ return nil unless mode
223
+
224
+ class_name = mode.to_s.capitalize + "Decorator"
225
+
226
+ path = "turn/decorators/#{mode}_decorator"
227
+ [File.expand_path('~'), Dir.pwd].each do |dir|
228
+ file = File.join(dir, ".turn", "decorators", "#{mode}_reporter.rb")
229
+ path = file if File.exist?(file)
230
+ end
231
+
232
+ require path
233
+
234
+ Turn.const_get(class_name)
235
+ end
236
+
237
+ #
238
+ def reporter_options
239
+ { :trace=>trace, :natural=>natural?, :verbose=>verbose?, :mark=>mark }
240
+ end
241
+
242
+ #
243
+ def environment_format
244
+ ENV['rpt']
245
+ end
246
+
247
+ #
248
+ def environment_mode
249
+ ENV['mode']
250
+ end
251
+
252
+ #
253
+ def environment_trace
254
+ (ENV['backtrace'] ? ENV['backtrace'].to_i : nil)
255
+ end
256
+
257
+ #
258
+ def environment_ansi
259
+ case ENV['ansi']
260
+ when 'true','yes','on'
261
+ true
262
+ when 'false','no','off'
263
+ false
264
+ else
265
+ nil
266
+ end
267
+ end
268
+
269
+ end
270
+
271
+ end