doctest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-04-12
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -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.
@@ -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
@@ -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.
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2008-4-12.
4
+ # Copyright (c) 2008. All rights reserved.
5
+
6
+ begin
7
+ require 'rubygems'
8
+ rescue LoadError
9
+ # no rubygems to load, so we fail silently
10
+ end
11
+
12
+ require 'doctest'
13
+ DocTest.run
@@ -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]))
@@ -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
@@ -0,0 +1,9 @@
1
+ module Doctest #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
File without changes
@@ -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"
@@ -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)