openlogic-turn 0.8.2
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/History.txt +54 -0
- data/README.txt +116 -0
- data/Rakefile +40 -0
- data/Release.txt +33 -0
- data/Version.txt +1 -0
- data/bin/turn +4 -0
- data/demo/test_autorun_minitest.rb +26 -0
- data/demo/test_autorun_testunit.rb +26 -0
- data/demo/test_sample.rb +35 -0
- data/demo/test_sample2.rb +33 -0
- data/lib/turn.rb +19 -0
- data/lib/turn/autorun/minitest.rb +155 -0
- data/lib/turn/autorun/testunit.rb +116 -0
- data/lib/turn/bin.rb +4 -0
- data/lib/turn/colorize.rb +65 -0
- data/lib/turn/command.rb +210 -0
- data/lib/turn/components/case.rb +104 -0
- data/lib/turn/components/method.rb +42 -0
- data/lib/turn/components/suite.rb +85 -0
- data/lib/turn/controller.rb +204 -0
- data/lib/turn/core_ext.rb +31 -0
- data/lib/turn/reporter.rb +69 -0
- data/lib/turn/reporters/cue_reporter.rb +167 -0
- data/lib/turn/reporters/dot_reporter.rb +93 -0
- data/lib/turn/reporters/marshal_reporter.rb +17 -0
- data/lib/turn/reporters/outline_reporter.rb +144 -0
- data/lib/turn/reporters/pretty_reporter.rb +184 -0
- data/lib/turn/reporters/progress_reporter.rb +116 -0
- data/lib/turn/runners/crossrunner.rb +42 -0
- data/lib/turn/runners/isorunner.rb +167 -0
- data/lib/turn/runners/loadrunner.rb +48 -0
- data/lib/turn/runners/minirunner.rb +189 -0
- data/lib/turn/runners/solorunner.rb +8 -0
- data/lib/turn/runners/testrunner.rb +166 -0
- data/test/helper.rb +97 -0
- data/test/runner +2 -0
- data/test/test_framework.rb +131 -0
- data/test/test_reporters.rb +44 -0
- data/test/test_runners.rb +45 -0
- metadata +138 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
module Turn
|
2
|
+
|
3
|
+
#
|
4
|
+
class TestMethod
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :file
|
7
|
+
attr_accessor :raised
|
8
|
+
attr_accessor :message
|
9
|
+
attr_accessor :backtrace
|
10
|
+
|
11
|
+
def initialize(name)
|
12
|
+
@name = name
|
13
|
+
@fail = false
|
14
|
+
@error = false
|
15
|
+
@raised = nil
|
16
|
+
@message = nil
|
17
|
+
@backtrace = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def fail!(assertion)
|
21
|
+
@fail, @error = true, false
|
22
|
+
@raised = assertion
|
23
|
+
@message = assertion.message
|
24
|
+
@backtrace = assertion.backtrace
|
25
|
+
end
|
26
|
+
|
27
|
+
def error!(exception)
|
28
|
+
@fail, @error = false, true
|
29
|
+
@raised = exception
|
30
|
+
@message = exception.message
|
31
|
+
@backtrace = exception.backtrace
|
32
|
+
end
|
33
|
+
|
34
|
+
def fail? ; @fail ; end
|
35
|
+
def error? ; @error ; end
|
36
|
+
def pass? ; !(@fail or @error) ; end
|
37
|
+
|
38
|
+
def to_s ; name ; end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Turn
|
2
|
+
|
3
|
+
#
|
4
|
+
class TestSuite
|
5
|
+
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_accessor :name
|
9
|
+
attr_accessor :size
|
10
|
+
attr_accessor :cases
|
11
|
+
|
12
|
+
# This one can be set manually since it
|
13
|
+
# is not calculatable (beyond the case level).
|
14
|
+
attr_accessor :count_assertions
|
15
|
+
|
16
|
+
#
|
17
|
+
def initialize(name=nil)
|
18
|
+
@name = name
|
19
|
+
@size = nil
|
20
|
+
@cases = []
|
21
|
+
|
22
|
+
#@count_tests = nil
|
23
|
+
#@count_assertions = nil
|
24
|
+
#@count_failures = nil
|
25
|
+
#@count_errors = nil
|
26
|
+
#@count_passes = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
def new_case(name, *files)
|
31
|
+
c = TestCase.new(name, *files)
|
32
|
+
@cases << c
|
33
|
+
c
|
34
|
+
end
|
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
|
+
|
48
|
+
def count_failures
|
49
|
+
#@count_failures ||= (
|
50
|
+
sum = 0; each{ |c| sum += c.count_failures }; sum
|
51
|
+
#)
|
52
|
+
end
|
53
|
+
|
54
|
+
def count_errors
|
55
|
+
#@count_errors ||= (
|
56
|
+
sum = 0; each{ |c| sum += c.count_errors }; sum
|
57
|
+
#)
|
58
|
+
end
|
59
|
+
|
60
|
+
def count_passes
|
61
|
+
#@count_passes ||= (
|
62
|
+
sum = 0; each{ |c| sum += c.count_passes }; sum
|
63
|
+
#)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Convenience methods --this is what is typcially wanted.
|
67
|
+
def counts
|
68
|
+
return count_tests, count_assertions, count_failures, count_errors #,count_skips
|
69
|
+
end
|
70
|
+
|
71
|
+
def each(&block)
|
72
|
+
@cases.each(&block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def size
|
76
|
+
@size ||= @cases.size
|
77
|
+
end
|
78
|
+
|
79
|
+
def passed?
|
80
|
+
(count_failures == 0 && count_errors == 0)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Turn
|
4
|
+
require 'turn/components/suite.rb'
|
5
|
+
require 'turn/components/case.rb'
|
6
|
+
require 'turn/components/method.rb'
|
7
|
+
|
8
|
+
# = Controller
|
9
|
+
#
|
10
|
+
#--
|
11
|
+
# TODO: Add support to test run loggging.
|
12
|
+
#++
|
13
|
+
class Controller
|
14
|
+
|
15
|
+
# File glob pattern of tests to run.
|
16
|
+
# Can be an array of files/globs.
|
17
|
+
attr_accessor :tests
|
18
|
+
|
19
|
+
# Files globs to specially exclude.
|
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
|
+
# Add these folders to the $LOAD_PATH.
|
27
|
+
attr_accessor :loadpath
|
28
|
+
|
29
|
+
# Libs to require when running tests.
|
30
|
+
attr_accessor :requires
|
31
|
+
|
32
|
+
# Reporter type.
|
33
|
+
attr_accessor :format
|
34
|
+
|
35
|
+
# Run mode.
|
36
|
+
attr_accessor :runmode
|
37
|
+
|
38
|
+
# Test against live install (i.e. Don't use loadpath option)
|
39
|
+
attr_accessor :live
|
40
|
+
|
41
|
+
# Log results? May be true/false or log file name. (TODO)
|
42
|
+
attr_accessor :log
|
43
|
+
|
44
|
+
# Verbose output?
|
45
|
+
attr_accessor :verbose
|
46
|
+
|
47
|
+
# Test framework, either :minitest or :testunit
|
48
|
+
attr_accessor :framework
|
49
|
+
|
50
|
+
def verbose? ; @verbose ; end
|
51
|
+
def live? ; @live ; end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
yield(self) if block_given?
|
57
|
+
initialize_defaults
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
def initialize_defaults
|
62
|
+
@loadpath ||= ['lib']
|
63
|
+
@tests ||= "test/**/{test,}*{,test}"
|
64
|
+
@exclude ||= []
|
65
|
+
@requires ||= []
|
66
|
+
@live ||= false
|
67
|
+
@log ||= true
|
68
|
+
#@reporter ||= OutlineReporter.new($stdout)
|
69
|
+
#@runner ||= RUBY_VERSION >= "1.9" ? MiniRunner : TestRunner
|
70
|
+
@pattern ||= /.*/
|
71
|
+
end
|
72
|
+
|
73
|
+
# Collect test configuation.
|
74
|
+
#def test_configuration(options={})
|
75
|
+
# #options = configure_options(options, 'test')
|
76
|
+
# #options['loadpath'] ||= metadata.loadpath
|
77
|
+
# options['tests'] ||= self.tests
|
78
|
+
# options['loadpath'] ||= self.loadpath
|
79
|
+
# options['requires'] ||= self.requires
|
80
|
+
# options['live'] ||= self.live
|
81
|
+
# options['exclude'] ||= self.exclude
|
82
|
+
# #options['tests'] = list_option(options['tests'])
|
83
|
+
# options['loadpath'] = list_option(options['loadpath'])
|
84
|
+
# options['exclude'] = list_option(options['exclude'])
|
85
|
+
# options['require'] = list_option(options['require'])
|
86
|
+
# return options
|
87
|
+
#end
|
88
|
+
|
89
|
+
#
|
90
|
+
def list_option(list)
|
91
|
+
case list
|
92
|
+
when nil
|
93
|
+
[]
|
94
|
+
when Array
|
95
|
+
list
|
96
|
+
else
|
97
|
+
list.split(/[:;]/)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
public
|
102
|
+
|
103
|
+
def loadpath=(paths)
|
104
|
+
@loadpath = list_option(paths)
|
105
|
+
end
|
106
|
+
|
107
|
+
def exclude=(paths)
|
108
|
+
@exclude = list_option(paths)
|
109
|
+
end
|
110
|
+
|
111
|
+
def requires=(paths)
|
112
|
+
@requires = list_option(paths)
|
113
|
+
end
|
114
|
+
|
115
|
+
def files
|
116
|
+
@files ||= (
|
117
|
+
fs = tests.map do |t|
|
118
|
+
File.directory?(t) ? Dir[File.join(t, '**', '*')] : Dir[t]
|
119
|
+
end
|
120
|
+
fs = fs.flatten.reject{ |f| File.directory?(f) }
|
121
|
+
ex = exclude.map do |x|
|
122
|
+
File.directory?(x) ? Dir[File.join(x, '**', '*')] : Dir[x]
|
123
|
+
end
|
124
|
+
ex = ex.flatten.reject{ |f| File.directory?(f) }
|
125
|
+
(fs - ex).uniq.map{ |f| File.expand_path(f) }
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
def start
|
130
|
+
@files = nil # reset files just in case
|
131
|
+
|
132
|
+
if files.empty?
|
133
|
+
$stderr.puts "No tests."
|
134
|
+
return
|
135
|
+
end
|
136
|
+
|
137
|
+
testrun = runner.new(self)
|
138
|
+
|
139
|
+
testrun.start
|
140
|
+
end
|
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
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
@@ -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
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Turn
|
2
|
+
require 'turn/colorize'
|
3
|
+
require 'turn/core_ext'
|
4
|
+
|
5
|
+
# = Reporter
|
6
|
+
#
|
7
|
+
# There are two distinct way in which a report may be utilized
|
8
|
+
# by a Runner: per-call or per-file. The method #pass, #fail
|
9
|
+
# and #error are generic, and will be used in either case.
|
10
|
+
# A per-call runner will use all the methods of a Reporter,
|
11
|
+
# while a per-file runner will use start_case per file,
|
12
|
+
# and will not use the start_test and finish_test methods,
|
13
|
+
# since those are beyond it's grainularity.
|
14
|
+
#
|
15
|
+
class Reporter
|
16
|
+
|
17
|
+
include Colorize
|
18
|
+
|
19
|
+
attr :io
|
20
|
+
|
21
|
+
def initialize(io)
|
22
|
+
@io = io || $stdout
|
23
|
+
end
|
24
|
+
|
25
|
+
# These methods are called in the process of running the tests.
|
26
|
+
|
27
|
+
def start_suite(test_suite)
|
28
|
+
end
|
29
|
+
|
30
|
+
def start_case(test_case)
|
31
|
+
end
|
32
|
+
|
33
|
+
def start_test(test)
|
34
|
+
end
|
35
|
+
|
36
|
+
def pass(message=nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def fail(assertion, message=nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
def error(exception, message=nil)
|
43
|
+
end
|
44
|
+
|
45
|
+
def finish_test(test)
|
46
|
+
end
|
47
|
+
|
48
|
+
def finish_case(test_case)
|
49
|
+
end
|
50
|
+
|
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+'/', '') }
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'turn/reporter'
|
2
|
+
|
3
|
+
module Turn
|
4
|
+
|
5
|
+
# = Cue Reporter
|
6
|
+
#
|
7
|
+
# Inspired by Shindo.
|
8
|
+
#
|
9
|
+
class CueReporter < Reporter
|
10
|
+
|
11
|
+
def start_suite(suite)
|
12
|
+
@suite = suite
|
13
|
+
@time = Time.now
|
14
|
+
@stdout = StringIO.new
|
15
|
+
@stderr = StringIO.new
|
16
|
+
#files = suite.collect{ |s| s.file }.join(' ')
|
17
|
+
io.puts "Loaded suite #{suite.name}"
|
18
|
+
#io.puts "Started"
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_case(kase)
|
22
|
+
io.puts(kase.name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_test(test)
|
26
|
+
#if @file != test.file
|
27
|
+
# @file = test.file
|
28
|
+
# io.puts(test.file)
|
29
|
+
#end
|
30
|
+
io.print Colorize.blue(" %-69s" % test.name)
|
31
|
+
$stdout = @stdout
|
32
|
+
$stderr = @stderr
|
33
|
+
$stdout.rewind
|
34
|
+
$stderr.rewind
|
35
|
+
end
|
36
|
+
|
37
|
+
def pass(message=nil)
|
38
|
+
io.puts " #{PASS}"
|
39
|
+
if message
|
40
|
+
message = Colorize.green(message)
|
41
|
+
message = message.to_s.tabto(8)
|
42
|
+
io.puts(message)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def fail(assertion, message=nil)
|
47
|
+
io.puts(" #{FAIL}")
|
48
|
+
#message = assertion.location[0] + "\n" + assertion.message #.gsub("\n","\n")
|
49
|
+
message = message || assertion.to_s
|
50
|
+
#if message
|
51
|
+
message = Colorize.red(message)
|
52
|
+
message = message.to_s.tabto(8)
|
53
|
+
io.puts(message)
|
54
|
+
#end
|
55
|
+
|
56
|
+
show_captured_output
|
57
|
+
|
58
|
+
prompt
|
59
|
+
end
|
60
|
+
|
61
|
+
def error(exception, message=nil)
|
62
|
+
#message = exception.to_s.split("\n")[2..-1].join("\n")
|
63
|
+
message = message || exception.to_s
|
64
|
+
io.puts("#{ERROR}")
|
65
|
+
io.puts(message) #if message
|
66
|
+
|
67
|
+
prompt
|
68
|
+
end
|
69
|
+
|
70
|
+
def finish_test(test)
|
71
|
+
$stdout = STDOUT
|
72
|
+
$stderr = STDERR
|
73
|
+
end
|
74
|
+
|
75
|
+
def show_captured_output
|
76
|
+
show_captured_stdout
|
77
|
+
show_captured_stderr
|
78
|
+
end
|
79
|
+
|
80
|
+
def show_captured_stdout
|
81
|
+
@stdout.rewind
|
82
|
+
return if @stdout.eof?
|
83
|
+
STDOUT.puts(<<-output.tabto(8))
|
84
|
+
\nSTDOUT:
|
85
|
+
#{@stdout.read}
|
86
|
+
output
|
87
|
+
end
|
88
|
+
|
89
|
+
def show_captured_stderr
|
90
|
+
@stderr.rewind
|
91
|
+
return if @stderr.eof?
|
92
|
+
STDOUT.puts(<<-output.tabto(8))
|
93
|
+
\nSTDERR:
|
94
|
+
#{@stderr.read}
|
95
|
+
output
|
96
|
+
end
|
97
|
+
|
98
|
+
#def finish_case(kase)
|
99
|
+
#end
|
100
|
+
|
101
|
+
def finish_suite(suite)
|
102
|
+
total = suite.count_tests
|
103
|
+
failure = suite.count_failures
|
104
|
+
error = suite.count_errors
|
105
|
+
pass = total - failure - error
|
106
|
+
|
107
|
+
bar = '=' * 78
|
108
|
+
if COLORIZE
|
109
|
+
bar = if pass == total then Colorize.green(bar)
|
110
|
+
else Colorize.red(bar) end
|
111
|
+
end
|
112
|
+
|
113
|
+
tally = [total, suite.count_assertions]
|
114
|
+
|
115
|
+
io.puts bar
|
116
|
+
io.puts " pass: %d, fail: %d, error: %d" % [pass, failure, error]
|
117
|
+
io.puts " total: %d tests with %d assertions in #{Time.new - @time} seconds" % tally
|
118
|
+
io.puts bar
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def prompt
|
124
|
+
begin
|
125
|
+
io << " [c,i,q,r,t,#,?] "
|
126
|
+
io.flush
|
127
|
+
until inp = $stdin.gets ; sleep 1 ; end
|
128
|
+
answer = inp.strip
|
129
|
+
case answer
|
130
|
+
when 'c', ''
|
131
|
+
when 'r'
|
132
|
+
# how to reload and start over?
|
133
|
+
when 'i'
|
134
|
+
# how to drop into an interactive console?
|
135
|
+
when 't'
|
136
|
+
io.puts $@
|
137
|
+
raise ArgumentError
|
138
|
+
when /^\d+$/
|
139
|
+
io.puts $@[0..answer.to_i]
|
140
|
+
raise ArgumentError
|
141
|
+
when 'q'
|
142
|
+
exit -1
|
143
|
+
when '?'
|
144
|
+
io.puts HELP
|
145
|
+
raise ArgumentError #prompt
|
146
|
+
else
|
147
|
+
raise ArgumentError
|
148
|
+
end
|
149
|
+
rescue ArgumentError
|
150
|
+
retry
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
HELP = %{
|
155
|
+
c continue
|
156
|
+
r restart
|
157
|
+
i irb
|
158
|
+
t backtrace
|
159
|
+
# backtrace lines
|
160
|
+
q quit
|
161
|
+
? help
|
162
|
+
}
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|