tablatom-rubydoctest 0.2.1 → 1.0.0

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.
@@ -1,3 +1,7 @@
1
+ == 0.3.0 2008-06-17
2
+
3
+ * Added ability to put doctest code within .rb file comments
4
+
1
5
  == 0.2.1 2008-05-26
2
6
 
3
7
  * Adding self-doctesting doctests
@@ -1,20 +1,19 @@
1
- Copyright (c) 2008 FIXME full name
1
+ Copyright (c) 2008 Tom Locke, Nic Williams, Duane Johnson
2
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:
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:
10
9
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
13
12
 
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.
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.
@@ -4,26 +4,34 @@ Manifest.txt
4
4
  PostInstall.txt
5
5
  README.txt
6
6
  Rakefile
7
+ Ruby DocTest.tmproj
7
8
  bin/rubydoctest
8
9
  config/hoe.rb
9
10
  config/requirements.rb
11
+ lib/code_block.rb
12
+ lib/doctest_require.rb
13
+ lib/lines.rb
14
+ lib/result.rb
10
15
  lib/rubydoctest.rb
11
16
  lib/rubydoctest/version.rb
17
+ lib/runner.rb
18
+ lib/special_directive.rb
19
+ lib/statement.rb
20
+ lib/test.rb
12
21
  rubydoctest.gemspec
13
22
  script/console
14
23
  script/destroy
15
24
  script/generate
25
+ script/rstakeout
16
26
  script/txt2html
17
27
  setup.rb
18
28
  tasks/deployment.rake
19
29
  tasks/doctests.rake
20
30
  tasks/environment.rake
21
31
  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
32
+ textmate/DocTest (Markdown).textmate
33
+ textmate/DocTest (Ruby).textmate
34
+ textmate/DocTest (Text).textmate
27
35
  website/index.html
28
36
  website/index.txt
29
37
  website/javascripts/rounded_corners_lite.inc.js
@@ -1,8 +1,7 @@
1
1
 
2
- rubydoctest comes as an executable that takes a file or directory:
2
+ rubydoctest comes as an executable that takes a list of files:
3
3
 
4
- rubydoctest .
5
- rubydoctest some/path/to/tests
4
+ rubydoctest lib/*.rb
6
5
  rubydoctest simple.doctest
7
6
 
8
7
 
data/README.txt CHANGED
@@ -1,24 +1,37 @@
1
- = rubydoctest
1
+ = Ruby DocTest
2
2
 
3
- * http://github.com/tablatom/rubydoctest
3
+ Official repository:
4
+ * http://github.com/tablatom/rubydoctest
4
5
 
5
- == DESCRIPTION:
6
+ Wiki documentation:
7
+ * http://github.com/tablatom/rubydoctest/wikis
6
8
 
7
- Ruby version of Python's doctest tool, but a bit different.
9
+ == Description:
8
10
 
9
- == FEATURES/PROBLEMS:
11
+ Ruby version of Python's doctest tool, but a bit different. Ruby DocTest
12
+ allows you to:
10
13
 
11
- * FIX (list of features or problems)
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.
12
16
 
13
- == SYNOPSIS:
17
+ == Synopsis:
14
18
 
15
- rubydoctest comes as an executable that takes a file or directory:
19
+ rubydoctest comes as an executable that takes a list of files:
16
20
 
17
- rubydoctest .
21
+ rubydoctest lib/*.rb
18
22
  rubydoctest simple.doctest
19
23
 
20
- == EXAMPLE:
24
+ == Examples:
21
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
+
22
35
  Here is an example doctest file (say called simple.doctest):
23
36
 
24
37
  # Simple test of RubyDocTest
@@ -33,30 +46,9 @@ Here is an example doctest file (say called simple.doctest):
33
46
  >> 1 + 2
34
47
  => 4
35
48
 
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
49
+ See the doc directory of this project for more .doctest examples and documentation.
58
50
 
59
- == INSTALL:
51
+ == Installation:
60
52
 
61
53
  Major releases:
62
54
 
@@ -66,9 +58,9 @@ Build from source:
66
58
 
67
59
  git clone git://github.com/tablatom/rubydoctest.git
68
60
  cd rubydoctest
69
- rake manifest && rake install
61
+ rake manifest:refresh && rake install
70
62
 
71
- == SELF-DOCTESTING:
63
+ == Testing DocTest:
72
64
 
73
65
  Ruby DocTest uses itself to test and document itself.
74
66
 
@@ -79,31 +71,30 @@ using script/rstakeout
79
71
 
80
72
  rake test:doctest:auto
81
73
 
82
- == TEXTMATE BUNDLE:
74
+ == TextMate Bundle:
83
75
 
84
76
  See http://github.com/drnic/ruby-doctest-tmbundle
85
77
 
86
- == LICENSE:
78
+ == License:
87
79
 
88
80
  (The MIT License)
89
81
 
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.
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.
@@ -1,35 +1,51 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- USAGE = "USAGE: rdoctest [ --html ] [ --trace ] [ --debugger ] <path>"
4
-
5
- SUFFIX = "{r,}doctest"
3
+ if ARGV.empty?
4
+ puts <<-DIRECTIONS
5
+ USAGE: rubydoctest [options] <files>
6
+
7
+ rubydoctest parses Ruby files (.rb) or DocTest files (.doctest) for irb-style
8
+ sessions in comments, and runs the commented sessions as tests.
9
+
10
+ Options:
11
+ Output Format:
12
+ --html - output in HTML format
13
+ --plain - force output in plain text (no Ansi colors)
14
+
15
+ Debug:
16
+ --ignore-interactive - do not heed !!! special directives
17
+ --trace - turn backtrace on to debug Ruby DocTest
18
+ --debugger - include ruby-debug library / gem
19
+
20
+ See http://github.com/tablatom/rubydoctest/wikis for more information.
21
+ DIRECTIONS
22
+ exit 0
23
+ end
6
24
 
7
- file = ARGV.pop or (puts USAGE; exit 1)
25
+ options, files = ARGV.partition{ |a| a =~ /^--/ }
8
26
 
9
27
  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")
28
+ requires << 'ruby-debug' if options.include?("--debugger")
29
+ ruby_lines = []
30
+ ruby_lines << "RubyDocTest.trace = true;" if options.include?("--trace")
31
+ ruby_lines << "RubyDocTest.ignore_interactive = true;" if options.include?("--ignore-interactive")
19
32
 
20
33
  requires = requires.map {|lib| "require '#{lib}'; "}.join
21
34
 
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")
35
+ def files_runner(command, files, requires, lines)
36
+ files.reverse_each do |f|
37
+ system %(#{command} -e "#{requires} #{lines.join(" ")} RubyDocTest::Runner.new(File.read('#{f}'), '#{f}').run")
38
+ end
33
39
  end
34
40
 
35
- puts "</pre></body></html>" if ARGV.include?("--html")
41
+ if options.include?("--plain")
42
+ ruby_lines << "RubyDocTest.output_format = :plain;"
43
+ files_runner("ruby", files, requires, ruby_lines)
44
+ elsif options.include?("--html")
45
+ ruby_lines << "RubyDocTest.output_format = :html;"
46
+ puts "<html><body><pre>"
47
+ files_runner("ruby", files, requires, ruby_lines)
48
+ puts "</pre></body></html>"
49
+ else
50
+ files_runner("ruby", files, requires, ruby_lines)
51
+ end
@@ -1,15 +1,13 @@
1
1
  require 'rubydoctest/version'
2
2
 
3
- AUTHOR = ['Tom Locke', 'Dr Nic Williams'] # can also be an array of Authors
4
- EMAIL = "drnicwilliams@gmail.com"
3
+ AUTHOR = ['Duane Johnson', 'Tom Locke', 'Dr Nic Williams'] # can also be an array of Authors
4
+ EMAIL = "duane.johnson@gmail.com"
5
5
  DESCRIPTION = "Ruby version of Python's doctest tool, but a bit different."
6
6
  GEM_NAME = 'rubydoctest' # what ppl will type to install your gem
7
7
  RUBYFORGE_PROJECT = 'rubydoctest' # The unix name for your project
8
8
  HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
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]
10
+ EXTRA_DEPENDENCIES = []
13
11
 
14
12
  @config_file = "~/.rubyforge/user-config.yml"
15
13
  @config = nil
@@ -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
@@ -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