rubydoctest 0.2.1
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 +14 -0
- data/License.txt +20 -0
- data/Manifest.txt +31 -0
- data/PostInstall.txt +8 -0
- data/README.txt +109 -0
- data/Rakefile +4 -0
- data/bin/rubydoctest +35 -0
- data/config/hoe.rb +74 -0
- data/config/requirements.rb +15 -0
- data/lib/rubydoctest.rb +271 -0
- data/lib/rubydoctest/version.rb +9 -0
- data/rubydoctest.gemspec +32 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/doctests.rake +28 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/doctest/file_relative.doctest +5 -0
- data/test/doctest/runner.doctest +58 -0
- data/test/doctest/simple.doctest +30 -0
- data/test/test_helper.rb +2 -0
- data/test/test_rubydoctest.rb +11 -0
- data/website/index.html +11 -0
- data/website/index.txt +83 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +99 -0
data/History.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
== 0.2.1 2008-05-26
|
2
|
+
|
3
|
+
* Adding self-doctesting doctests
|
4
|
+
|
5
|
+
== 0.2.0 2008-05-25
|
6
|
+
|
7
|
+
* Initial changes by Dr Nic
|
8
|
+
* __FILE__ is changed to the explicit file path (since it was eval'ing to the code, not the test file)
|
9
|
+
* Starting to write doctests for the project itself
|
10
|
+
|
11
|
+
== 0.1.0 2008-05-25
|
12
|
+
|
13
|
+
* 1 major enhancement:
|
14
|
+
* Initial release from Tom's personal stash of code
|
data/License.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 FIXME full name
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
PostInstall.txt
|
5
|
+
README.txt
|
6
|
+
Rakefile
|
7
|
+
bin/rubydoctest
|
8
|
+
config/hoe.rb
|
9
|
+
config/requirements.rb
|
10
|
+
lib/rubydoctest.rb
|
11
|
+
lib/rubydoctest/version.rb
|
12
|
+
rubydoctest.gemspec
|
13
|
+
script/console
|
14
|
+
script/destroy
|
15
|
+
script/generate
|
16
|
+
script/txt2html
|
17
|
+
setup.rb
|
18
|
+
tasks/deployment.rake
|
19
|
+
tasks/doctests.rake
|
20
|
+
tasks/environment.rake
|
21
|
+
tasks/website.rake
|
22
|
+
test/doctest/file_relative.doctest
|
23
|
+
test/doctest/runner.doctest
|
24
|
+
test/doctest/simple.doctest
|
25
|
+
test/test_helper.rb
|
26
|
+
test/test_rubydoctest.rb
|
27
|
+
website/index.html
|
28
|
+
website/index.txt
|
29
|
+
website/javascripts/rounded_corners_lite.inc.js
|
30
|
+
website/stylesheets/screen.css
|
31
|
+
website/template.html.erb
|
data/PostInstall.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
= rubydoctest
|
2
|
+
|
3
|
+
* http://github.com/tablatom/rubydoctest
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Ruby version of Python's doctest tool, but a bit different.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* FIX (list of features or problems)
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
rubydoctest comes as an executable that takes a file or directory:
|
16
|
+
|
17
|
+
rubydoctest .
|
18
|
+
rubydoctest simple.doctest
|
19
|
+
|
20
|
+
== EXAMPLE:
|
21
|
+
|
22
|
+
Here is an example doctest file (say called simple.doctest):
|
23
|
+
|
24
|
+
# Simple test of RubyDocTest
|
25
|
+
|
26
|
+
This is an example test
|
27
|
+
|
28
|
+
>> 1 + 2
|
29
|
+
=> 3
|
30
|
+
|
31
|
+
And here's a test that will fail
|
32
|
+
|
33
|
+
>> 1 + 2
|
34
|
+
=> 4
|
35
|
+
|
36
|
+
Test a some multiline statements
|
37
|
+
|
38
|
+
>>
|
39
|
+
class Person
|
40
|
+
attr_accessor :name
|
41
|
+
end
|
42
|
+
|
43
|
+
>> Person
|
44
|
+
=> Person
|
45
|
+
>> p = Person.new
|
46
|
+
>> p.name = "Tom"
|
47
|
+
>> p.name
|
48
|
+
=> "Tom"
|
49
|
+
|
50
|
+
|
51
|
+
>> "a
|
52
|
+
b"
|
53
|
+
=> "a\nb"
|
54
|
+
|
55
|
+
>> 1 +
|
56
|
+
?> 2
|
57
|
+
=> 3
|
58
|
+
|
59
|
+
== INSTALL:
|
60
|
+
|
61
|
+
Major releases:
|
62
|
+
|
63
|
+
sudo gem install rubydoctest
|
64
|
+
|
65
|
+
Build from source:
|
66
|
+
|
67
|
+
git clone git://github.com/tablatom/rubydoctest.git
|
68
|
+
cd rubydoctest
|
69
|
+
rake manifest && rake install
|
70
|
+
|
71
|
+
== SELF-DOCTESTING:
|
72
|
+
|
73
|
+
Ruby DocTest uses itself to test and document itself.
|
74
|
+
|
75
|
+
rake test:doctest
|
76
|
+
|
77
|
+
In development of Ruby DocTest, there is an autotest system in-built
|
78
|
+
using script/rstakeout
|
79
|
+
|
80
|
+
rake test:doctest:auto
|
81
|
+
|
82
|
+
== TEXTMATE BUNDLE:
|
83
|
+
|
84
|
+
See http://github.com/drnic/ruby-doctest-tmbundle
|
85
|
+
|
86
|
+
== LICENSE:
|
87
|
+
|
88
|
+
(The MIT License)
|
89
|
+
|
90
|
+
Copyright (c) 2008 FIX
|
91
|
+
|
92
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
93
|
+
a copy of this software and associated documentation files (the
|
94
|
+
'Software'), to deal in the Software without restriction, including
|
95
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
96
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
97
|
+
permit persons to whom the Software is furnished to do so, subject to
|
98
|
+
the following conditions:
|
99
|
+
|
100
|
+
The above copyright notice and this permission notice shall be
|
101
|
+
included in all copies or substantial portions of the Software.
|
102
|
+
|
103
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
104
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
105
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
106
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
107
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
108
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
109
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/rubydoctest
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
USAGE = "USAGE: rdoctest [ --html ] [ --trace ] [ --debugger ] <path>"
|
4
|
+
|
5
|
+
SUFFIX = "{r,}doctest"
|
6
|
+
|
7
|
+
file = ARGV.pop or (puts USAGE; exit 1)
|
8
|
+
|
9
|
+
requires = ['rubygems', File.dirname(__FILE__) + "/../lib/rubydoctest"]
|
10
|
+
requires << 'ruby-debug' if ARGV.include?("--debugger")
|
11
|
+
|
12
|
+
command = if ARGV.include?("--rcov")
|
13
|
+
args = (ARGV - ["--rcov"]).map { |a| %("#{a}") }.join(' ')
|
14
|
+
"rcov -x /gems/,rdoctest"
|
15
|
+
else
|
16
|
+
"ruby"
|
17
|
+
end
|
18
|
+
trace = "RubyDocTest.trace = true;" if ARGV.include?("--trace")
|
19
|
+
|
20
|
+
requires = requires.map {|lib| "require '#{lib}'; "}.join
|
21
|
+
|
22
|
+
puts "<html><body><pre>" if ARGV.include?("--html")
|
23
|
+
|
24
|
+
files = if File.directory?(file)
|
25
|
+
Dir["#{file}/**/*.#{SUFFIX}"]
|
26
|
+
else
|
27
|
+
[file]
|
28
|
+
end
|
29
|
+
|
30
|
+
files.reverse_each do |f|
|
31
|
+
puts "*** " + f.sub("#{file}/", "").sub(".#{SUFFIX}", ""), "" if files.length > 1
|
32
|
+
system %(#{command} -e "#{requires} #{trace} RubyDocTest.new(File.read('#{f}'), '#{f}').run")
|
33
|
+
end
|
34
|
+
|
35
|
+
puts "</pre></body></html>" if ARGV.include?("--html")
|
data/config/hoe.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rubydoctest/version'
|
2
|
+
|
3
|
+
AUTHOR = ['Tom Locke', 'Dr Nic Williams'] # can also be an array of Authors
|
4
|
+
EMAIL = "drnicwilliams@gmail.com"
|
5
|
+
DESCRIPTION = "Ruby version of Python's doctest tool, but a bit different."
|
6
|
+
GEM_NAME = 'rubydoctest' # what ppl will type to install your gem
|
7
|
+
RUBYFORGE_PROJECT = 'rubydoctest' # The unix name for your project
|
8
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
10
|
+
EXTRA_DEPENDENCIES = [
|
11
|
+
# ['activesupport', '>= 1.3.1']
|
12
|
+
] # An array of rubygem dependencies [name, version]
|
13
|
+
|
14
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
15
|
+
@config = nil
|
16
|
+
RUBYFORGE_USERNAME = "unknown"
|
17
|
+
def rubyforge_username
|
18
|
+
unless @config
|
19
|
+
begin
|
20
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
21
|
+
rescue
|
22
|
+
puts <<-EOS
|
23
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
24
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
25
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
26
|
+
EOS
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
REV = nil
|
35
|
+
# UNCOMMENT IF REQUIRED:
|
36
|
+
# REV = YAML.load(`svn info`)['Revision']
|
37
|
+
VERS = Rubydoctest::VERSION::STRING + (REV ? ".#{REV}" : "")
|
38
|
+
RDOC_OPTS = ['--quiet', '--title', 'rubydoctest documentation',
|
39
|
+
"--opname", "index.html",
|
40
|
+
"--line-numbers",
|
41
|
+
"--main", "README",
|
42
|
+
"--inline-source"]
|
43
|
+
|
44
|
+
class Hoe
|
45
|
+
def extra_deps
|
46
|
+
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
|
47
|
+
@extra_deps
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generate all the Rake tasks
|
52
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
53
|
+
$hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
54
|
+
p.author = AUTHOR
|
55
|
+
p.email = EMAIL
|
56
|
+
p.description = DESCRIPTION
|
57
|
+
p.summary = DESCRIPTION
|
58
|
+
p.url = HOMEPATH
|
59
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
60
|
+
p.test_globs = ["test/**/test_*.rb"]
|
61
|
+
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
62
|
+
|
63
|
+
# == Optional
|
64
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
65
|
+
#p.extra_deps = EXTRA_DEPENDENCIES
|
66
|
+
|
67
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
68
|
+
end
|
69
|
+
|
70
|
+
CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
|
71
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
72
|
+
$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
73
|
+
$hoe.rsync_args = '-av --delete --ignore-errors'
|
74
|
+
$hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
%w[rake hoe newgem rubigen].each do |req_gem|
|
6
|
+
begin
|
7
|
+
require req_gem
|
8
|
+
rescue LoadError
|
9
|
+
puts "This Rakefile requires the '#{req_gem}' RubyGem."
|
10
|
+
puts "Installation: gem install #{req_gem} -y"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
|
data/lib/rubydoctest.rb
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'irb'
|
5
|
+
|
6
|
+
class RubyDocTest
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :trace
|
10
|
+
end
|
11
|
+
|
12
|
+
PROMPT_RX = /^[>?]>( |\s*$)/
|
13
|
+
|
14
|
+
RESULT_RX = /^=> /
|
15
|
+
|
16
|
+
CODE_LINE_RX = /^( |\t)/
|
17
|
+
|
18
|
+
def initialize(src, file_name)
|
19
|
+
@passed = 0
|
20
|
+
@block_count = 0
|
21
|
+
@failures = []
|
22
|
+
@src_lines = src.split("\n")
|
23
|
+
@line_num = 0
|
24
|
+
@file_name = file_name
|
25
|
+
|
26
|
+
# next_line # get first line
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
run_file
|
31
|
+
print_report
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_accessor :passed, :failures, :current_line, :src_lines, :line_num, :block_count
|
35
|
+
|
36
|
+
def environment
|
37
|
+
TOPLEVEL_BINDING
|
38
|
+
end
|
39
|
+
|
40
|
+
def next_line
|
41
|
+
@line_num += 1
|
42
|
+
@current_line = src_lines.shift
|
43
|
+
end
|
44
|
+
|
45
|
+
def next_line?
|
46
|
+
src_lines.any?
|
47
|
+
end
|
48
|
+
|
49
|
+
def strip_prompt(s)
|
50
|
+
s.sub(PROMPT_RX, "")
|
51
|
+
end
|
52
|
+
|
53
|
+
def result_start?(s=current_line)
|
54
|
+
s =~ RESULT_RX
|
55
|
+
end
|
56
|
+
|
57
|
+
def string_result_start?(s=current_line)
|
58
|
+
s =~ /^=>""/
|
59
|
+
end
|
60
|
+
|
61
|
+
def statement_start?(s=current_line)
|
62
|
+
s =~ PROMPT_RX
|
63
|
+
end
|
64
|
+
|
65
|
+
def strip_result_marker(s=current_line)
|
66
|
+
s.sub(RESULT_RX, "")
|
67
|
+
end
|
68
|
+
|
69
|
+
def normalize_result(s)
|
70
|
+
s.gsub(/:0x[a-f0-9]{8}>/, ':0xXXXXXXXX>').strip
|
71
|
+
end
|
72
|
+
|
73
|
+
def code_line?(s=current_line)
|
74
|
+
s =~ CODE_LINE_RX
|
75
|
+
end
|
76
|
+
|
77
|
+
def code_block_start?(s=current_line)
|
78
|
+
l = unindent_code_line
|
79
|
+
code_line? && (statement_start?(l) || irb_interrupt?(l))
|
80
|
+
end
|
81
|
+
|
82
|
+
def blank_line?(s=current_line)
|
83
|
+
s =~ /^\s*$/
|
84
|
+
end
|
85
|
+
|
86
|
+
def irb_interrupt?(line)
|
87
|
+
line =~ /!!!/
|
88
|
+
end
|
89
|
+
|
90
|
+
def run_file
|
91
|
+
# run_code_block if code_block_start?
|
92
|
+
while next_line
|
93
|
+
run_code_block if code_block_start?
|
94
|
+
end
|
95
|
+
failures.length == 0
|
96
|
+
end
|
97
|
+
|
98
|
+
def unindent_code_line(s=current_line)
|
99
|
+
s.sub(CODE_LINE_RX, "")
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def get_code_lines
|
104
|
+
lines = []
|
105
|
+
while blank_line? || code_line?
|
106
|
+
lines << [unindent_code_line, line_num]
|
107
|
+
next_line
|
108
|
+
end
|
109
|
+
lines.pop while blank_line?(lines.last)
|
110
|
+
lines
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def run_code_block
|
115
|
+
self.block_count += 1
|
116
|
+
|
117
|
+
lines = get_code_lines
|
118
|
+
|
119
|
+
reading = :statement
|
120
|
+
|
121
|
+
result = nil
|
122
|
+
statement = ""
|
123
|
+
statement_line = lines.first.last
|
124
|
+
lines.each do |line, line_num|
|
125
|
+
|
126
|
+
if irb_interrupt?(line)
|
127
|
+
evaluate(statement, statement_line) unless statement == ""
|
128
|
+
|
129
|
+
puts statement unless statement.blank?
|
130
|
+
puts "=> #{result}" unless result.blank?
|
131
|
+
puts
|
132
|
+
|
133
|
+
start_irb
|
134
|
+
line = nil
|
135
|
+
|
136
|
+
elsif string_result_start?(line)
|
137
|
+
reading = :string_result
|
138
|
+
line = nil
|
139
|
+
result = ""
|
140
|
+
|
141
|
+
elsif result_start?(line)
|
142
|
+
reading = :ruby_result
|
143
|
+
line = strip_result_marker(line)
|
144
|
+
result = ""
|
145
|
+
|
146
|
+
elsif statement_start?(line)
|
147
|
+
if result
|
148
|
+
# start of a new statement
|
149
|
+
if reading == :string_result
|
150
|
+
# end of a string result statement
|
151
|
+
result.chomp!
|
152
|
+
run_statement(statement, result, statement_line, true)
|
153
|
+
else
|
154
|
+
run_statement(statement, result, statement_line)
|
155
|
+
end
|
156
|
+
statement_line = line_num
|
157
|
+
statement = ""
|
158
|
+
result = nil
|
159
|
+
end
|
160
|
+
reading = :statement
|
161
|
+
end
|
162
|
+
|
163
|
+
if reading == :statement
|
164
|
+
# The statement has a prompt on every line
|
165
|
+
if line
|
166
|
+
line = strip_prompt(line)
|
167
|
+
statement << line + "\n"
|
168
|
+
end
|
169
|
+
else
|
170
|
+
# There's only one result marker - stripped above
|
171
|
+
result << line + "\n" if line
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
if result.nil?
|
177
|
+
# The block ends with a statement - just evaluate it
|
178
|
+
evaluate(statement, statement_line)
|
179
|
+
else
|
180
|
+
run_statement(statement, result, statement_line)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
def start_irb
|
186
|
+
IRB.init_config(nil)
|
187
|
+
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
188
|
+
irb = IRB::Irb.new(IRB::WorkSpace.new(environment))
|
189
|
+
IRB.conf[:MAIN_CONTEXT] = irb.context
|
190
|
+
irb.eval_input
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
def run_statement(statement, expected_result, statement_line, string_comparison=false)
|
195
|
+
actual_result = evaluate(statement, statement_line)
|
196
|
+
|
197
|
+
if result_matches?(expected_result, actual_result, string_comparison)
|
198
|
+
self.passed += 1
|
199
|
+
else
|
200
|
+
actual_result = actual_result.inspect unless string_comparison
|
201
|
+
failures << [statement, actual_result, expected_result, statement_line]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
def result_matches?(expected_result, actual_result, string_comparison)
|
207
|
+
if string_comparison
|
208
|
+
actual_result == expected_result
|
209
|
+
else
|
210
|
+
actual_result = actual_result.inspect
|
211
|
+
normalize_result(expected_result) == normalize_result(actual_result) or
|
212
|
+
# If the expected result looks like a literal, see if they eval to equal objects - this will often fail
|
213
|
+
if expected_result =~ /^[:\[{A-Z'"%\/]/
|
214
|
+
begin
|
215
|
+
eval(expected_result) == eval(actual_result)
|
216
|
+
rescue Exception
|
217
|
+
false
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def evaluate(statement, line_num)
|
225
|
+
statement.gsub!("__FILE__", @file_name.inspect)
|
226
|
+
eval(statement, environment, __FILE__, __LINE__)
|
227
|
+
rescue SyntaxError => e
|
228
|
+
puts "Syntax error in statement on line #{line_num}:"
|
229
|
+
puts indent(statement)
|
230
|
+
puts e.to_s
|
231
|
+
puts
|
232
|
+
exit 1
|
233
|
+
rescue Exception => e
|
234
|
+
puts "Exception in statement on line #{line_num}:"
|
235
|
+
puts indent(statement)
|
236
|
+
puts e.backtrace
|
237
|
+
|
238
|
+
if RubyDocTest.trace
|
239
|
+
raise
|
240
|
+
else
|
241
|
+
puts e.to_s
|
242
|
+
puts
|
243
|
+
exit 1
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
def number_run
|
249
|
+
passed + failures.length
|
250
|
+
end
|
251
|
+
|
252
|
+
def indent(s, level=4)
|
253
|
+
spaces = " " * level
|
254
|
+
spaces + s.split("\n").join("\n#{spaces}")
|
255
|
+
end
|
256
|
+
|
257
|
+
def print_report
|
258
|
+
statements_per_block = number_run.to_f / block_count
|
259
|
+
puts("%d blocks, %d tests (avg. %.1f/block), %d failures\n\n" %
|
260
|
+
[block_count, number_run, statements_per_block, failures.length])
|
261
|
+
|
262
|
+
failures.each do |statement, actual, expected, lnum|
|
263
|
+
puts "Failure line #{lnum}"
|
264
|
+
puts " Statement:", indent(statement)
|
265
|
+
puts " Expected:", indent(expected)
|
266
|
+
puts " Got:\n", indent(actual)
|
267
|
+
puts
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
end
|