tablatom-rubydoctest 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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