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.
@@ -0,0 +1,44 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'lines'
5
+
6
+ module RubyDocTest
7
+ class SpecialDirective < Lines
8
+ NAMES = ["doctest:", "!!!", "doctest_require:"]
9
+ NAMES_FOR_RX = NAMES.map{ |n| Regexp.escape(n) }.join("|")
10
+
11
+ # === Test
12
+ #
13
+ # doctest: The name of the directive should be detected in the first line
14
+ # >> s = RubyDocTest::SpecialDirective.new(["doctest: Testing Stuff", "Other Stuff"])
15
+ # >> s.name
16
+ # => "doctest:"
17
+ def name
18
+ if m = lines.first.match(/^#{Regexp.escape(indentation)}(#{NAMES_FOR_RX})/)
19
+ m[1]
20
+ end
21
+ end
22
+
23
+ # === Test
24
+ #
25
+ # doctest: The value of the directive should be detected in the first line
26
+ # >> s = RubyDocTest::SpecialDirective.new(["doctest: Testing Stuff", "Other Stuff"])
27
+ # >> s.value
28
+ # => "Testing Stuff"
29
+ #
30
+ # >> s = RubyDocTest::SpecialDirective.new([" # doctest: Testing Stuff", " # Other Stuff"])
31
+ # >> s.value
32
+ # => "Testing Stuff"
33
+ #
34
+ # doctest: Multiple lines for the directive value should work as well
35
+ # >> s = RubyDocTest::SpecialDirective.new(["doctest: Testing Stuff", " On Two Lines"])
36
+ # >> s.value
37
+ # => "Testing Stuff\nOn Two Lines"
38
+ def value
39
+ if m = lines.join("\n").match(/^#{Regexp.escape(indentation)}(#{NAMES_FOR_RX})(.*)/m)
40
+ m[2].strip
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,75 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubydoctest'
5
+ require 'lines'
6
+
7
+ module RubyDocTest
8
+ class EvaluationError < Exception
9
+ attr_reader :statement, :original_exception
10
+ def initialize(statement, original_exception)
11
+ @statement, @original_exception = statement, original_exception
12
+ end
13
+ end
14
+
15
+ class Statement < Lines
16
+
17
+ attr_reader :actual_result
18
+
19
+ # === Tests
20
+ #
21
+ # doctest: The FILENAME ruby constant should be replaced by the name of the file
22
+ # >> __FILE__[/statement\.rb$/]
23
+ # => "statement.rb"
24
+ def initialize(doc_lines, line_index = 0, file_name = nil)
25
+ @file_name = file_name
26
+ super(doc_lines, line_index)
27
+ end
28
+
29
+ # === Tests
30
+ #
31
+ # doctest: A statement should parse out a '>>' irb prompt
32
+ # >> s = RubyDocTest::Statement.new([">> a = 1"])
33
+ # >> s.source_code
34
+ # => "a = 1"
35
+ #
36
+ # doctest: More than one line should get included, if indentation so indicates
37
+ # >> s = RubyDocTest::Statement.new([">> b = 1 +", " 1", "not part of the statement"])
38
+ # >> s.source_code
39
+ # => "b = 1 +\n1"
40
+ #
41
+ # doctest: Lines indented by ?> should have the ?> removed.
42
+ # >> s = RubyDocTest::Statement.new([">> b = 1 +", "?> 1"])
43
+ # >> s.source_code
44
+ # => "b = 1 +\n1"
45
+ def source_code
46
+ lines.first =~ /^#{Regexp.escape(indentation)}>>\s(.*)$/
47
+ first = [$1]
48
+ remaining = (lines[1..-1] || [])
49
+ (first + remaining).join("\n")
50
+ end
51
+
52
+ # === Test
53
+ #
54
+ # doctest: Evaluating a multi-line statement should be ok
55
+ # >> s = RubyDocTest::Statement.new([">> b = 1 +", " 1", "not part of the statement"])
56
+ # >> s.evaluate
57
+ # => 2
58
+ #
59
+ # doctest: Evaluating a syntax error should raise an EvaluationError
60
+ # >> s = RubyDocTest::Statement.new([">> b = 1 +"])
61
+ # >> begin s.evaluate; :fail; rescue RubyDocTest::EvaluationError; :ok end
62
+ # => :ok
63
+ def evaluate
64
+ sc = source_code.gsub("__FILE__", @file_name.inspect)
65
+ # puts "EVAL: #{sc}"
66
+ @actual_result = eval(sc, TOPLEVEL_BINDING, __FILE__, __LINE__)
67
+ rescue Exception => e
68
+ if RubyDocTest.trace
69
+ raise e.class, e.to_s + "\n" + e.backtrace.first
70
+ else
71
+ raise EvaluationError.new(self, e)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,29 @@
1
+ module RubyDocTest
2
+ # This is the top-level 'test' container that holds an optional description and one
3
+ # or more CodeBlock objects.
4
+ class Test
5
+ attr_accessor :description
6
+ attr_reader :code_blocks, :passed
7
+
8
+ def initialize(description, code_blocks)
9
+ @description, @code_blocks = description, code_blocks
10
+ end
11
+
12
+ def pass?
13
+ @passed = @code_blocks.all?{ |c| c.pass? }
14
+ end
15
+
16
+ def first_failed
17
+ @code_blocks.detect{ |cb| !cb.pass? }
18
+ end
19
+
20
+ def actual_result
21
+ first_failed.actual_result.inspect
22
+ end
23
+
24
+ def expected_result
25
+ first_failed.expected_result
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,32 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{rubydoctest}
3
+ s.version = "1.0.0"
4
+
5
+ s.specification_version = 2 if s.respond_to? :specification_version=
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Duane Johnson", "Tom Locke", "Dr Nic Williams"]
9
+ s.date = %q{2008-06-21}
10
+ s.default_executable = %q{rubydoctest}
11
+ s.description = %q{Ruby version of Python's doctest tool, but a bit different.}
12
+ s.email = ["duane.johnson@gmail.com"]
13
+ s.executables = ["rubydoctest"]
14
+ s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "website/index.txt"]
15
+ s.files = IO.read("Manifest.txt").split("\n")
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://rubydoctest.rubyforge.org}
18
+ s.post_install_message = %q{
19
+ rubydoctest comes as an executable that takes a file or directory:
20
+
21
+ rubydoctest .
22
+ rubydoctest simple.doctest
23
+
24
+
25
+ }
26
+ s.rdoc_options = ["--main", "README.txt"]
27
+ s.require_paths = ["lib"]
28
+ s.rubyforge_project = %q{rubydoctest}
29
+ s.rubygems_version = %q{1.1.1}
30
+ s.summary = %q{Ruby version of Python's doctest tool, but a bit different.}
31
+ s.test_files = []
32
+ end
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ##
4
+ # Originally by Mike Clark.
5
+ #
6
+ # From http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/StakingOutFileChanges.rdoc
7
+ #
8
+ # Runs a user-defined command when files are modified.
9
+ #
10
+ # Like autotest, but more customizable. This is useful when you want to do
11
+ # something other than run tests. For example, generate a PDF book, run
12
+ # a single test, or run a legacy Test::Unit suite in an app that also
13
+ # has an rSpec suite.
14
+ #
15
+ # Can use Ruby's Dir[] to get file glob. Quote your args to take advantage of this.
16
+ #
17
+ # rstakeout 'rake test:recent' **/*.rb
18
+ # => Only watches Ruby files one directory down (no quotes)
19
+ #
20
+ # rstakeout 'rake test:recent' '**/*.rb'
21
+ # => Watches all Ruby files in all directories and subdirectories
22
+ #
23
+ # Modified (with permission) by Geoffrey Grosenbach to call growlnotify for
24
+ # rspec and Test::Unit output.
25
+ #
26
+ # See the PeepCode screencast on rSpec or other blog articles for instructions on
27
+ # setting up growlnotify.
28
+
29
+ def growl(title, msg, img, pri=0, sticky="")
30
+ system "growlnotify -n autotest --image ~/.autotest_images/#{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"
31
+ end
32
+
33
+ def self.growl_fail(output)
34
+ growl "FAIL", "#{output}", "fail.png", 2
35
+ end
36
+
37
+ def self.growl_pass(output)
38
+ growl "Pass", "#{output}", "pass.png"
39
+ end
40
+
41
+ command = ARGV.shift
42
+ files = {}
43
+
44
+ ARGV.each do |arg|
45
+ Dir[arg].each { |file|
46
+ files[file] = File.mtime(file)
47
+ }
48
+ end
49
+
50
+ puts "Watching #{files.keys.join(', ')}\n\nFiles: #{files.keys.length}"
51
+
52
+ trap('INT') do
53
+ puts "\nQuitting..."
54
+ exit
55
+ end
56
+
57
+
58
+ loop do
59
+
60
+ sleep 1
61
+
62
+ changed_file, last_changed = files.find { |file, last_changed|
63
+ File.mtime(file) > last_changed
64
+ }
65
+
66
+ if changed_file
67
+ files[changed_file] = File.mtime(changed_file)
68
+ puts "=> #{changed_file} changed, running #{command}"
69
+ args = ""
70
+ args += ARGV.last == '--pass-as-arg' ? changed_file : ""
71
+ args += ARGV.last == '--pass-as-env' ? "CHANGED=#{changed_file}" : ""
72
+ puts "Executing: #{command} #{args}"
73
+ results = `#{command} #{args}`
74
+ puts results
75
+
76
+ if results.include? 'tests'
77
+ output = results.slice(/(\d+)\s+tests?,\s*(\d+)\s+assertions?,\s*(\d+)\s+failures?(,\s*(\d+)\s+errors)?/)
78
+ if output
79
+ $~[3].to_i + $~[5].to_i > 0 ? growl_fail(output) : growl_pass(output)
80
+ end
81
+ else
82
+ output = results.slice(/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+not implemented)?/)
83
+ if output
84
+ $~[2].to_i > 0 ? growl_fail(output) : growl_pass(output)
85
+ end
86
+ end
87
+ # TODO Generic growl notification for other actions
88
+
89
+ puts "=> done"
90
+ end
91
+
92
+ end
@@ -0,0 +1,29 @@
1
+ namespace :test do
2
+ desc "Run doctests"
3
+ task :doctest do
4
+ sh "ruby #{File.dirname(__FILE__)}/../bin/rubydoctest #{File.dirname(__FILE__)}/../lib/*.rb"
5
+ sh "ruby #{File.dirname(__FILE__)}/../bin/rubydoctest #{File.dirname(__FILE__)}/../doc/*.doctest"
6
+ end
7
+
8
+ namespace :doctest do
9
+ desc "Run rstakeout on test/doctest files"
10
+ task :auto do
11
+ tests = "#{File.dirname(__FILE__)}/../test/doctest/*"
12
+ tests_path = File.dirname(tests)
13
+ files = "#{File.dirname(__FILE__)}/../lib/*.rb #{File.dirname(__FILE__)}/../bin/*"
14
+ sh "#{File.dirname(__FILE__)}/../script/rstakeout 'rake test:doctest:changed DOCTESTS=#{tests_path}' #{tests} #{files} --pass-as-env"
15
+ end
16
+
17
+ desc "Run doctest(s) based on a specific file that changed"
18
+ task :changed do
19
+ file = ENV['CHANGED']
20
+ doctests = ENV['DOCTESTS']
21
+ unless file && doctests
22
+ puts "Requires ENV['CHANGED']=file_path and ENV['DOCTESTS']=some/path/**/*.doctest"
23
+ exit
24
+ end
25
+ tests = File.basename(file) =~ %r{\..*doctest\Z} ? file : doctests
26
+ sh "ruby #{File.dirname(__FILE__)}/../bin/rubydoctest #{tests}"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ { scopeName = 'text.html.markdown.ruby.doctest';
2
+ fileTypes = ( 'doctest', 'rdoctest' );
3
+ patterns = (
4
+ { include = 'text.ruby.doctest'; },
5
+ { include = 'text.html.markdown'; }
6
+ );
7
+ }
@@ -0,0 +1,55 @@
1
+ { scopeName = 'source.ruby.doctest';
2
+ patterns = (
3
+ { name = 'comment.block.documentation.ruby';
4
+ comment = 'multiline comments';
5
+ begin = '^=begin';
6
+ end = '^=end';
7
+ captures = { 0 = { name = 'punctuation.definition.comment.ruby'; }; };
8
+ patterns = (
9
+ { include = "text.ruby.doctest"; }
10
+ );
11
+ },
12
+ {
13
+ name = 'source.ruby.doctest.description.commented';
14
+ begin = '^([ \t]*(#)\s+)(doctest:)(.*)';
15
+ end = '^(?!\1)|^(?=\1[^\s])|^(?=\1$)';
16
+ captures = {
17
+ 2 = { name = 'comment.line.number-sign.ruby';};
18
+ 3 = { name = 'keyword.ruby.doctest'; };
19
+ 4 = { name = 'comment.ruby.doctest'; };
20
+ };
21
+ patterns = (
22
+ { include = '#indented_description'; }
23
+ );
24
+ },
25
+ {
26
+ name = 'source.ruby.doctest.statement.commented';
27
+ begin = '^([ \t]*(#)\s+)(>>|=>|doctest_require:)';
28
+ end = '^(?!\1)|^(?=\1[^\s])|^(?=\1$)';
29
+ captures = {
30
+ 2 = { name = 'comment.line.number-sign.ruby'; };
31
+ 3 = { name = 'keyword.ruby.doctest'; };
32
+ };
33
+ patterns = (
34
+ { include = 'source.ruby.rails'; }
35
+ );
36
+ },
37
+ {
38
+ name = 'source.ruby.doctest.directive';
39
+ begin = '^([ \t]*(#)\s+)(\!\!\!)\s*$';
40
+ end = '\n';
41
+ captures = {
42
+ 2 = { name = 'comment.line.number-sign.ruby'; };
43
+ 3 = { name = 'keyword.ruby.doctest'; };
44
+ };
45
+ },
46
+ { include = 'source.ruby'; }
47
+ );
48
+ repository = {
49
+ indented_description = {
50
+ name = 'comment.ruby.doctest';
51
+ begin = '^([ \t]*#\s+)(.+)';
52
+ end = '^(?!\1)';
53
+ };
54
+ };
55
+ }
@@ -0,0 +1,66 @@
1
+ { scopeName = 'text.ruby.doctest';
2
+ fileTypes = ( 'txt', 'text' );
3
+ patterns = (
4
+ {
5
+ name = 'source.ruby.doctest.description.unindented';
6
+ begin = '^(doctest:)(.*)';
7
+ end = '^(?=[^\s]|$)';
8
+ captures = {
9
+ 1 = { name = 'keyword.ruby.doctest'; };
10
+ 2 = { name = 'comment.ruby.doctest'; };
11
+ };
12
+ patterns = (
13
+ { include = '#indented_description'; }
14
+ );
15
+ },
16
+ {
17
+ name = 'source.ruby.doctest.description.indented';
18
+ begin = '^(\s+)(doctest:)(.*)';
19
+ end = '^(?!\1)|^(?=\1[^\s])|^(?=\1$)';
20
+ captures = {
21
+ 2 = { name = 'keyword.ruby.doctest'; };
22
+ 3 = { name = 'comment.ruby.doctest'; };
23
+ };
24
+ patterns = (
25
+ { include = '#indented_description'; }
26
+ );
27
+ },
28
+ {
29
+ name = 'source.ruby.doctest.statement.unindented';
30
+ begin = '^(>>|=>|doctest_require:)';
31
+ end = '^(?=[^\s]|$)';
32
+ captures = {
33
+ 1 = { name = 'keyword.ruby.doctest'; };
34
+ };
35
+ patterns = (
36
+ { include = 'source.ruby.rails'; }
37
+ );
38
+ },
39
+ {
40
+ name = 'source.ruby.doctest.statement.indented';
41
+ begin = '^(\s+)(>>|=>|doctest_require:)';
42
+ end = '^(?!\1)|^(?=\1[^\s])|^(?=\1$)';
43
+ captures = {
44
+ 2 = { name = 'keyword.ruby.doctest'; };
45
+ };
46
+ patterns = (
47
+ { include = 'source.ruby.rails'; }
48
+ );
49
+ },
50
+ {
51
+ name = 'source.ruby.doctest.directive';
52
+ begin = '^(\s*)(\!\!\!)\s*$';
53
+ end = '\n';
54
+ captures = {
55
+ 2 = { name = 'keyword.ruby.doctest'; };
56
+ };
57
+ }
58
+ );
59
+ repository = {
60
+ indented_description = {
61
+ name = 'comment.ruby.doctest';
62
+ begin = '^(\s+)(.+)';
63
+ end = '^(?!\1)';
64
+ };
65
+ };
66
+ }
@@ -1,11 +1,141 @@
1
- <html>
2
- <head>
3
- <meta http-equiv="Content-type" content="text/html; charset=utf-8">
4
- <title>rubydoctest</title>
5
-
6
- </head>
7
- <body id="body">
8
- <p>This page has not yet been created for RubyGem <code>rubydoctest</code></p>
9
- <p>To the developer: To generate it, update website/index.txt and run the rake task <code>website</code> to generate this <code>index.html</code> file.</p>
10
- </body>
11
- </html>
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ rubydoctest
9
+ </title>
10
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
+ <style>
12
+
13
+ </style>
14
+ <script type="text/javascript">
15
+ window.onload = function() {
16
+ settings = {
17
+ tl: { radius: 10 },
18
+ tr: { radius: 10 },
19
+ bl: { radius: 10 },
20
+ br: { radius: 10 },
21
+ antiAlias: true,
22
+ autoPad: true,
23
+ validTags: ["div"]
24
+ }
25
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
+ versionBox.applyCornersToAll();
27
+ }
28
+ </script>
29
+ </head>
30
+ <body>
31
+ <div id="main">
32
+
33
+ <h1>rubydoctest</h1>
34
+ <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/rubydoctest"; return false'>
35
+ <p>Get Version</p>
36
+ <a href="http://rubyforge.org/projects/rubydoctest" class="numbers">1.0.0</a>
37
+ </div>
38
+ <h1>&#x2192; &#8216;rubydoctest&#8217;</h1>
39
+
40
+
41
+ <h2>What</h2>
42
+
43
+
44
+ <h2>Installing</h2>
45
+
46
+
47
+ <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">rubydoctest</span></pre></p>
48
+
49
+
50
+ <h2>The basics</h2>
51
+
52
+
53
+ <h2>Demonstration of usage</h2>
54
+
55
+
56
+ <h2>Forum</h2>
57
+
58
+
59
+ <p><a href="http://groups.google.com/group/rubydoctest">http://groups.google.com/group/rubydoctest</a></p>
60
+
61
+
62
+ <p><span class="caps">TODO</span> &#8211; create Google Group &#8211; rubydoctest</p>
63
+
64
+
65
+ <h2>How to submit patches</h2>
66
+
67
+
68
+ <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
69
+
70
+
71
+ <p><span class="caps">TODO</span> &#8211; pick <span class="caps">SVN</span> or Git instructions</p>
72
+
73
+
74
+ <p>The trunk repository is <code>svn://rubyforge.org/var/svn/rubydoctest/trunk</code> for anonymous access.</p>
75
+
76
+
77
+ <p><span class="caps">OOOORRRR</span></p>
78
+
79
+
80
+ <p>You can fetch the source from either:</p>
81
+
82
+
83
+ <ul>
84
+ <li>rubyforge: <span class="caps">MISSING IN ACTION</span></li>
85
+ </ul>
86
+
87
+
88
+ <p><span class="caps">TODO</span> &#8211; You can not created a RubyForge project, OR have not run <code>rubyforge config</code>
89
+ yet to refresh your local rubyforge data with this projects&#8217; id information.</p>
90
+
91
+
92
+ <p>When you do this, this message will magically disappear!</p>
93
+
94
+
95
+ <p>Or you can hack website/index.txt and make it all go away!!</p>
96
+
97
+
98
+ <ul>
99
+ <li>github: <a href="http://github.com/GITHUB_USERNAME/rubydoctest/tree/master">http://github.com/GITHUB_USERNAME/rubydoctest/tree/master</a></li>
100
+ </ul>
101
+
102
+
103
+ <pre>git clone git://github.com/GITHUB_USERNAME/rubydoctest.git</pre>
104
+
105
+ <p><span class="caps">TODO</span> &#8211; add &#8220;github_username: username&#8221; to ~/.rubyforge/user-config.yml and newgem will reuse it for future projects.</p>
106
+
107
+
108
+ <ul>
109
+ <li>gitorious: <a href="git://gitorious.org/rubydoctest/mainline.git">git://gitorious.org/rubydoctest/mainline.git</a></li>
110
+ </ul>
111
+
112
+
113
+ <pre>git clone git://gitorious.org/rubydoctest/mainline.git</pre>
114
+
115
+ <h3>Build and test instructions</h3>
116
+
117
+
118
+ <pre>cd rubydoctest
119
+ rake test
120
+ rake install_gem</pre>
121
+
122
+ <h2>License</h2>
123
+
124
+
125
+ <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
126
+
127
+
128
+ <h2>Contact</h2>
129
+
130
+
131
+ <p>Comments are welcome. Send an email to <a href="mailto:FIXME"><span class="caps">FIXME</span> full name</a> email via the <a href="http://groups.google.com/group/rubydoctest">forum</a></p>
132
+ <p class="coda">
133
+ <a href="mailto:duane.johnson@gmail.com">Duane Johnson</a>, 17th June 2008<br>
134
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
135
+ </p>
136
+ </div>
137
+
138
+ <!-- insert site tracking codes here, like Google Urchin -->
139
+
140
+ </body>
141
+ </html>