doctest 0.0.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 +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +26 -0
- data/README.txt +48 -0
- data/Rakefile +4 -0
- data/bin/doctest +13 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +15 -0
- data/lib/doctest.rb +204 -0
- data/lib/doctest/version.rb +9 -0
- data/log/debug.log +0 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/test_doctest.rb +12 -0
- data/test/test_helper.rb +2 -0
- data/test/test_tester.rb +35 -0
- data/website/index.html +11 -0
- data/website/index.txt +39 -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 +86 -0
data/History.txt
ADDED
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,26 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
bin/doctest
|
7
|
+
config/hoe.rb
|
8
|
+
config/requirements.rb
|
9
|
+
lib/doctest.rb
|
10
|
+
lib/doctest/version.rb
|
11
|
+
log/debug.log
|
12
|
+
script/console
|
13
|
+
script/destroy
|
14
|
+
script/generate
|
15
|
+
script/txt2html
|
16
|
+
setup.rb
|
17
|
+
tasks/deployment.rake
|
18
|
+
tasks/environment.rake
|
19
|
+
tasks/website.rake
|
20
|
+
test/test_doctest.rb
|
21
|
+
test/test_helper.rb
|
22
|
+
website/index.html
|
23
|
+
website/index.txt
|
24
|
+
website/javascripts/rounded_corners_lite.inc.js
|
25
|
+
website/stylesheets/screen.css
|
26
|
+
website/template.html.erb
|
data/README.txt
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= doctest
|
2
|
+
|
3
|
+
* FIX (url)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
FIX (describe your package)
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* FIX (list of features or problems)
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
FIX (code sample of usage)
|
16
|
+
|
17
|
+
== REQUIREMENTS:
|
18
|
+
|
19
|
+
* FIX (list of requirements)
|
20
|
+
|
21
|
+
== INSTALL:
|
22
|
+
|
23
|
+
* FIX (sudo gem install, anything else)
|
24
|
+
|
25
|
+
== LICENSE:
|
26
|
+
|
27
|
+
(The MIT License)
|
28
|
+
|
29
|
+
Copyright (c) 2008 FIX
|
30
|
+
|
31
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
32
|
+
a copy of this software and associated documentation files (the
|
33
|
+
'Software'), to deal in the Software without restriction, including
|
34
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
35
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
36
|
+
permit persons to whom the Software is furnished to do so, subject to
|
37
|
+
the following conditions:
|
38
|
+
|
39
|
+
The above copyright notice and this permission notice shall be
|
40
|
+
included in all copies or substantial portions of the Software.
|
41
|
+
|
42
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
43
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
44
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
45
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
46
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
47
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
48
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/doctest
ADDED
data/config/hoe.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'doctest/version'
|
2
|
+
|
3
|
+
AUTHOR = 'FIXME full name' # can also be an array of Authors
|
4
|
+
EMAIL = "FIXME email"
|
5
|
+
DESCRIPTION = "description of gem"
|
6
|
+
GEM_NAME = 'doctest' # what ppl will type to install your gem
|
7
|
+
RUBYFORGE_PROJECT = 'doctest' # The unix name for your project
|
8
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
10
|
+
|
11
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
12
|
+
@config = nil
|
13
|
+
RUBYFORGE_USERNAME = "unknown"
|
14
|
+
def rubyforge_username
|
15
|
+
unless @config
|
16
|
+
begin
|
17
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
18
|
+
rescue
|
19
|
+
puts <<-EOS
|
20
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
21
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
22
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
23
|
+
EOS
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
REV = nil
|
32
|
+
# UNCOMMENT IF REQUIRED:
|
33
|
+
# REV = YAML.load(`svn info`)['Revision']
|
34
|
+
VERS = Doctest::VERSION::STRING + (REV ? ".#{REV}" : "")
|
35
|
+
RDOC_OPTS = ['--quiet', '--title', 'doctest documentation',
|
36
|
+
"--opname", "index.html",
|
37
|
+
"--line-numbers",
|
38
|
+
"--main", "README",
|
39
|
+
"--inline-source"]
|
40
|
+
|
41
|
+
class Hoe
|
42
|
+
def extra_deps
|
43
|
+
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
|
44
|
+
@extra_deps
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Generate all the Rake tasks
|
49
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
50
|
+
$hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
51
|
+
p.developer(AUTHOR, EMAIL)
|
52
|
+
p.description = DESCRIPTION
|
53
|
+
p.summary = DESCRIPTION
|
54
|
+
p.url = HOMEPATH
|
55
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
56
|
+
p.test_globs = ["test/**/test_*.rb"]
|
57
|
+
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
58
|
+
|
59
|
+
# == Optional
|
60
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
61
|
+
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
62
|
+
|
63
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
|
68
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
69
|
+
$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
70
|
+
$hoe.rsync_args = '-av --delete --ignore-errors'
|
@@ -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/doctest.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
=begin
|
2
|
+
A testing module allowing for people to add IRB code snippets to their code descriptions, which IRB code snippets 'second' as tests for the code itself.
|
3
|
+
Ex:
|
4
|
+
=begin
|
5
|
+
# doctest This function adds 2 to its parameters
|
6
|
+
>> setup(1)
|
7
|
+
#=end
|
8
|
+
def setup a
|
9
|
+
a + 2
|
10
|
+
end
|
11
|
+
=> 3
|
12
|
+
=end
|
13
|
+
|
14
|
+
# todo:
|
15
|
+
# the 'inline for rubydoc' option
|
16
|
+
# low priority:
|
17
|
+
# make it even more robust to errors--if it errs, look for internal hashes, convert
|
18
|
+
# Fix so raising errors validates -- currently ignores
|
19
|
+
# multi line strings
|
20
|
+
# option to run each in its own directory
|
21
|
+
# tell them how to change dirs on their own [add an end guy?]
|
22
|
+
# #doctest_end
|
23
|
+
# WAY more line logic
|
24
|
+
# some way of reusing tests, like classes [?] or functions :) -- this doctest gets this replaced with this :P
|
25
|
+
# normal code inline [maybe that can raise if it errs, maybe more]
|
26
|
+
# check python's --what they got?
|
27
|
+
# use rspec, how can it improve?
|
28
|
+
# todo better params
|
29
|
+
|
30
|
+
if ARGV[0] == '--help'
|
31
|
+
print "
|
32
|
+
use: doctest file_name.rb (or directory_name): default '.'
|
33
|
+
-- note it recurses and scans all .rb in that directory and its subdirectories
|
34
|
+
ex: doctest .
|
35
|
+
doctest file.rb
|
36
|
+
doctest dir #also scans its subdirs
|
37
|
+
"
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
|
41
|
+
BINDING = binding()
|
42
|
+
|
43
|
+
class DocTest
|
44
|
+
CODE_REGEX = Regexp.new(/^(>>|irb.*?>) (.*)/)
|
45
|
+
RESULT_REGEX = Regexp.new(/^=> (.*)/)
|
46
|
+
EXCEPTION_REGEX = Regexp.new(/^([A-Z][A-Za-z0-9]*):/)
|
47
|
+
|
48
|
+
def get_ruby_files(dir_name)
|
49
|
+
ruby_file_names = []
|
50
|
+
|
51
|
+
Dir.foreach(dir_name) do |file_name|
|
52
|
+
unless file_name == '.' || file_name == '..'
|
53
|
+
full_name = File.join(dir_name, file_name)
|
54
|
+
if /.*\.rb$/ =~ full_name
|
55
|
+
ruby_file_names << full_name
|
56
|
+
elsif File.directory? full_name
|
57
|
+
sub_files = get_ruby_files(full_name)
|
58
|
+
ruby_file_names.concat(sub_files) unless sub_files.empty?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
ruby_file_names
|
64
|
+
end
|
65
|
+
=begin
|
66
|
+
#doctest normalize substring
|
67
|
+
>> a = DocTest.new
|
68
|
+
=> #<DocTest:0x37012c>
|
69
|
+
>> a.normalize_result('0xtion:0x1876bc0 @@p')
|
70
|
+
=> "0xtion:0xXXXXXXXX @@p"
|
71
|
+
=end
|
72
|
+
def normalize_result(input)
|
73
|
+
input.gsub(/:0x([a-f0-9]){5,8}/, ':0xXXXXXXXX') # makes them all 8 digits long
|
74
|
+
end
|
75
|
+
|
76
|
+
def failure_report(statement, expected_result, result)
|
77
|
+
report = "\n FAILED" #add line number logic here
|
78
|
+
report << " Code: " << statement << "\n"
|
79
|
+
report << " Expected: " << expected_result << "\n"
|
80
|
+
report << " But got: " << result
|
81
|
+
end
|
82
|
+
|
83
|
+
=begin
|
84
|
+
#doctest should match with hashes
|
85
|
+
>> {1=>1, 2=>2, 3=> 3, 4=>4,5=>5}
|
86
|
+
=> {5=>5, 1=>1, 2=>2, 3=>3, 4=>4}
|
87
|
+
now test with different ordered hashes
|
88
|
+
>> {1=>1, 2=>2, 3=> 3, 4=>4,5=>5}
|
89
|
+
=> {4=>4, 1=>1, 2=>2, 3=>3, 5=>5}
|
90
|
+
>> {1=>":0x123456", 2=>2, 3=> 3, 4=>4,5=>5}
|
91
|
+
=> {4=>4, 1=>":0x123456", 2=>2, 3=>3, 5=>5}
|
92
|
+
=end
|
93
|
+
def dbg
|
94
|
+
require 'rubygems'; require 'ruby-debug'; debugger
|
95
|
+
end
|
96
|
+
|
97
|
+
def run_doc_tests(doc_test)
|
98
|
+
statement, report = '', ''
|
99
|
+
wrong, passed = 0, 0
|
100
|
+
doc_test.split("\n").each do |line|
|
101
|
+
case line
|
102
|
+
when CODE_REGEX
|
103
|
+
statement << CODE_REGEX.match(line)[2]
|
104
|
+
when RESULT_REGEX, EXCEPTION_REGEX
|
105
|
+
if line =~ RESULT_REGEX
|
106
|
+
expected_result_string = normalize_result(RESULT_REGEX.match(line)[1])
|
107
|
+
else
|
108
|
+
raise unless line =~ EXCEPTION_REGEX
|
109
|
+
expected_result_string = $1
|
110
|
+
end
|
111
|
+
|
112
|
+
begin
|
113
|
+
result_we_got = eval(statement, BINDING)
|
114
|
+
rescue Exception => e
|
115
|
+
result_we_got = e.class
|
116
|
+
end
|
117
|
+
|
118
|
+
they_match = false
|
119
|
+
if result_we_got.class.ancestors.include? Hash
|
120
|
+
# change them to 'kind of real' hashes, so that we cancompare them and have comparison work--hashes sometimes display in different orders when printed
|
121
|
+
expected_result = eval(expected_result_string, BINDING)
|
122
|
+
if eval(normalize_result(result_we_got.inspect), BINDING) == expected_result # todo some tests for this with whack-o stuff thrown in :)
|
123
|
+
# the Hashes matched, string-wise
|
124
|
+
they_match = true
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
they_match = true if expected_result_string =~ /#doctest_fail_ok/
|
129
|
+
result_string = normalize_result(result_we_got.inspect)
|
130
|
+
they_match = true if result_string == expected_result_string
|
131
|
+
unless they_match
|
132
|
+
report << failure_report(statement, expected_result_string, result_string)
|
133
|
+
wrong += 1
|
134
|
+
else
|
135
|
+
passed += 1
|
136
|
+
end
|
137
|
+
statement = '' # reset it for the next round
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return passed, wrong, report
|
141
|
+
end
|
142
|
+
|
143
|
+
def process_ruby_file(file_name)
|
144
|
+
tests, succeeded, failed = 0, 0, 0
|
145
|
+
file_report = ''
|
146
|
+
code = File.read file_name
|
147
|
+
|
148
|
+
startup_code_for_this_file = code.scan(/begin\s#setup_doctest once_per_file(.*?)=end/m)
|
149
|
+
|
150
|
+
if startup_code_for_this_file.length > 0
|
151
|
+
raise 'can only do one_time_file_setup declaration once' if startup_code_for_this_file.length > 1 or startup_code_for_this_file[0].length > 1
|
152
|
+
startup_code_for_this_file = startup_code_for_this_file[0][0]
|
153
|
+
begin
|
154
|
+
eval startup_code_for_this_file, BINDING
|
155
|
+
rescue Exception => e
|
156
|
+
print "Uh oh unable to execute startup code for #{file_name}...continuing #{e}\n"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# todo would be nice to have multiple tests in the same comment block
|
161
|
+
# so a scan + sub scan for doctests
|
162
|
+
code.scan(/=begin\s#doctest([^\n]*)\n(.*?)=end/m) do |doc_test| # could do--replace default named ones with their line number :)
|
163
|
+
require file_name # might as well have its functions available to itself :P
|
164
|
+
# todo could tear out anything loaded after each file, I suppose, as active support does
|
165
|
+
file_report << "\n Testing '#{doc_test[0]}'..."
|
166
|
+
passed, wrong, report = run_doc_tests(doc_test[1])
|
167
|
+
file_report += (wrong == 0 ? "OK" : report)
|
168
|
+
tests += 1
|
169
|
+
succeeded += passed
|
170
|
+
failed += wrong
|
171
|
+
end
|
172
|
+
file_report = "Processing '#{file_name}' from current directory " + file_report unless file_report.empty?
|
173
|
+
return tests, succeeded, failed, file_report
|
174
|
+
end
|
175
|
+
def DocTest.run
|
176
|
+
# parse command line--currently just 'filename' or 'directory name'
|
177
|
+
runner = DocTest.new
|
178
|
+
if File.directory? ARGV[0] || ''
|
179
|
+
ruby_file_names = runner.get_ruby_files(ARGV[0])
|
180
|
+
elsif File.exist? ARGV[0] || ''
|
181
|
+
ruby_file_names = [ARGV[0]]
|
182
|
+
else
|
183
|
+
ruby_file_names = runner.get_ruby_files('.')
|
184
|
+
end
|
185
|
+
|
186
|
+
total_report = "Looking for doctests in a total of #{ruby_file_names.length} possible files\n"
|
187
|
+
total_files, total_tests, total_succeeded, total_failed = 0, 0, 0, 0
|
188
|
+
ruby_file_names.each do |ruby_file_name|
|
189
|
+
tests, succeeded, failed, report = runner.process_ruby_file(ruby_file_name)
|
190
|
+
total_files += 1 if tests > 0
|
191
|
+
total_tests += tests
|
192
|
+
total_succeeded += succeeded
|
193
|
+
total_failed += failed
|
194
|
+
total_report << report << "\n" unless report.empty?
|
195
|
+
end
|
196
|
+
total_report << "Total files: #{total_files}, total tests: #{total_tests}, assertions succeeded: #{total_succeeded}, assertions failed: #{total_failed}"
|
197
|
+
puts total_report
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
if $0 == __FILE__
|
203
|
+
DocTest.run
|
204
|
+
end
|
data/log/debug.log
ADDED
File without changes
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/doctest.rb'}"
|
9
|
+
puts "Loading doctest gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|