matthewrudy-rubydoctest 1.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 ADDED
@@ -0,0 +1,24 @@
1
+ == 1.0.0 2008-06-23
2
+
3
+ * Added doctest: and doctest_require: special directives.
4
+ * Bug fixes.
5
+ * Documentation and wiki.
6
+
7
+ == 0.3.0 2008-06-17
8
+
9
+ * Added ability to put doctest code within .rb file comments
10
+
11
+ == 0.2.1 2008-05-26
12
+
13
+ * Adding self-doctesting doctests
14
+
15
+ == 0.2.0 2008-05-25
16
+
17
+ * Initial changes by Dr Nic
18
+ * __FILE__ is changed to the explicit file path (since it was eval'ing to the code, not the test file)
19
+ * Starting to write doctests for the project itself
20
+
21
+ == 0.1.0 2008-05-25
22
+
23
+ * 1 major enhancement:
24
+ * Initial release from Tom's personal stash of code
data/License.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008 Tom Locke, Nic Williams, Duane Johnson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,38 @@
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/code_block.rb
11
+ lib/doctest_require.rb
12
+ lib/lines.rb
13
+ lib/result.rb
14
+ lib/rubydoctest.rb
15
+ lib/rubydoctest/version.rb
16
+ lib/runner.rb
17
+ lib/special_directive.rb
18
+ lib/statement.rb
19
+ lib/test.rb
20
+ rubydoctest.gemspec
21
+ script/console
22
+ script/destroy
23
+ script/generate
24
+ script/rstakeout
25
+ script/txt2html
26
+ setup.rb
27
+ tasks/deployment.rake
28
+ tasks/doctests.rake
29
+ tasks/environment.rake
30
+ tasks/website.rake
31
+ textmate/DocTest (Markdown).textmate
32
+ textmate/DocTest (Ruby).textmate
33
+ textmate/DocTest (Text).textmate
34
+ website/index.html
35
+ website/index.txt
36
+ website/javascripts/rounded_corners_lite.inc.js
37
+ website/stylesheets/screen.css
38
+ website/template.html.erb
data/PostInstall.txt ADDED
@@ -0,0 +1,7 @@
1
+
2
+ rubydoctest comes as an executable that takes a list of files:
3
+
4
+ rubydoctest lib/*.rb
5
+ rubydoctest simple.doctest
6
+
7
+
data/README.txt ADDED
@@ -0,0 +1,100 @@
1
+ = Ruby DocTest
2
+
3
+ Official repository:
4
+ * http://github.com/tablatom/rubydoctest
5
+
6
+ Wiki documentation:
7
+ * http://github.com/tablatom/rubydoctest/wikis
8
+
9
+ == Description:
10
+
11
+ Ruby version of Python's doctest tool, but a bit different. Ruby DocTest
12
+ allows you to:
13
+
14
+ 1. Write tests in irb format and keep them as comments next to your Ruby code.
15
+ 2. Write markdown documents with irb format tests embedded in them.
16
+
17
+ == Synopsis:
18
+
19
+ rubydoctest comes as an executable that takes a list of files:
20
+
21
+ rubydoctest lib/*.rb
22
+ rubydoctest simple.doctest
23
+
24
+ == Examples:
25
+
26
+ Here is how you might use RubyDocTest within a ruby source file (say called five.rb):
27
+
28
+ # doctest: Add 5 and 5 to get 10
29
+ # >> five_and_five
30
+ # => 10
31
+ def five_and_five
32
+ 5 + 5
33
+ end
34
+
35
+ Here is an example doctest file (say called simple.doctest):
36
+
37
+ # Simple test of RubyDocTest
38
+
39
+ This is an example test
40
+
41
+ >> 1 + 2
42
+ => 3
43
+
44
+ And here's a test that will fail
45
+
46
+ >> 1 + 2
47
+ => 4
48
+
49
+ See the doc directory of this project for more .doctest examples and documentation.
50
+
51
+ == Installation:
52
+
53
+ Major releases:
54
+
55
+ sudo gem install rubydoctest
56
+
57
+ Build from source:
58
+
59
+ git clone git://github.com/tablatom/rubydoctest.git
60
+ cd rubydoctest
61
+ rake manifest:refresh && rake install
62
+
63
+ == Testing DocTest:
64
+
65
+ Ruby DocTest uses itself to test and document itself.
66
+
67
+ rake test:doctest
68
+
69
+ In development of Ruby DocTest, there is an autotest system in-built
70
+ using script/rstakeout
71
+
72
+ rake test:doctest:auto
73
+
74
+ == TextMate Bundle:
75
+
76
+ See http://github.com/drnic/ruby-doctest-tmbundle
77
+
78
+ == License:
79
+
80
+ (The MIT License)
81
+
82
+ Copyright (c) 2008 Tom Locke, Nic Williams, Duane Johnson
83
+
84
+ Permission is hereby granted, free of charge, to any person obtaining a copy
85
+ of this software and associated documentation files (the 'Software'), to deal
86
+ in the Software without restriction, including without limitation the rights
87
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88
+ copies of the Software, and to permit persons to whom the Software is
89
+ furnished to do so, subject to the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be included in all
92
+ copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
95
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
96
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
97
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
98
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
99
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
100
+ SOFTWARE.
data/Rakefile ADDED
@@ -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 }
data/bin/rubydoctest ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ options, files = ARGV.partition{ |a| a =~ /^-/ }
4
+
5
+ if ARGV.empty? or options.include?("-h") or options.include?("--help")
6
+ require 'rubydoctest/version'
7
+ puts <<-DIRECTIONS
8
+ Ruby DocTest #{Rubydoctest::VERSION::STRING}
9
+ USAGE: rubydoctest [options] <files>
10
+
11
+ rubydoctest parses Ruby files (.rb) or DocTest files (.doctest) for irb-style
12
+ sessions in comments, and runs the commented sessions as tests.
13
+
14
+ Options:
15
+ General:
16
+ --help - show this usage / help information
17
+ -t<n> - only run test number n, e.g. -t1 -t3
18
+
19
+ Output Format:
20
+ --html - output in HTML format
21
+ --plain - force output in plain text (no Ansi colors)
22
+
23
+ Debug:
24
+ --ignore-interactive - do not heed !!! special directives
25
+ --trace - turn backtrace on to debug Ruby DocTest
26
+ --debugger - include ruby-debug library / gem
27
+ --require=</path/to/require>,</another/path/to/require> - eg. --require=config/environment.rb
28
+
29
+ See http://github.com/tablatom/rubydoctest/wikis for more information.
30
+ DIRECTIONS
31
+ exit 0
32
+ end
33
+
34
+ requires = ['rubygems', File.dirname(__FILE__) + "/../lib/rubydoctest"]
35
+ requires << 'ruby-debug' if options.include?("--debugger")
36
+
37
+ if options.detect {|opt| opt =~ /^--require=(.+)/}
38
+ requires << $1.split(",")
39
+ end
40
+
41
+ ruby_lines = []
42
+ ruby_lines << "RubyDocTest.trace = true;" if options.include?("--trace")
43
+ ruby_lines << "RubyDocTest.ignore_interactive = true;" if options.include?("--ignore-interactive")
44
+
45
+ tests = options.map{ |o| o =~ /^-t(\d+)/; $1 }.compact
46
+ ruby_lines << "RubyDocTest.tests = #{tests.inspect};" if tests.size > 0
47
+
48
+ requires = requires.map {|lib| "require '#{lib}'; "}.join
49
+
50
+ def files_runner(command, files, requires, lines)
51
+ files.reverse_each do |f|
52
+ system %(#{command} -e "#{requires} #{lines.join(" ")} RubyDocTest::Runner.new(File.read('#{f}'), '#{f}').run")
53
+ end
54
+ end
55
+
56
+ if options.include?("--plain")
57
+ ruby_lines << "RubyDocTest.output_format = :plain;"
58
+ files_runner("ruby", files, requires, ruby_lines)
59
+ elsif options.include?("--html")
60
+ ruby_lines << "RubyDocTest.output_format = :html;"
61
+ puts "<html><body><pre>"
62
+ files_runner("ruby", files, requires, ruby_lines)
63
+ puts "</pre></body></html>"
64
+ else
65
+ files_runner("ruby", files, requires, ruby_lines)
66
+ end
data/config/hoe.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'rubydoctest/version'
2
+
3
+ AUTHOR = ['Duane Johnson', 'Tom Locke', 'Dr Nic Williams'] # can also be an array of Authors
4
+ EMAIL = "duane.johnson@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
+
12
+ @config_file = "~/.rubyforge/user-config.yml"
13
+ @config = nil
14
+ RUBYFORGE_USERNAME = "unknown"
15
+ def rubyforge_username
16
+ unless @config
17
+ begin
18
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
19
+ rescue
20
+ puts <<-EOS
21
+ ERROR: No rubyforge config file found: #{@config_file}
22
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
23
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
24
+ EOS
25
+ exit
26
+ end
27
+ end
28
+ RUBYFORGE_USERNAME.replace @config["username"]
29
+ end
30
+
31
+
32
+ REV = nil
33
+ # UNCOMMENT IF REQUIRED:
34
+ # REV = YAML.load(`svn info`)['Revision']
35
+ VERS = Rubydoctest::VERSION::STRING + (REV ? ".#{REV}" : "")
36
+ RDOC_OPTS = ['--quiet', '--title', 'rubydoctest documentation',
37
+ "--opname", "index.html",
38
+ "--line-numbers",
39
+ "--main", "README",
40
+ "--inline-source"]
41
+
42
+ class Hoe
43
+ def extra_deps
44
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
45
+ @extra_deps
46
+ end
47
+ end
48
+
49
+ # Generate all the Rake tasks
50
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
51
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
52
+ p.author = AUTHOR
53
+ p.email = EMAIL
54
+ p.description = DESCRIPTION
55
+ p.summary = DESCRIPTION
56
+ p.url = HOMEPATH
57
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
58
+ p.test_globs = ["test/**/test_*.rb"]
59
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
60
+
61
+ # == Optional
62
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
63
+ #p.extra_deps = EXTRA_DEPENDENCIES
64
+
65
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
66
+ end
67
+
68
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
69
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
70
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
71
+ $hoe.rsync_args = '-av --delete --ignore-errors'
72
+ $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/code_block.rb ADDED
@@ -0,0 +1,68 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'statement'
5
+ require 'result'
6
+
7
+ module RubyDocTest
8
+ # A +CodeBlock+ is a group of one or more ruby statements, followed by an optional result.
9
+ # For example:
10
+ # >> a = 1 + 1
11
+ # >> a - 3
12
+ # => -1
13
+ class CodeBlock
14
+ attr_reader :statements, :result, :passed
15
+
16
+ def initialize(statements = [], result = nil)
17
+ @statements = statements
18
+ @result = result
19
+ end
20
+
21
+ # === Tests
22
+ # doctest: Single statement with result should pass
23
+ # >> ss = [RubyDocTest::Statement.new([">> a = 1"])]
24
+ # >> r = RubyDocTest::Result.new(["=> 1"])
25
+ # >> cb = RubyDocTest::CodeBlock.new(ss, r)
26
+ # >> cb.pass?
27
+ # => true
28
+ #
29
+ # doctest: Single statement without result should pass by default
30
+ # >> ss = [RubyDocTest::Statement.new([">> a = 1"])]
31
+ # >> cb = RubyDocTest::CodeBlock.new(ss)
32
+ # >> cb.pass?
33
+ # => true
34
+ #
35
+ # doctest: Multi-line statement with result should pass
36
+ # >> ss = [RubyDocTest::Statement.new([">> a = 1"]),
37
+ # RubyDocTest::Statement.new([">> 'a' + a.to_s"])]
38
+ # >> r = RubyDocTest::Result.new(["=> 'a1'"])
39
+ # >> cb = RubyDocTest::CodeBlock.new(ss, r)
40
+ # >> cb.pass?
41
+ # => true
42
+ def pass?
43
+ if @computed
44
+ @passed
45
+ else
46
+ @computed = true
47
+ @passed =
48
+ begin
49
+ actual_results = @statements.map{ |s| s.evaluate }
50
+ @result ? @result.matches?(actual_results.last) : true
51
+ end
52
+ end
53
+ end
54
+
55
+ def actual_result
56
+ @statements.last.actual_result
57
+ end
58
+
59
+ def expected_result
60
+ @result.expected_result
61
+ end
62
+
63
+ def lines
64
+ @statements.map{ |s| s.lines }.flatten +
65
+ @result.lines
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ def is_doctest_require_successful?
2
+ true
3
+ end
data/lib/lines.rb ADDED
@@ -0,0 +1,143 @@
1
+ module RubyDocTest
2
+ # === Description
3
+ # Keeps track of which lines within a document belong to a group. Line groups are
4
+ # determined by their indentation level, as in the Python programming language.
5
+ #
6
+ # === Example
7
+ # This line and the next one
8
+ # are part of the same group
9
+ #
10
+ # But this line is separate from
11
+ # this line.
12
+ #
13
+ # === Note
14
+ # This class also considers one '#' character (comment) as an indentation character,
15
+ # i.e. similar to how whitespace is treated.
16
+ class Lines
17
+ def initialize(doc_lines, line_index = 0)
18
+ @doc_lines, @line_index = doc_lines, line_index
19
+ end
20
+
21
+
22
+ def line_number
23
+ @line_index + 1
24
+ end
25
+
26
+ # === Tests
27
+ # doctest: Return an array of 1 line if there is only one line
28
+ # >> l = RubyDocTest::Lines.new(["line 1"])
29
+ # >> l.lines
30
+ # => ["line 1"]
31
+ #
32
+ # doctest: Remove indentation from lines 2 to the end of this Lines group.
33
+ # >> l = RubyDocTest::Lines.new(["line 1", " line 2", " line 3", " line 4"])
34
+ # >> l.lines
35
+ # => ["line 1", "line 2", "line 3", " line 4"]
36
+ def lines
37
+ r = range
38
+ size = r.last - r.first + 1
39
+ if size > 1
40
+ # Remove indentation from all lines after the first,
41
+ # as measured from the 2nd line's indentation level
42
+ idt2 = indentation(@doc_lines, @line_index + 1)
43
+ [@doc_lines[range.first]] +
44
+ @doc_lines[(range.first + 1)..(range.last)].
45
+ map{ |l| $1 if l =~ /^#{Regexp.escape(idt2)}(.*)/ }
46
+ else
47
+ @doc_lines[range]
48
+ end
49
+ end
50
+
51
+
52
+ # === Description
53
+ # Calculate the range of python-like indentation within this Lines group
54
+ #
55
+ # === Tests
56
+ # >> l = RubyDocTest::Lines.new([])
57
+ #
58
+ # doctest: Return a range of one line when there is only one line to begin with
59
+ # >> l.range %w(a), 0
60
+ # => 0..0
61
+ #
62
+ # doctest: Return a range of one line when there are two lines, side by side
63
+ # >> l.range %w(a b), 0
64
+ # => 0..0
65
+ # >> l.range %w(a b), 1
66
+ # => 1..1
67
+ #
68
+ # doctest: Return a range of two lines when there are two lines, the second blank
69
+ # >> l.range ["a", ""], 0
70
+ # => 0..1
71
+ #
72
+ # doctest: Return a range of two lines when the second is indented
73
+ # >> l.range ["a", " b"], 0
74
+ # => 0..1
75
+ #
76
+ # doctest: Indentation can also include the ?> marker
77
+ # >> l.range [">> 1 +", "?> 2"], 0
78
+ # => 0..1
79
+ def range(doc_lines = @doc_lines, start_index = @line_index)
80
+ end_index = start_index
81
+ idt = indentation(doc_lines, start_index)
82
+ # Find next lines that are blank, or have indentation more than the first line
83
+ remaining_lines(doc_lines, start_index + 1).each do |current_line|
84
+ if current_line =~ /^(#{Regexp.escape(idt)}(\s+|\?>\s)|\s*$)/
85
+ end_index += 1
86
+ else
87
+ break
88
+ end
89
+ end
90
+ # Compute the range from what we found
91
+ start_index..end_index
92
+ end
93
+
94
+ def inspect
95
+ "#<#{self.class} lines=#{lines.inspect}>"
96
+ end
97
+
98
+ protected
99
+
100
+ # === Tests
101
+ # >> l = RubyDocTest::Lines.new([])
102
+ #
103
+ # doctest: Get a whitespace indent from a line with whitespace
104
+ # >> l.send :indentation, [" a"], 0
105
+ # => " "
106
+ #
107
+ # doctest: Get a whitespace and '#' indent from a comment line
108
+ # >> l.send :indentation, [" # a"], 0
109
+ # => " # "
110
+ def indentation(doc_lines = @doc_lines, line_index = @line_index)
111
+ if doc_lines[line_index]
112
+ doc_lines[line_index][/^(\s*#\s*|\s*)(\?>\s)?/]
113
+ else
114
+ ""
115
+ end
116
+ end
117
+
118
+
119
+ # === Description
120
+ # Get lines from +start_index+ up to the end of the document.
121
+ #
122
+ # === Tests
123
+ # >> l = RubyDocTest::Lines.new([])
124
+ #
125
+ # doctest: Return an empty array if start_index is out of bounds
126
+ # >> l.send :remaining_lines, [], 1
127
+ # => []
128
+ # >> l.send :remaining_lines, [], -1
129
+ # => []
130
+ #
131
+ # doctest: Return the specified line at start_index, up to and including the
132
+ # last line of +doc_lines+.
133
+ # >> l.send :remaining_lines, %w(a b c), 1
134
+ # => %w(b c)
135
+ # >> l.send :remaining_lines, %w(a b c), 2
136
+ # => %w(c)
137
+ #
138
+ def remaining_lines(doc_lines = @doc_lines, start_index = @line_index)
139
+ return [] if start_index < 0 or start_index >= doc_lines.size
140
+ doc_lines[start_index..-1]
141
+ end
142
+ end
143
+ end