rspec 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -13,6 +13,15 @@
13
13
  * Make sure the PKG_VERSION constant in Rakefile.rb is
14
14
  consistent with the latest version in this document.
15
15
 
16
+ == Version 0.2.0
17
+
18
+ This release provides a tutorial for new users wishing to get started with
19
+ RSpec, and many improvements.
20
+
21
+ * improved reporting in the spec runner output
22
+ * update the examples to the new mock api
23
+ * added TUTORIAL, a getting started document for new users of RSpec
24
+
16
25
  == Version 0.1.7
17
26
 
18
27
  This release improves installation and documentation, mock integration and error reporting.
@@ -19,7 +19,7 @@ PKG_NAME = "rspec"
19
19
  # (This is subject to change - AH)
20
20
  #
21
21
  # REMEMBER TO KEEP PKG_VERSION IN SYNC WITH CHANGELOG
22
- PKG_VERSION = "0.1.7"
22
+ PKG_VERSION = "0.2.0"
23
23
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
24
24
  PKG_FILES = FileList[
25
25
  '[A-Z]*',
@@ -29,9 +29,7 @@ PKG_FILES = FileList[
29
29
  'doc/**/*'
30
30
  ]
31
31
 
32
- task :default => [:test, :test_craps_collector, :test_movie_collector,
33
- :test_rspec_craps, :test_rspec_movie, :test_rspec_craps_and_movie,
34
- :test_text_runner]
32
+ task :default => [:test, :test_text_runner]
35
33
 
36
34
  Rake::TestTask.new do |t|
37
35
  t.libs << "test"
@@ -40,45 +38,6 @@ Rake::TestTask.new do |t|
40
38
  t.verbose = true
41
39
  end
42
40
 
43
- # collector tests need to run individually
44
-
45
- Rake::TestTask.new(:test_craps_collector) do |t|
46
- t.libs << "test"
47
- t.libs << "examples"
48
- t.test_files = FileList['test/craps_collector_test.rb']
49
- t.verbose = true
50
- end
51
-
52
- Rake::TestTask.new(:test_movie_collector) do |t|
53
- t.libs << "test"
54
- t.libs << "examples"
55
- t.test_files = FileList['test/movie_collector_test.rb']
56
- t.verbose = true
57
- end
58
-
59
- # rspec tests need to run individually
60
-
61
- Rake::TestTask.new(:test_rspec_craps) do |t|
62
- t.libs << "test"
63
- t.libs << "examples"
64
- t.test_files = FileList['test/rspec_craps_test.rb']
65
- t.verbose = true
66
- end
67
-
68
- Rake::TestTask.new(:test_rspec_movie) do |t|
69
- t.libs << "test"
70
- t.libs << "examples"
71
- t.test_files = FileList['test/rspec_movie_test.rb']
72
- t.verbose = true
73
- end
74
-
75
- Rake::TestTask.new(:test_rspec_craps_and_movie) do |t|
76
- t.libs << "test"
77
- t.libs << "examples"
78
- t.test_files = FileList['test/rspec_craps_and_movie_test.rb']
79
- t.verbose = true
80
- end
81
-
82
41
  # text runner tests need to run individually
83
42
 
84
43
  Rake::TestTask.new(:test_text_runner) do |t|
@@ -0,0 +1,259 @@
1
+ = Getting Started with RSpec
2
+
3
+ RSpec is a behaviour specification framework for the Ruby Programming
4
+ Language. More information on the Ruby Programming Language can be found at
5
+ http://www.ruby-lang.org/. For more information on Behaviour Driven
6
+ Development, please see _A New Look at Test Driven Development_ which can be
7
+ found at http://www.daveastels.com/index.php?p=5.
8
+
9
+ This document is intended to help those interested in getting started with
10
+ Behaviour Driven Development using the RSpec behaviour specification
11
+ framework. Please send comments and/or corrections to me via email: srbaker at
12
+ pobox dot com.
13
+
14
+ == Installation
15
+
16
+ The first thing you need to do to start specifying your software is to install
17
+ RSpec. Thanks to the work on the Gem packaging of RSpec by Aslak Hellesoy, you
18
+ can install RSpec via RubyGems by issuing the following command:
19
+
20
+ $ gem install rspec
21
+
22
+ If you do not have RubyGems installed, see http://docs.rubygems.org/ for
23
+ information about RubyGems including how to install it.
24
+
25
+ == Usage
26
+
27
+ Once you have RSpec installed, ensure that it is correctly installed by
28
+ running the spec command from the command line without arguments. You should
29
+ get something like the following output:
30
+
31
+ Finished in 0.002726 seconds
32
+
33
+ 0 specifications, 0 expectations, 0 failures
34
+
35
+ If you get this output, you can be sure that RSpec has been installed and is
36
+ ready for use!
37
+
38
+ = Specification Anatomy
39
+
40
+ == Expectations
41
+
42
+ The simplest part of your set of specifications will be an expectation. An
43
+ expectation tells RSpec what the expected result of a piece code is. Your set of
44
+ specifications is simply a collection of expectations about how your code should
45
+ behave.
46
+
47
+ In RSpec, the expectations are methods that are available on every object in the
48
+ system. If I want to set an expectation that the value of 1 is 1, I would write:
49
+
50
+ 1.should_equal 1
51
+
52
+ And to set the expectation that 1 + 1 should be equal to 2, I would write the
53
+ following code:
54
+
55
+ (1 + 1).should_equal 2
56
+
57
+ There are many available expectation methods, and they can be found by looking
58
+ in the API documentation for RSpec. For most, if not all, of the expections
59
+ the negation is also provided. Thus, to ensure that subtracting 1 from 2 does
60
+ not equal 2, write the following:
61
+
62
+ (2 - 1).should_not_equal 2
63
+
64
+ These examples are extremely simple, but they accurately convey the simplicity
65
+ with which expectations can be written. When specifying your software, you are
66
+ simply writing expectations that specify how your software will behave. The rest
67
+ of the constructs in RSpec exist entirely to help you organize your
68
+ expectations, and to provide accurate and helpful reporting when these
69
+ expectations are not met.
70
+
71
+ Eventually, writing expectations for addition and subtraction of numbers will
72
+ get boring. When that happens, you can start writing expectations for your own
73
+ code. Let's try a slightly more involved example.
74
+
75
+ We have been asked to write a robot which will start at a given X, Y coordinate,
76
+ and will move in for directions a given number of units. If no starting
77
+ coordinate is given, the robot will start at 0,0. When the robot is moved, a
78
+ two-element array should be returned with the x and y coordinates. Some
79
+ expectations you might write for this robot might be the following:
80
+
81
+ rob = Robot.new
82
+
83
+ rob.should_not_be_nil
84
+ rob.should_be_kind_of Robot
85
+ rob.x_coordinate.should_equal 0
86
+ rob.y_coordinate.should_equal 0
87
+ rob.location.should_equal [0,0]
88
+
89
+ rob.move_north(1).should_equal [0, 1]
90
+ rob.move_south(5).should_equal [0, -4]
91
+ rob.move_east(10).should_equal [10, -4]
92
+ rob.move_west(5).should_equal [5, -4]
93
+
94
+ The code example above isn't intended to demonstrate good design, but has been
95
+ created explicitly to demonstrate the use of the expectation methods.
96
+
97
+ Also note that these expectations would be written iteratively, but the purpose
98
+ of this document is to serve as an introduction to the RSpec framework, not to
99
+ Behaviour Driven Development itself.
100
+
101
+ As you can see, writing expectations can be rather verbose, even for a simple
102
+ project like the example above. For clarity, your expectations will be grouped
103
+ into specifications, which are described in the next section.
104
+
105
+ == Specifications
106
+
107
+ Your software will be specified by writing expectations, which were explained in
108
+ the previous section. Your expectations will be grouped into specifications for
109
+ clarity. A specification is simply a method that contains expectations. The name
110
+ of your specification will be used by the Spec Runner (see Running and
111
+ Reporting) to inform you of unmet expectations, so choose your names wisely.
112
+
113
+ Consider the robot example from the previous example, but divided into
114
+ specification methods:
115
+
116
+ def initialization_without_coordinates
117
+ rob = Robot.new
118
+ rob.x_coordinate.should_equal 0
119
+ rob.y_coordinate.should_equal 0
120
+ rob.location.should_equal [0,0]
121
+ end
122
+
123
+ def initialization_with_coordinates
124
+ rob = Robot.new(10, 15)
125
+ rob.x_coordinate.should_equal 10
126
+ rob.y_coordinate.should_equal 15
127
+ rob.location.should_equal [10, 15]
128
+ end
129
+
130
+ def north_movement
131
+ rob = Robot.new
132
+ rob.move_north(1).should_equal [0, 1]
133
+ end
134
+
135
+ def west_movement
136
+ rob = Robot.new(10, 5)
137
+ rob.move_west(15).should_equal [-5, 5]
138
+ end
139
+
140
+ By dividing expectations into specification methods, our specifications for the
141
+ behaviour of our software are far easier to read and clearly express the intent.
142
+ Even those who are unfamiliar with Ruby specifically (and perhaps even some who
143
+ are relatively unfamiliar with software development in general) can easily read
144
+ our specifications.
145
+
146
+ == Fixtures
147
+
148
+ As you can see, there is some duplicated code in the example from the last
149
+ section in the creation of the Robot objects. You will find that the
150
+ initialization of objects will often be duplicated when writing specifications.
151
+ RSpec provides you with a way of setting up this data ahead of time, by
152
+ providing two methods: setup and teardown.
153
+
154
+ The setup method is called before invoking each specification to allow you to
155
+ set up resources which are required for each specification, and the teardown
156
+ method is called after invoking each specification, to allow you to
157
+ appropriately deallocate or close resources wich were required for the
158
+ specifications.
159
+
160
+ The example in the next section include a demonstration of the usage of fixtures
161
+ in Contexts.
162
+
163
+ == Contexts
164
+
165
+ The specifications described in the Specifications example are absolutely
166
+ useless if they're not placed in a context. Because you will be writing a large
167
+ number of specifications for your software, you will want a way to divide them
168
+ into logical groups. Specification methods are grouped within subclasses of
169
+ Context. You can define as many contexts as you wish, and you are encouraged to
170
+ divide your software into many well-defined contexts.
171
+
172
+ The following Context is a complete specification for the movement of the robot,
173
+ and if it were run, would produce useful output.
174
+
175
+ require 'spec'
176
+ class RobotMovement < Spec::Context
177
+ def setup
178
+ @rob = Robot.new
179
+ @rob1 = Robot.new(10, 15)
180
+ end
181
+
182
+ def movement
183
+ @rob.move_north(1).should_equal [0, 1]
184
+ @rob1.move_west(15).should_equal [-5, 5]
185
+ end
186
+
187
+ def teardown
188
+ @rob.die
189
+ @rob1.die
190
+ end
191
+ end
192
+
193
+ === Specification Naming
194
+
195
+ RSpec does not require the use of a specific naming scheme for specifications.
196
+ When a context is run, all of the public methods which you define in the context
197
+ will be executed. The only exceptions are currently methods which are used
198
+ internally by RSpec. The forbidden names are initialize, mock, violated, and
199
+ run. Because of Ruby's dynamic nature, you will not see a warning if you
200
+ override any of these methods, and unexpected behaviour may ensue.
201
+
202
+ In addition to the four aforementioned forbidden specification method names,
203
+ methods named with a leading underscore will also not be run as specifications.
204
+ This allows you a way to define methods for your own use within the Context and
205
+ not have them run as specifications.
206
+
207
+ == Running and Reporting
208
+
209
+ There currently exists a command-line runner for RSpec, called 'spec'. If you
210
+ write specifications and pass them to the runner on the command line, your
211
+ specifications will run and tell you where you have errors. You are encouraged
212
+ to try out the command line runner, first with the provided examples, and then
213
+ by writing your own specifications.
214
+
215
+ As an example of the output, if you run the movie_spec.rb file from the RSpec
216
+ examples, you will get the following output:
217
+
218
+ $ spec movie_spec.rb
219
+ ....
220
+ Finished in 0.016 seconds.
221
+
222
+ 4 specifications, 4 expectations, 0 failures.
223
+
224
+ The spec runner counts the specification as it executes them by printing a
225
+ single dot (.) to the screen. It indicates a failure with an X. For every
226
+ failure, the specification runner will provide a backtrace indicating where the
227
+ failure occured. A failure is basically a raised exception. Either an exception
228
+ raised by the software you're specifying, by Ruby itself (such as SyntaxError or
229
+ RuntimeError), or it will be an unmet expectation (ExpectationNotMet).
230
+
231
+ For instance, if you expect "Space Balls" to be in OneMovieList which actually
232
+ includes "Star Wars", you will get the following error:
233
+
234
+ $ spec movie_spec.rb
235
+ X...
236
+
237
+ 1)
238
+ <#<MovieList:0x284c1e0 @movies={"Star Wars"=>#<Movie:0x284c180 @name="Star Wars"
239
+ >}>> should include <"Space Balls"> (Spec::Exceptions::ExpectationNotMetError)
240
+ ./movie_spec.rb:34:in `should_include_space_balls'
241
+ ../bin/spec:10
242
+
243
+ Finished in 0.016 seconds
244
+
245
+ 4 specifications, 4 expectations, 1 failures
246
+
247
+ This informs you that the MovieList object should include "Space Balls", but got
248
+ an ExpectationNotMet error. The backtrace also informs you that the unmet
249
+ expectation can be found in the file 'movie_spec.rb' on line 34, in the
250
+ `should_include_space_balls' method.
251
+
252
+ == Conclusion
253
+
254
+ This document was by no means intended to provide an exhaustive overview of
255
+ Behaviour Driven Development in general, or RSpec specifically. It is intended
256
+ as a tutorial to get you started with specifying the behaviour of your software
257
+ with RSpec. More information can be found in the API documentation of RSpec
258
+ itself. Further documentation on BDD, and RSpec is on the way.
259
+
@@ -1,5 +1,5 @@
1
1
  require 'spec'
2
- require 'craps'
2
+ require File.dirname(__FILE__) + '/craps'
3
3
 
4
4
  class CrapsSpecification < Spec::Context
5
5
 
@@ -94,7 +94,7 @@ class CrapsSpecification < Spec::Context
94
94
  end
95
95
 
96
96
  def _load_die(die, rolls)
97
- rolls.each {| each | die.__expects(:roll).once.with_no_args.returns(each) }
97
+ rolls.each { |roll| die.should_receive(:roll).once.with_no_args.and_return(roll) }
98
98
  end
99
99
 
100
100
  end
@@ -56,7 +56,7 @@ module Spec
56
56
  end
57
57
 
58
58
  def dump_backtrace(trace)
59
- lines = trace.reject {|line| line.include? "lib/spec"}
59
+ lines = trace.reject {|line| line.include? "lib/spec"}.reject {|line | line.include? "./spec:"}
60
60
  @output << lines.join("\n")
61
61
  @output << "\n\n"
62
62
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: rspec
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.7
7
- date: 2005-08-30 00:00:00 -04:00
6
+ version: 0.2.0
7
+ date: 2005-09-27
8
8
  summary: Behaviour Specification Framework for Ruby
9
9
  require_paths:
10
10
  - lib
@@ -27,8 +27,6 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
27
27
  version: 0.0.0
28
28
  version:
29
29
  platform: ruby
30
- signing_key:
31
- cert_chain:
32
30
  authors:
33
31
  - Steven Baker
34
32
  files:
@@ -37,6 +35,7 @@ files:
37
35
  - Rakefile.rb
38
36
  - README
39
37
  - TODO
38
+ - TUTORIAL
40
39
  - lib/spec.rb
41
40
  - lib/spec/collector.rb
42
41
  - lib/spec/context.rb
@@ -46,18 +45,12 @@ files:
46
45
  - lib/spec/text_runner.rb
47
46
  - test/context_fixtures_test.rb
48
47
  - test/context_run_test.rb
49
- - test/craps_collector_test.rb
50
48
  - test/error_reporting_test.rb
51
49
  - test/expectations_test.rb
52
50
  - test/get_classes.rb
53
51
  - test/mock_test.rb
54
- - test/movie_collector_test.rb
55
- - test/rspec_craps_and_movie_test.rb
56
- - test/rspec_craps_test.rb
57
- - test/rspec_movie_test.rb
58
52
  - test/spec_collection_test.rb
59
53
  - test/specification_identification_test.rb
60
- - test/test_unit_ext_spec.rb
61
54
  - test/text_runner_test.rb
62
55
  - examples/craps.rb
63
56
  - examples/craps_spec.rb
@@ -1,17 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'spec'
4
-
5
-
6
- class CrapsCollectorTest < Test::Unit::TestCase
7
-
8
- def setup
9
- require 'examples/craps_spec'
10
- end
11
-
12
- def test_should_collect_only_craps_specification
13
- assert_equal CrapsSpecification.specifications.length, Spec::Collector.collection.length
14
- end
15
-
16
- end
17
-
@@ -1,19 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'spec'
4
-
5
-
6
- class MovieCollectorTest < Test::Unit::TestCase
7
-
8
- def setup
9
- require 'examples/movie_spec'
10
- end
11
-
12
- def test_should_collect_only_movie_specs
13
- specifications = EmptyMovieList.specifications.length
14
- specifications += OneMovieList.specifications.length
15
- assert_equal specifications, Spec::Collector.collection.length
16
- end
17
-
18
- end
19
-
@@ -1,32 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'rspec'
4
- require 'get_classes'
5
-
6
- class RSpecCrapsAndMovieTest < Test::Unit::TestCase
7
-
8
- def setup
9
- @rspec = RSpec.new(["examples/craps_spec.rb", "examples/movie_spec.rb"])
10
- end
11
-
12
- def test_should_load_craps_and_movie_specs
13
- assert_equal true, get_classes.include?('CrapsSpecification')
14
- assert_equal true, get_classes.include?('EmptyMovieList')
15
- assert_equal true, get_classes.include?('OneMovieList')
16
- end
17
-
18
- def test_should_include_all_specifications
19
- specifications = CrapsSpecification.collection.length
20
- specifications += EmptyMovieList.collection.length
21
- specifications += OneMovieList.collection.length
22
- assert_equal specifications, Spec::Collector.collection.length
23
- end
24
-
25
- def test_should_run_all_specifications
26
- buffer = ""
27
- @rspec.run(Spec::TextRunner.new(buffer))
28
- assert_equal true, buffer.include?("16 specifications, 16 expectations, 0 failures")
29
- end
30
-
31
- end
32
-
@@ -1,35 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'spec'
4
-
5
- require 'rspec'
6
-
7
- require 'get_classes'
8
-
9
- class RSpecCrapsTest < Test::Unit::TestCase
10
-
11
- def setup
12
- @rspec = RSpec.new(["examples/craps_spec.rb"])
13
- end
14
-
15
- def test_should_load_craps_spec
16
- assert_equal true, get_classes.include?('CrapsSpecification')
17
- end
18
-
19
- def test_should_not_load_movie_specs
20
- assert_equal false, get_classes.include?('OneMovieList')
21
- assert_equal false, get_classes.include?('EmptyMovieList')
22
- end
23
-
24
- def test_should_include_craps_specifications
25
- assert_equal CrapsSpecification.collection.length, Spec::Collector.collection.length
26
- end
27
-
28
- def test_should_run_craps_specifications
29
- buffer = ""
30
- @rspec.run(Spec::TextRunner.new(buffer))
31
- assert_equal true, buffer.include?("12 specifications, 12 expectations, 0 failures")
32
- end
33
-
34
- end
35
-
@@ -1,33 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'rspec'
4
- require 'get_classes'
5
-
6
- class RSpecMovieTest < Test::Unit::TestCase
7
-
8
- def setup
9
- @rspec = RSpec.new(["examples/movie_spec.rb"])
10
- end
11
-
12
- def test_should_load_movie_spec
13
- assert_equal true, get_classes.include?('EmptyMovieList')
14
- assert_equal true, get_classes.include?('OneMovieList')
15
- end
16
-
17
- def test_should_not_load_craps_spec
18
- assert_equal false, get_classes.include?('CrapsSpecification')
19
- end
20
-
21
- def test_should_include_movie_specifications
22
- specifications = EmptyMovieList.collection.length + OneMovieList.collection.length
23
- assert_equal specifications, Spec::Collector.collection.length
24
- end
25
-
26
- def test_should_run_movie_specifications
27
- buffer = ""
28
- @rspec.run(Spec::TextRunner.new(buffer))
29
- assert_equal true, buffer.include?("4 specifications, 4 expectations, 0 failures")
30
- end
31
-
32
- end
33
-
@@ -1,9 +0,0 @@
1
- require 'spec'
2
-
3
- module Foo
4
- class BarSpec < Spec::Context
5
- def should_fail
6
- raise "ERRORRRR"
7
- end
8
- end
9
- end