turn 0.7.0 → 0.8.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.
data/lib/turn/command.rb CHANGED
@@ -1,165 +1,210 @@
1
- # Turn - Pretty Unit Test Runner for Ruby
2
- #
3
- # SYNOPSIS
4
- # turn [OPTIONS] [RUN MODE] [OUTPUT MODE] [test globs...]
5
- #
6
- # OPTIONS
7
- # -h --help display this help information
8
- # --live don't use loadpath
9
- # --log log results to a file
10
- # -n --name=PATTERN only run tests that match regexp PATTERN
11
- # -I --loadpath=PATHS add given paths to the $LOAD_PATH
12
- # -r --requires=PATHS require given paths before running tests
13
- #
14
- # RUN MODES
15
- # --normal run all tests in a single process [default]
16
- # --solo run each test in a separate process
17
- # --cross run each pair of test files in a separate process
18
- #
19
- # OUTPUT MODES
20
- # -O --outline turn's original case/test outline mode [default]
21
- # -P --progress indicates progress with progress bar
22
- # -D --dotted test/unit's traditonal dot-progress mode
23
- # -M --marshal dump output as YAML (normal run mode only)
24
-
25
- require 'getoptlong'
1
+ require 'optparse'
26
2
  require 'turn/controller'
27
3
 
28
- #RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
4
+ module Turn
29
5
 
30
- original_argv = ARGV.dup
6
+ # Turn - Pretty Unit Test Runner for Ruby
7
+ #
8
+ # 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
+ #
20
+ # 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
+ #
25
+ # 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
32
+ #
33
+ class Command
31
34
 
32
- opts = GetoptLong.new(
33
- [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
34
- [ '--live', GetoptLong::NO_ARGUMENT ],
35
- [ '--log', GetoptLong::OPTIONAL_ARGUMENT ],
36
- [ '--name', '-n', GetoptLong::REQUIRED_ARGUMENT ],
37
- [ '--loadpath', '-I', GetoptLong::REQUIRED_ARGUMENT ],
38
- [ '--requires', '-r', GetoptLong::REQUIRED_ARGUMENT ],
35
+ # Shortcut for new.main(*argv)
36
+ def self.main(*argv)
37
+ new.main(*argv)
38
+ end
39
39
 
40
- # RUN MODES
41
- [ '--normal', GetoptLong::NO_ARGUMENT ],
42
- [ '--solo', GetoptLong::NO_ARGUMENT ],
43
- [ '--cross', GetoptLong::NO_ARGUMENT ],
44
- #[ '--load', GetoptLong::NO_ARGUMENT ],
40
+ # Log output.
41
+ attr :log
45
42
 
46
- # OUTPUT MODES
47
- [ '--outline', '-O', GetoptLong::NO_ARGUMENT ],
48
- [ '--progress', '-P', GetoptLong::NO_ARGUMENT ],
49
- [ '--dotted', '-D', GetoptLong::NO_ARGUMENT ],
50
- [ '--marshal', '-M', GetoptLong::NO_ARGUMENT ]
51
- )
52
-
53
- live = nil
54
- log = nil
55
- pattern = nil
56
- loadpath = []
57
- requires = []
58
-
59
- runmode = nil
60
- outmode = nil
61
-
62
- opts.each do |opt, arg|
63
- case opt
64
- when '--help'
65
- help, rest = File.read(__FILE__).split(/^\s*$/)
66
- puts help.gsub(/^\#[ ]{0,1}/,'')
67
- exit
68
-
69
- when '--live'
70
- live = true
71
- when '--log'
72
- log = true
73
- when '--name'
74
- pattern = Regexp.new(arg, Regexp::IGNORECASE)
75
- when '--loadpath'
76
- loadpath << arg
77
- when '--requires'
78
- requires << arg
79
-
80
- when '--solo'
81
- runmode = :solo
82
- when '--cross'
83
- runmode = :cross
84
- when '--marshal'
85
- runmode = :marshal
86
- outmode = :marshal
87
- when '--progress'
88
- outmode = :progress
89
- when '--outline'
90
- outmode = :outline
91
- when '--dotted'
92
- outmode = :dotted
93
- end
94
- end
43
+ # Do not use local loadpath.
44
+ attr :live
95
45
 
96
- loadpath = ['lib'] if loadpath.empty?
46
+ # Only run tests matching this pattern.
47
+ attr :pattern
97
48
 
98
- tests = ARGV.empty? ? nil : ARGV.dup
49
+ # List of paths to add to $LOAD_PATH
50
+ attr :loadpath
99
51
 
100
- case outmode
101
- when :marshal
102
- reporter = Turn::MarshalReporter.new($stdout)
103
- when :progress
104
- reporter = Turn::ProgressReporter.new($stdout)
105
- when :dotted
106
- reporter = Turn::DotReporter.new($stdout)
107
- else
108
- reporter = Turn::OutlineReporter.new($stdout)
109
- end
52
+ # Libraries to require before running tests.
53
+ attr :requires
110
54
 
111
- case runmode
112
- when :marshal
113
- require 'turn/runners/testrunner'
114
- runner = Turn::TestRunner
115
- when :solo
116
- require 'turn/runners/solorunner'
117
- runner = Turn::SoloRunner
118
- when :cross
119
- require 'turn/runners/crossrunner'
120
- runner = Turn::CrossRunner
121
- else
122
- require 'turn/runners/testrunner'
123
- runner = Turn::TestRunner
124
- end
55
+ # Framework to use, :minitest or :testunit.
56
+ attr :framework
125
57
 
126
- controller = Turn::Controller.new do |c|
127
- c.live = live
128
- c.log = log
129
- c.loadpath = loadpath
130
- c.requires = requires
131
- c.tests = tests
132
- c.runner = runner
133
- c.reporter = reporter
134
- c.pattern = pattern
135
- end
58
+ # Run mode.
59
+ attr :runmode
136
60
 
137
- controller.start
61
+ # Output mode.
62
+ attr :outmode
138
63
 
139
- =begin
140
- else
64
+ #
65
+ def initialize
66
+ @live = nil
67
+ @log = nil
68
+ @pattern = nil
69
+ @loadpath = []
70
+ @requires = []
71
+ @runmode = nil
72
+ @outmode = nil
73
+ @framework = RUBY_VERSION >= "1.9" ? :minitest : :testunit
74
+ end
141
75
 
142
- begin
143
- require 'turn/adapters/testunit' # 'turn'
144
- rescue LoadError
145
- require 'rubygems'
146
- require 'turn/adapters/testunit' # 'turn'
147
- end
76
+ #
77
+ def option_parser
78
+ OptionParser.new do |opts|
148
79
 
149
- ARGV.each{ |a| Dir[a].each{ |f| require f }}
150
- Turn::TestRunner.run(TS_MyTests)
80
+ opts.banner = "Turn - Pretty Unit Test Runner for Ruby"
151
81
 
152
- #RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
153
- #
154
- #begin
155
- # require 'turn'
156
- # Kernel.exec(RUBY, '-r', 'turn', *ARGV)
157
- #rescue LoadError
158
- # require 'rubygems'
159
- # require 'turn'
160
- # Kernel.exec(RUBY, '-rubygems', '-r', 'turn', *ARGV)
161
- #end
82
+ opts.separator " "
83
+ opts.separator "SYNOPSIS"
84
+ opts.separator " turn [OPTIONS] [RUN MODE] [OUTPUT MODE] [TEST GLOBS ...]"
162
85
 
163
- end
164
- =end
86
+ opts.separator " "
87
+ opts.separator "GENERAL OPTIONS"
165
88
 
89
+ opts.on('-I', '--loadpath=PATHS', "add paths to $LOAD_PATH") do |path|
90
+ @loadpath.concat(path.split(':'))
91
+ end
92
+
93
+ opts.on('-r', '--require=LIBS', "require libraries") do |lib|
94
+ @requires.concat(lib.split(':'))
95
+ end
96
+
97
+ opts.on('-n', '--name=PATTERN', "only run tests that match PATTERN") do |pattern|
98
+ @pattern = Regexp.new(pattern, Regexp::IGNORECASE)
99
+ end
100
+
101
+ opts.on('-m', '--minitest', "Force use of MiniTest framework") do
102
+ @framework = :minitest
103
+ end
104
+
105
+ # Turn does not support Test::Unit 2.0+
106
+ #opts.on('-u', '--testunit', "Force use of TestUnit framework") do
107
+ # @framework = :testunit
108
+ #end
109
+
110
+ opts.on('--log', "log results to a file") do #|path|
111
+ @log = true # TODO: support path/file
112
+ end
113
+
114
+ opts.on('--live', "do not use local load path") do
115
+ @live = true
116
+ end
117
+
118
+ opts.separator " "
119
+ opts.separator "RUN MODES"
120
+
121
+ opts.on('--normal', "run all tests in a single process [default]") do
122
+ @runmode = nil
123
+ end
124
+
125
+ opts.on('--solo', "run each test in a separate process") do
126
+ @runmode = :solo
127
+ end
128
+
129
+ opts.on('--cross', "run each pair of test files in a separate process") do
130
+ @runmode = :cross
131
+ end
132
+
133
+ #opts.on('--load', "") do
134
+ #end
135
+
136
+ opts.separator " "
137
+ opts.separator "OUTPUT MODES"
138
+
139
+ opts.on('--outline', '-O', "turn's original case/test outline mode [default]") do
140
+ @outmode = :outline
141
+ end
142
+
143
+ opts.on('--progress', '-P', "indicates progress with progress bar") do
144
+ @outmode = :progress
145
+ end
146
+
147
+ opts.on('--dotted', '-D', "test-unit's traditonal dot-progress mode") do
148
+ @outmode = :dotted
149
+ end
150
+
151
+ opts.on('--pretty', '-T', "new pretty output mode") do
152
+ @outmode = :pretty
153
+ end
154
+
155
+ opts.on('--cue', '-C', "cue for action on each failure/error") do
156
+ @outmode = :cue
157
+ end
158
+
159
+ opts.on('--marshal', '-M', "dump output as YAML (normal run mode only)") do
160
+ @runmode = :marshal
161
+ @outmode = :marshal
162
+ end
163
+
164
+ opts.separator " "
165
+ opts.separator "COMMAND OPTIONS"
166
+
167
+ opts.on('--debug', "turn debug mode on") do
168
+ $VERBOSE = true
169
+ $DEBUG = true
170
+ end
171
+
172
+ opts.on_tail('--help', '-h', "display this help information") do
173
+ puts opts
174
+ exit
175
+ end
176
+ end
177
+ end
178
+
179
+ # Run command.
180
+ def main(*argv)
181
+ option_parser.parse!(argv)
182
+
183
+ @loadpath = ['lib'] if loadpath.empty?
184
+
185
+ tests = ARGV.empty? ? nil : ARGV.dup
186
+
187
+ controller = Turn::Controller.new do |c|
188
+ c.live = live
189
+ c.log = log
190
+ c.loadpath = loadpath
191
+ c.requires = requires
192
+ c.tests = tests
193
+ c.runmode = runmode
194
+ c.format = outmode
195
+ c.pattern = pattern
196
+ c.framework = framework
197
+ end
198
+
199
+ result = controller.start
200
+
201
+ if result
202
+ exit result.passed?
203
+ else # no tests
204
+ exit
205
+ end
206
+ end
207
+
208
+ end
209
+
210
+ end
@@ -2,6 +2,7 @@ module Turn
2
2
 
3
3
  #
4
4
  class TestCase
5
+ include Enumerable
5
6
 
6
7
  # Name of test case.
7
8
  attr_accessor :name
@@ -17,7 +18,7 @@ module Turn
17
18
  #attr_accessor :count_errors
18
19
  #attr_accessor :count_tests
19
20
 
20
- # This can;t be calculated, so it must be
21
+ # This can't be calculated, so it must be
21
22
  # assigned by the runner.
22
23
  attr_accessor :count_assertions
23
24
 
@@ -71,6 +72,8 @@ module Turn
71
72
  tests.size
72
73
  end
73
74
 
75
+ alias_method :size, :count_tests
76
+
74
77
  def count_failures
75
78
  sum = 0; tests.each{ |t| sum += 1 if t.fail? }; sum
76
79
  end
@@ -92,6 +95,9 @@ module Turn
92
95
  tests.collect{ |t| t.message }.join("\n")
93
96
  end
94
97
 
98
+ def each(&block)
99
+ tests.each(&block)
100
+ end
95
101
  end
96
102
 
97
103
  end
@@ -4,28 +4,38 @@ module Turn
4
4
  class TestMethod
5
5
  attr_accessor :name
6
6
  attr_accessor :file
7
+ attr_accessor :raised
7
8
  attr_accessor :message
9
+ attr_accessor :backtrace
8
10
 
9
11
  def initialize(name)
10
- @name = name
11
- @fail = false
12
- @error = false
13
- @message = nil
12
+ @name = name
13
+ @fail = false
14
+ @error = false
15
+ @raised = nil
16
+ @message = nil
17
+ @backtrace = []
14
18
  end
15
19
 
16
- def fail!(message=nil)
20
+ def fail!(assertion)
17
21
  @fail, @error = true, false
18
- @message = message if message
22
+ @rasied = assertion
23
+ @message = assertion.message
24
+ @backtrace = assertion.backtrace
19
25
  end
20
26
 
21
- def error!(message=nil)
27
+ def error!(exception)
22
28
  @fail, @error = false, true
23
- @message = message if message
29
+ @rasied = exception
30
+ @message = exception.message
31
+ @backtrace = exception.backtrace
24
32
  end
25
33
 
26
34
  def fail? ; @fail ; end
27
35
  def error? ; @error ; end
28
36
  def pass? ; !(@fail or @error) ; end
37
+
38
+ def to_s ; name ; end
29
39
  end
30
40
 
31
41
  end
@@ -33,6 +33,18 @@ module Turn
33
33
  c
34
34
  end
35
35
 
36
+ def count_tests
37
+ #@count_tests ||= (
38
+ sum = 0; each{ |c| sum += c.count_tests }; sum
39
+ #)
40
+ end
41
+
42
+ def count_assertions
43
+ #@count_assertions ||= (
44
+ sum = 0; each{ |c| sum += c.count_assertions }; sum
45
+ #)
46
+ end
47
+
36
48
  def count_failures
37
49
  #@count_failures ||= (
38
50
  sum = 0; each{ |c| sum += c.count_failures }; sum
@@ -51,21 +63,9 @@ module Turn
51
63
  #)
52
64
  end
53
65
 
54
- def count_tests
55
- #@count_tests ||= (
56
- sum = 0; each{ |c| sum += c.count_tests }; sum
57
- #)
58
- end
59
-
60
- def count_assertions
61
- #@count_assertions ||= (
62
- sum = 0; each{ |c| sum += c.count_assertions }; sum
63
- #)
64
- end
65
-
66
66
  # Convenience methods --this is what is typcially wanted.
67
67
  def counts
68
- return count_tests, count_assertions, count_failures, count_errors
68
+ return count_tests, count_assertions, count_failures, count_errors #,count_skips
69
69
  end
70
70
 
71
71
  def each(&block)
@@ -76,6 +76,9 @@ module Turn
76
76
  @size ||= @cases.size
77
77
  end
78
78
 
79
+ def passed?
80
+ (count_failures == 0 && count_errors == 0)
81
+ end
79
82
  end
80
83
 
81
84
  end
@@ -5,15 +5,6 @@ module Turn
5
5
  require 'turn/components/case.rb'
6
6
  require 'turn/components/method.rb'
7
7
 
8
- require 'turn/reporters/outline_reporter'
9
- require 'turn/reporters/marshal_reporter'
10
- require 'turn/reporters/progress_reporter'
11
- require 'turn/reporters/dot_reporter'
12
-
13
- require 'turn/runners/testrunner'
14
- require 'turn/runners/solorunner'
15
- require 'turn/runners/crossrunner'
16
-
17
8
  # = Controller
18
9
  #
19
10
  #--
@@ -38,11 +29,11 @@ module Turn
38
29
  # Libs to require when running tests.
39
30
  attr_accessor :requires
40
31
 
41
- # Instance of Reporter.
42
- attr_accessor :reporter
32
+ # Reporter type.
33
+ attr_accessor :format
43
34
 
44
- # Insatance of Runner.
45
- attr_accessor :runner
35
+ # Run mode.
36
+ attr_accessor :runmode
46
37
 
47
38
  # Test against live install (i.e. Don't use loadpath option)
48
39
  attr_accessor :live
@@ -53,6 +44,9 @@ module Turn
53
44
  # Verbose output?
54
45
  attr_accessor :verbose
55
46
 
47
+ # Test framework, either :minitest or :testunit
48
+ attr_accessor :framework
49
+
56
50
  def verbose? ; @verbose ; end
57
51
  def live? ; @live ; end
58
52
 
@@ -71,8 +65,8 @@ module Turn
71
65
  @requires ||= []
72
66
  @live ||= false
73
67
  @log ||= true
74
- @reporter ||= OutlineReporter.new($stdout)
75
- @runner ||= TestRunner.new
68
+ #@reporter ||= OutlineReporter.new($stdout)
69
+ #@runner ||= RUBY_VERSION >= "1.9" ? MiniRunner : TestRunner
76
70
  @pattern ||= /.*/
77
71
  end
78
72
 
@@ -128,7 +122,7 @@ module Turn
128
122
  File.directory?(x) ? Dir[File.join(x, '**', '*')] : Dir[x]
129
123
  end
130
124
  ex = ex.flatten.reject{ |f| File.directory?(f) }
131
- (fs - ex).uniq
125
+ (fs - ex).uniq.map{ |f| File.expand_path(f) }
132
126
  )
133
127
  end
134
128
 
@@ -145,6 +139,65 @@ module Turn
145
139
  testrun.start
146
140
  end
147
141
 
142
+ # Select reporter based on output mode.
143
+ def reporter
144
+ @reporter ||= (
145
+ case format
146
+ when :marshal
147
+ require 'turn/reporters/marshal_reporter'
148
+ Turn::MarshalReporter.new($stdout)
149
+ when :progress
150
+ require 'turn/reporters/progress_reporter'
151
+ Turn::ProgressReporter.new($stdout)
152
+ when :dotted
153
+ require 'turn/reporters/dot_reporter'
154
+ Turn::DotReporter.new($stdout)
155
+ when :pretty
156
+ require 'turn/reporters/pretty_reporter'
157
+ Turn::PrettyReporter.new($stdout)
158
+ when :cue
159
+ require 'turn/reporters/cue_reporter'
160
+ Turn::CueReporter.new($stdout)
161
+ else
162
+ require 'turn/reporters/outline_reporter'
163
+ Turn::OutlineReporter.new($stdout)
164
+ end
165
+ )
166
+ end
167
+
168
+ # # Insatance of Runner, selected based on format and runmode.
169
+ def runner
170
+ @runner ||= (
171
+ case framework
172
+ when :minitest
173
+ require 'turn/runners/minirunner'
174
+ else
175
+ require 'turn/runners/testrunner'
176
+ end
177
+
178
+ case runmode
179
+ when :marshal
180
+ if framework == :minitest
181
+ Turn::MiniRunner
182
+ else
183
+ Turn::TestRunner
184
+ end
185
+ when :solo
186
+ require 'turn/runners/solorunner'
187
+ Turn::SoloRunner
188
+ when :cross
189
+ require 'turn/runners/crossrunner'
190
+ Turn::CrossRunner
191
+ else
192
+ if framework == :minitest
193
+ Turn::MiniRunner
194
+ else
195
+ Turn::TestRunner
196
+ end
197
+ end
198
+ )
199
+ end
200
+
148
201
  end
149
202
 
150
203
  end
@@ -0,0 +1,31 @@
1
+ # Borrowed methods from Ruby Facets.
2
+
3
+ class String
4
+
5
+ # Aligns each line n spaces.
6
+ def tab(n)
7
+ gsub(/^ */, ' ' * n)
8
+ end
9
+
10
+ # Preserves relative tabbing.
11
+ # The first non-empty line ends up with n spaces before nonspace.
12
+ def tabto(n)
13
+ if self =~ /^( *)\S/
14
+ indent(n - $1.length)
15
+ else
16
+ self
17
+ end
18
+ end
19
+
20
+ # Indent left or right by n spaces.
21
+ # (This used to be called #tab and aliased as #indent.)
22
+ def indent(n, c=' ')
23
+ if n >= 0
24
+ gsub(/^/, c * n)
25
+ else
26
+ gsub(/^#{Regexp.escape(c)}{0,#{-n}}/, "")
27
+ end
28
+ end
29
+
30
+ end
31
+
data/lib/turn/reporter.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  module Turn
2
2
  require 'turn/colorize'
3
+ require 'turn/core_ext'
3
4
 
4
5
  # = Reporter
5
6
  #
@@ -23,10 +24,10 @@ module Turn
23
24
 
24
25
  # These methods are called in the process of running the tests.
25
26
 
26
- def start_suite(suite)
27
+ def start_suite(test_suite)
27
28
  end
28
29
 
29
- def start_case(kase)
30
+ def start_case(test_case)
30
31
  end
31
32
 
32
33
  def start_test(test)
@@ -35,19 +36,31 @@ module Turn
35
36
  def pass(message=nil)
36
37
  end
37
38
 
38
- def fail(message=nil)
39
+ def fail(assertion, message=nil)
39
40
  end
40
41
 
41
- def error(message=nil)
42
+ def error(exception, message=nil)
42
43
  end
43
44
 
44
45
  def finish_test(test)
45
46
  end
46
47
 
47
- def finish_case(kase)
48
+ def finish_case(test_case)
48
49
  end
49
50
 
50
- def finish_suite(suite)
51
+ def finish_suite(test_suite)
52
+ end
53
+
54
+ private
55
+
56
+ # TODO: backtrace filter probably could use some refinement.
57
+ def filter_backtrace(bt)
58
+ return [] unless bt
59
+ bt.reject!{ |line| line.rindex('minitest') }
60
+ bt.reject!{ |line| line.rindex('test/unit') }
61
+ bt.reject!{ |line| line.rindex('lib/turn') }
62
+ bt.reject!{ |line| line.rindex('bin/turn') }
63
+ bt.map{ |line| line.sub(Dir.pwd+'/', '') }
51
64
  end
52
65
 
53
66
  end