turn 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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