rspec 0.5.9 → 0.5.10

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/CHANGES CHANGED
@@ -1,5 +1,10 @@
1
1
  = RSpec Changelog
2
2
 
3
+ == Version 0.5.10
4
+ This version features a second rewrite of test2spec - hopefully better than the previous one.
5
+
6
+ * Improved test2spec's internals. It now transforms the syntax tree before writing out the code.
7
+
3
8
  == Version 0.5.9
4
9
  This release improves test2spec by allowing more control over the output
5
10
 
data/README CHANGED
@@ -3,15 +3,16 @@ Then you must install the following gems:
3
3
 
4
4
  * rake
5
5
  * rcov
6
- * RubyInline
7
6
  * ParseTree (Ignore the message: test/test_parse_tree.rb:190:38: ':' not followed by identified or operator)
7
+ * RubyInline
8
8
  * webgen
9
9
  * RedCloth
10
10
  * syntax
11
11
 
12
12
  Note that RSpec itself - once built - doesn't have any dependencies outside the Ruby core
13
13
  and stdlib - with a few exceptions:
14
- * test2spec uses RubyInline, RubyToC and ParseTree
15
- * The spectask needs rcov if rcov is enabled.
14
+
15
+ * The test2spec command line uses ParseTree and RubyInline
16
+ * The Spec::Rake::SpecTask needs RCov if RCov is enabled in the task.
16
17
 
17
18
  See http://rspec.rubyforge.org for further documentation.
data/Rakefile CHANGED
@@ -6,8 +6,6 @@ require 'rake/clean'
6
6
  require 'rake/testtask'
7
7
  require 'rake/rdoctask'
8
8
  require 'spec/version'
9
- require 'spec/rake/spectask'
10
- require 'spec/rake/rcov_verify'
11
9
  require 'rcov/rcovtask'
12
10
 
13
11
  # Some of the tasks are in separate files since they are also part of the website documentation
@@ -27,7 +25,7 @@ PKG_FILES = FileList[
27
25
  'doc/**/*'
28
26
  ]
29
27
 
30
- task :default => [:test]
28
+ task :default => :test
31
29
 
32
30
  desc "Run all failing examples"
33
31
  Spec::Rake::SpecTask.new('failing_examples') do |t|
@@ -47,12 +45,18 @@ end
47
45
 
48
46
  desc 'Translate our own tests to specs'
49
47
  task :test2spec do
50
- `bin/test2spec --template spec/test2spec.erb --specdir spec test`
48
+ `bin/test2spec --force --template spec/test2spec.erb --specdir spec/translated test`
51
49
  end
52
50
 
53
51
  desc 'Generate HTML documentation'
54
- task :doc => :test2spec do
55
- sh %{pushd doc; webgen; popd}
52
+ task :webgen => :test2spec do
53
+ Dir.chdir 'doc' do
54
+ output = nil
55
+ IO.popen('webgen 2>&1') do |io|
56
+ output = io.read
57
+ end
58
+ raise "ERROR while running webgen: #{output}" if output =~ /ERROR/n || $? != 0
59
+ end
56
60
  end
57
61
 
58
62
  desc 'Generate RDoc'
@@ -119,7 +123,7 @@ end
119
123
 
120
124
  task :clobber do
121
125
  rm_rf 'doc/output'
122
- rm_rf 'spec/spec'
126
+ rm_rf 'spec/translated'
123
127
  end
124
128
 
125
129
  task :release => [:clobber, :verify_committed, :verify_user, :verify_password, :test, :publish_packages, :tag, :publish_website, :publish_news]
@@ -141,7 +145,7 @@ task :tag do
141
145
  end
142
146
 
143
147
  desc "Build the website with rdoc and rcov, but do not publish it"
144
- task :website => [:clobber, :rcov_verify, :doc, :examples_specdoc, :rdoc]
148
+ task :website => [:clobber, :rcov_verify, :webgen, :examples_specdoc, :rdoc]
145
149
 
146
150
  task :verify_user do
147
151
  raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
@@ -7,10 +7,10 @@ require 'test/unit/ui/testrunnermediator'
7
7
  require 'test/unit/autorunner'
8
8
  require 'optparse'
9
9
 
10
- $LOAD_PATH.push File.dirname(__FILE__) + '/../lib'
10
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
11
11
 
12
12
  require 'rubygems'
13
- require 'spec/tool/translation_test_runner'
13
+ require 'spec/test_to_spec/translation_test_runner'
14
14
  require 'spec/version'
15
15
 
16
16
  $test2spec_options = {
@@ -26,13 +26,11 @@ opts = OptionParser.new do |opts|
26
26
  end
27
27
 
28
28
  opts.on("-t", "--template FILE",
29
- "ERB template that will be used to create each file. The template",
30
- "has access toi the following variables:",
29
+ "ERB template that will be used to decorate each translated file.",
30
+ "The template has access to the following variables:",
31
31
  " translation : the translated source code",
32
32
  " depth : the directory depth of the file to be written",
33
- " relative_path : the relative name of the file to be written",
34
- "Example:",
35
- "<%= @translation %>"
33
+ " relative_path : the relative name of the file to be written"
36
34
  ) do |file|
37
35
  $test2spec_options[:template] = file
38
36
  end
@@ -87,7 +85,7 @@ module Test
87
85
  class AutoRunner
88
86
  def initialize(standalone)
89
87
  @standalone = standalone
90
- @runner = proc { |r| Spec::Tool::TranslationTestRunner }
88
+ @runner = proc { |r| Spec::TestToSpec::TranslationTestRunner }
91
89
  @collector = COLLECTORS[(standalone ? :dir : :objectspace)]
92
90
  @filters = []
93
91
  @to_run = []
@@ -0,0 +1,19 @@
1
+ require 'webgen/plugins/tags/tags'
2
+ require File.dirname(__FILE__) + '/../../lib/spec/version'
3
+
4
+ module Tags
5
+
6
+ class VersionTag < DefaultTag
7
+
8
+ summary "Puts the version on the page"
9
+ depends_on 'Tags'
10
+
11
+ tag 'version'
12
+
13
+ def process_tag(tag, node, refNode)
14
+ return Spec::VERSION::STRING
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -11,7 +11,7 @@
11
11
  <div id="container">
12
12
  <div id="header">
13
13
  <h2>Behaviour Driven Development for <strong>Ruby</strong></h2>
14
- <h1>RSpec</h1>
14
+ <h1>RSpec {version: }</h1>
15
15
  </div>
16
16
 
17
17
  <div id="navigation">
@@ -4,7 +4,7 @@ inMenu: true
4
4
  ---
5
5
  h2. Rake Task
6
6
 
7
- RSpec coomes with a Rake task for executing specs.
7
+ RSpec comes with a Rake task for executing specs.
8
8
  See "Spec::Rake::SpecTask":../rdoc/classes/Spec/Rake/SpecTask.html for details.
9
9
 
10
10
  h3. Run specs
@@ -2,11 +2,11 @@
2
2
  title: Test::Unit Migration
3
3
  inMenu: true
4
4
  ---
5
- h2. Test::Unit migration
5
+ h2. Overview of test2spec
6
6
 
7
7
  RSpec's test2spec command line tool translates existing Test::Unit classes to RSpec.
8
8
 
9
- Before you can use test2spec you must gem install ParseTree and RubyInline.
9
+ Before you can use test2spec you must gem install ParseTree (and RubyInline).
10
10
  RubyInline only works on systems that have a C compiler - i.e. most anything except Windows.
11
11
 
12
12
  If you're stuck on Windows, ask a friend who has a POSIX system to translate your specs.
@@ -46,10 +46,10 @@ h2. Sample translation
46
46
  <tbody>
47
47
  <tr>
48
48
  <td>
49
- <ruby file="../test/spec/tool/test_unit_api_test.rb"/>
49
+ <ruby file="../test/spec/test_to_spec/testfiles/test_unit_api_test.rb"/>
50
50
  </td>
51
51
  <td>
52
- <ruby file="../spec/spec/tool/test_unit_api_spec.rb"/>
52
+ <ruby file="../spec/translated/test_unit_api_spec.rb"/>
53
53
  </td>
54
54
  </tr>
55
55
  </tbody>
@@ -73,17 +73,20 @@ at RSpec's bug report system along with some code so we can reproduce (and hope
73
73
 
74
74
  h2. Internals
75
75
 
76
- The test2spec tool is based on three other tools:
76
+ The test2spec commandline 'runs' the tests with a special test runner - one that translates and writes out
77
+ the translations to disk instead of actually executing the tests.
78
+
79
+ The translation is done by the <tt>Test::Unit::TestCase#to_rspec</tt> method (which test2spec adds to all
80
+ test classes). This method will load the parse tree for the class, transform that tree to an RSpec context
81
+ and return the source code (using RubyToRuby).
82
+
83
+ test2spec is based directly on two other tools:
77
84
 
78
85
  * "RubyToRuby":http://blog.zenspider.com/archives/2005/02/rubytoruby.html
79
86
  * "ParseTree":http://rubyforge.org/projects/parsetree/
80
- * "RubyInline":http://rubyforge.org/projects/rubyinline/
81
87
 
82
88
  In fact, it's based on a modified version of "George Moschovitis' RubyToRuby enhancement":http://dark.fhtr.org/ruby2ruby.rb
83
89
  of "Ryan Davis' original RubyToRuby":http://blog.zenspider.com/archives/2005/02/rubytoruby.html.
84
90
 
85
91
  It has been modified to fix some subtle bugs that were not found by Gerorge's tests. The modified RubyToRuby
86
92
  currently lives in RSpec's subversion repository.
87
-
88
- The translation is done by TestUnitTranslator - subclass of RubyToRuby that writes out the syntax tree a little differently than
89
- its superclass. TestUnitTranslator looks for certain Test::Unit patterns and writes out an RSpec translation instead.
@@ -85,7 +85,7 @@ module Rake
85
85
  specs = file_list
86
86
  raise "No spec files found." if specs.empty?
87
87
 
88
- spec = File.dirname(__FILE__) + '/../../../bin/spec'
88
+ spec = File.expand_path(File.dirname(__FILE__) + '/../../../bin/spec')
89
89
  file_prefix = @rcov ? " -- " : ""
90
90
  interpreter = @rcov ? "rcov" : "ruby"
91
91
  redirect = @out.nil? ? "" : " > #{@out}"
@@ -62,11 +62,10 @@ module Spec
62
62
  end
63
63
 
64
64
  # This method is invoked at the very end.
65
- def dump_summary(duration, context_count, spec_count, failure_count)
65
+ def dump_summary(duration, spec_count, failure_count)
66
66
  return if @dry_run
67
67
  @output << "\n"
68
68
  @output << "Finished in " << (duration).to_s << " seconds\n\n"
69
- @output << "#{context_count} context#{'s' unless context_count == 1}, "
70
69
  @output << "#{spec_count} specification#{'s' unless spec_count == 1}, "
71
70
  @output << "#{failure_count} failure#{'s' unless failure_count == 1}"
72
71
  @output << "\n"
@@ -43,7 +43,7 @@ module Spec
43
43
  def dump
44
44
  @formatter.start_dump
45
45
  dump_failures
46
- @formatter.dump_summary(duration, @context_names.length, @spec_names.length, @failures.length)
46
+ @formatter.dump_summary(duration, @spec_names.length, @failures.length)
47
47
  @failures.length
48
48
  end
49
49
 
@@ -5,7 +5,7 @@ begin
5
5
  require 'parse_tree'
6
6
  require 'sexp_processor'
7
7
  rescue LoadError
8
- $stderr.puts "You must gem install ParseTree (and RubyInline)"
8
+ raise "You must gem install ParseTree (and RubyInline)"
9
9
  end
10
10
 
11
11
  class RubySource < String
@@ -482,5 +482,9 @@ class RubyToRuby < SexpProcessor
482
482
  end
483
483
  code.join("\n")
484
484
  end
485
-
485
+
486
+ def process_bmethod(exp)
487
+ raise "FIXME"
488
+ end
489
+
486
490
  end
@@ -0,0 +1,189 @@
1
+ require 'sexp_processor'
2
+
3
+ module Spec
4
+ module TestToSpec
5
+ # Transforms a Sexp tree (produced by ParseTree) for a Test::Unit class
6
+ # to an Sexp tree representing an RSpec context
7
+ class SexpTransformer < SexpProcessor
8
+ TRANSLATIONS = {
9
+ :assert_equal => :should_equal,
10
+ :assert_not_equal => :should_not_equal,
11
+ :assert_same => :should_be,
12
+ :assert_not_same => :should_not_be,
13
+ :assert_instance_of => :should_be_instance_of,
14
+ :assert_kind_of => :should_be_kind_of,
15
+ :assert_match => :should_match,
16
+ :assert_no_match => :should_not_match,
17
+ :assert_respond_to => :should_respond_to,
18
+ :assert => :should_be,
19
+ :assert_nil => :should_be,
20
+ :assert_not_nil => :should_not_be,
21
+ :assert_in_delta => :should_be_close,
22
+ :assert_block => :should_be,
23
+ :assert_raise => :should_raise,
24
+ :assert_raises => :should_raise,
25
+ :assert_nothing_raised => :should_not_raise,
26
+ :assert_throws => :should_throw,
27
+ :assert_nothing_thrown => :should_not_throw,
28
+ }
29
+
30
+ def initialize
31
+ super
32
+ self.expected = Array
33
+ end
34
+
35
+ def process(exp)
36
+ #puts "PROCESS:#{exp[0]}"
37
+ super
38
+ end
39
+
40
+ def process_class(exp)
41
+ # Get the class header
42
+ exp.shift
43
+ class_name = exp.shift.to_s.split("::").last
44
+ context_name = class_name.match(/(.*)Test/)[1]
45
+ exp.shift
46
+
47
+ # Partition all methods (and other stuff) into chunks, as we're
48
+ # going to handle them a bit differently
49
+ rest = exp
50
+ setup, rest = rest.partition{|e| e[0] == :defn && e[1].to_s == "setup"}
51
+ teardown, rest = rest.partition{|e| e[0] == :defn && e[1].to_s == "teardown"}
52
+ tests, rest = rest.partition{|e| e[0] == :defn && e[1].to_s =~ /^test/}
53
+ methods, rest = rest.partition{|e| e[0] == :defn}
54
+
55
+ if !methods.empty? && setup.empty?
56
+ # We have some methods, but no setup to put them in. Create empty setup
57
+ setup[0] = [:defn, :setup, [:scope, [:block, [:args], [:nil]]]]
58
+ end
59
+
60
+ context_body = []
61
+ unless setup.empty?
62
+ setup_block = process(setup.shift)
63
+ unless methods.empty?
64
+ if setup_block.length == 3
65
+ setup_block += methods
66
+ else
67
+ setup_block[3] += methods
68
+ end
69
+ end
70
+ context_body << setup_block
71
+ end
72
+ context_body << process(teardown.shift) until teardown.empty?
73
+ context_body << process(tests.shift) until tests.empty?
74
+ context_body << process(rest.shift) until rest.empty?
75
+ exp.clear
76
+
77
+ result = [:iter, [:fcall, :context, [:array, [:str, context_name]]], nil]
78
+ if context_body.length > 1
79
+ result << [:block] + context_body
80
+ else
81
+ result += context_body
82
+ end
83
+ [result]
84
+ end
85
+
86
+ def process_defn(exp)
87
+ method_name = exp[1].to_s
88
+ if method_name =~ /^test_(.*)/
89
+ spec_name = $1.gsub(/_/, " ")
90
+
91
+ test_body = exp[2][1][2..-1]
92
+ exp.clear
93
+ block_body = []
94
+ @dasgn_decl = []
95
+ block_body << process(test_body.shift) until test_body.empty?
96
+ result = [:iter, [:fcall, :specify, [:array, [:str, spec_name]]], nil]
97
+ result << [:block] unless block_body == [[:nil]]
98
+ result[-1] += @dasgn_decl unless @dasgn_decl.empty?
99
+ result[-1] += block_body unless block_body == [[:nil]]
100
+ result
101
+ elsif method_name == "setup" || method_name == "teardown"
102
+ test_body = exp[2][1][2..-1]
103
+ exp.clear
104
+ block_body = []
105
+ @dasgn_decl = []
106
+ block_body << process(test_body.shift) until test_body.empty?
107
+ result = [:iter, [:fcall, method_name.to_sym], nil]
108
+ result << [:block] unless block_body == [[:nil]]
109
+ result[-1] += @dasgn_decl unless @dasgn_decl.empty?
110
+ result[-1] += block_body unless block_body == [[:nil]]
111
+ result
112
+ end
113
+ end
114
+
115
+ def process_lasgn(exp)
116
+ result = exp.dup
117
+ result[0] = :dasgn_curr
118
+ decl = result[0..1].dup
119
+ if @dasgn_decl.empty?
120
+ @dasgn_decl += [decl]
121
+ else
122
+ @dasgn_decl_tail << decl
123
+ end
124
+ @dasgn_decl_tail = decl
125
+ exp.clear
126
+ result
127
+ end
128
+
129
+ # Handles 'block' assert_ calls
130
+ def process_iter(exp)
131
+ test_unit_fcall = exp[1][1]
132
+ rspec_should = TRANSLATIONS[test_unit_fcall]
133
+ unless rspec_should.nil?
134
+ body = exp[3]
135
+ args = exp[1][2]
136
+ args.delete_at(2) unless args.nil? # get rid of the message arg
137
+ result = [:call, [:iter, [:fcall, :lambda], nil, body], rspec_should]
138
+ result << args unless args.nil?
139
+ result << [:array, [:true]] if test_unit_fcall == :assert_block
140
+ exp.clear
141
+ result
142
+ else
143
+ exp.shift
144
+ result = [:iter]
145
+ result << process(exp.shift) until exp.empty?
146
+ result
147
+ end
148
+ end
149
+
150
+ # Handles regular assert_ calls
151
+ def process_fcall(exp)
152
+ test_unit_fcall = exp[1]
153
+ rspec_should = TRANSLATIONS[test_unit_fcall]
154
+ unless rspec_should.nil?
155
+ args = exp[2]
156
+ actual_index = [:assert, :assert_not_nil, :assert_nil, :assert_respond_to].index(test_unit_fcall) ? 1 : 2
157
+ actual = args.delete_at(actual_index)
158
+ expected = args
159
+ if test_unit_fcall == :assert_in_delta
160
+ expected.delete_at(3)
161
+ expected << args.delete_at(2)
162
+ else
163
+ msg_index = (test_unit_fcall == :assert_respond_to) ? 2 : actual_index
164
+ expected.delete_at(msg_index)
165
+ end
166
+ expected << [:true] if test_unit_fcall == :assert
167
+ expected << [:nil] if [:assert_not_nil, :assert_nil].index(test_unit_fcall)
168
+
169
+ actual = process(actual)
170
+
171
+ result = [:call, actual, rspec_should, expected]
172
+ exp.clear
173
+ result
174
+ else
175
+ result = exp.dup
176
+ exp.clear
177
+ result
178
+ end
179
+ end
180
+
181
+ def process_lvar(exp)
182
+ result = exp.dup
183
+ result[0] = :dvar
184
+ exp.clear
185
+ result
186
+ end
187
+ end
188
+ end
189
+ end