rspec 0.2.0 → 0.3.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.
- data/CHANGES +9 -0
- data/README +16 -23
- data/{Rakefile.rb → Rakefile} +1 -1
- data/TUTORIAL +56 -56
- data/examples/add_specification_spec.rb +15 -0
- data/examples/dsl_spec.rb +8 -0
- data/lib/spec.rb +2 -0
- data/lib/spec/context.rb +10 -2
- data/lib/spec/dsl.rb +23 -0
- data/lib/spec/expectations.rb +46 -4
- data/lib/spec/gui_runner.rb +59 -0
- data/lib/spec/mock.rb +43 -16
- data/lib/spec/text_runner.rb +10 -10
- data/test/dsl_test.rb +48 -0
- data/test/expectations_test.rb +40 -0
- data/test/gui_runner_test.rb +162 -0
- data/test/mock_test.rb +66 -1
- data/test/specification_addition_test.rb +29 -0
- data/test/text_runner_test.rb +28 -3
- metadata +13 -5
    
        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.3.0
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            It's been a while since last release, lots of new stuff is available.  For instance:
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             * improvements to the runners
         | 
| 21 | 
            +
             * addition of should_raise expectation (thanks to Brian Takita)
         | 
| 22 | 
            +
             * some documentation improvements
         | 
| 23 | 
            +
             * RSpec usable as a DSL
         | 
| 24 | 
            +
             | 
| 16 25 | 
             
            == Version 0.2.0
         | 
| 17 26 |  | 
| 18 27 | 
             
            This release provides a tutorial for new users wishing to get started with
         | 
    
        data/README
    CHANGED
    
    | @@ -1,45 +1,38 @@ | |
| 1 1 | 
             
            = RSpec - Behaviour Specification Framework for Ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            RSpec is a behaviour specification framework for Ruby.  RSpec was created in
         | 
| 4 | 
            -
            response to Dave Astels' article _A New Look at Test Driven Development_ which
         | 
| 5 | 
            -
            can be read at: http://daveastels.com/index.php?p=5  RSpec is intended to
         | 
| 6 | 
            -
            provide the features discussed in Dave's article.
         | 
| 3 | 
            +
            RSpec is a behaviour specification framework for Ruby.  RSpec was created in response to Dave Astels' article _A New Look at Test Driven Development_ which can be read at: http://daveastels.com/index.php?p=5  RSpec is intended to provide the features discussed in Dave's article.
         | 
| 7 4 |  | 
| 8 | 
            -
            RSpec  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 5 | 
            +
            RSpec is primarily developed by Steven Baker <srbaker@pobox.com>, and was inspired by and contributed to by Dave Astels.  Special thanks also to Aslak Hellesoy for many significant contributions.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            RSpec's included mocking framework is based on SchMock by Ben Griffiths.  SchMock can be found at http://rubyforge.org/projects/schmock/.
         | 
| 11 8 |  | 
| 12 9 | 
             
            == Download/Installation
         | 
| 13 10 |  | 
| 14 11 | 
             
            === Using RubyGems
         | 
| 15 12 |  | 
| 16 | 
            -
              sudo gem install rspec
         | 
| 13 | 
            +
              $ sudo gem install rspec
         | 
| 17 14 |  | 
| 18 15 | 
             
            === Getting the latest sources
         | 
| 19 16 |  | 
| 20 | 
            -
            RSpec  | 
| 17 | 
            +
            RSpec was previously hosted under the Monotone distributed version control system.  Due to the increasing popularity of RSpec, and the fact that a large part of the world hasn't yet discovered how wonderful Monotone is, we have succumbed to peer pressure and moved the repository to Subversion.
         | 
| 21 18 |  | 
| 22 | 
            -
             | 
| 23 | 
            -
                * monotone --db=database pull goliath.fundynet.ca org.rubyforge.rspec
         | 
| 24 | 
            -
                * monotone --db=database --branch=org.rubyforge.rspec checkout RSpec
         | 
| 19 | 
            +
            RSpec's repository is located at svn://svn.behaviourdriven.org/rspec
         | 
| 25 20 |  | 
| 26 | 
            -
             | 
| 21 | 
            +
            == Creating a Gem
         | 
| 27 22 |  | 
| 28 | 
            -
             | 
| 23 | 
            +
            If you have checked out the sources from version control, you can create a Gem from the checked out version with the 'gem' rake task, like so:
         | 
| 29 24 |  | 
| 30 | 
            -
             | 
| 25 | 
            +
              $ rake gem
         | 
| 31 26 |  | 
| 32 | 
            -
             | 
| 27 | 
            +
            This will create a gem in the pkg/ subdirectory.  To install the created gem, simply run 'gem install' as root (preferably using sudo(1)):
         | 
| 33 28 |  | 
| 34 | 
            -
             | 
| 29 | 
            +
              $ sudo gem install pkg/rspec_x.y.z.gem
         | 
| 35 30 |  | 
| 36 | 
            -
             | 
| 31 | 
            +
            Please visit the RSpec web site periodically, it will be updated with more information as it is made available including documentation, mailing lists, bug tracking, and more. Special thanks to RubyForge for hosting the project site.
         | 
| 37 32 |  | 
| 38 | 
            -
             | 
| 33 | 
            +
            == Usage
         | 
| 39 34 |  | 
| 40 | 
            -
             | 
| 35 | 
            +
            This will also install a new executable for you, 'spec'. Now you can
         | 
| 41 36 |  | 
| 37 | 
            +
              spec movie_spec.rb
         | 
| 42 38 | 
             
              spec *_spec.rb
         | 
| 43 | 
            -
             | 
| 44 | 
            -
            This is the coolest part.  Dance harder.  Now drink.
         | 
| 45 | 
            -
             | 
    
        data/{Rakefile.rb → Rakefile}
    RENAMED
    
    
    
        data/TUTORIAL
    CHANGED
    
    | @@ -40,12 +40,13 @@ ready for use! | |
| 40 40 | 
             
            == Expectations
         | 
| 41 41 |  | 
| 42 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 | 
| 44 | 
            -
            specifications is simply a collection of expectations about how your code | 
| 45 | 
            -
            behave.
         | 
| 43 | 
            +
            expectation tells RSpec what the expected result of a piece code is. Your set
         | 
| 44 | 
            +
            of specifications is simply a collection of expectations about how your code
         | 
| 45 | 
            +
            should behave.
         | 
| 46 46 |  | 
| 47 | 
            -
            In RSpec, the expectations are methods that are available on every object in | 
| 48 | 
            -
            system. If I want to set an expectation that the value of 1 is 1, I would | 
| 47 | 
            +
            In RSpec, the expectations are methods that are available on every object in
         | 
| 48 | 
            +
            the system. If I want to set an expectation that the value of 1 is 1, I would
         | 
| 49 | 
            +
            write:
         | 
| 49 50 |  | 
| 50 51 | 
             
                1.should_equal 1
         | 
| 51 52 |  | 
| @@ -63,8 +64,8 @@ not equal 2, write the following: | |
| 63 64 |  | 
| 64 65 | 
             
            These examples are extremely simple, but they accurately convey the simplicity
         | 
| 65 66 | 
             
            with which expectations can be written. When specifying your software, you are
         | 
| 66 | 
            -
            simply writing expectations that specify how your software will behave. The | 
| 67 | 
            -
            of the constructs in RSpec exist entirely to help you organize your
         | 
| 67 | 
            +
            simply writing expectations that specify how your software will behave. The
         | 
| 68 | 
            +
            rest of the constructs in RSpec exist entirely to help you organize your
         | 
| 68 69 | 
             
            expectations, and to provide accurate and helpful reporting when these
         | 
| 69 70 | 
             
            expectations are not met.
         | 
| 70 71 |  | 
| @@ -72,11 +73,11 @@ Eventually, writing expectations for addition and subtraction of numbers will | |
| 72 73 | 
             
            get boring. When that happens, you can start writing expectations for your own
         | 
| 73 74 | 
             
            code. Let's try a slightly more involved example.
         | 
| 74 75 |  | 
| 75 | 
            -
            We have been asked to write a robot which will start at a given X, Y | 
| 76 | 
            -
            and will move in for directions a given number of units. If no | 
| 77 | 
            -
            coordinate is given, the robot will start at 0,0. When the robot is | 
| 78 | 
            -
            two-element array should be returned with the x and y coordinates. | 
| 79 | 
            -
            expectations you might write for this robot might be the following:
         | 
| 76 | 
            +
            We have been asked to write a robot which will start at a given X, Y
         | 
| 77 | 
            +
            coordinate, and will move in for directions a given number of units. If no
         | 
| 78 | 
            +
            starting coordinate is given, the robot will start at 0,0. When the robot is
         | 
| 79 | 
            +
            moved, a two-element array should be returned with the x and y coordinates.
         | 
| 80 | 
            +
            Some expectations you might write for this robot might be the following:
         | 
| 80 81 |  | 
| 81 82 | 
             
                rob = Robot.new
         | 
| 82 83 |  | 
| @@ -94,9 +95,9 @@ expectations you might write for this robot might be the following: | |
| 94 95 | 
             
            The code example above isn't intended to demonstrate good design, but has been
         | 
| 95 96 | 
             
            created explicitly to demonstrate the use of the expectation methods.
         | 
| 96 97 |  | 
| 97 | 
            -
            Also note that these expectations would be written iteratively, but the | 
| 98 | 
            -
            of this document is to serve as an introduction to the RSpec | 
| 99 | 
            -
            Behaviour Driven Development itself.
         | 
| 98 | 
            +
            Also note that these expectations would be written iteratively, but the
         | 
| 99 | 
            +
            purpose of this document is to serve as an introduction to the RSpec
         | 
| 100 | 
            +
            framework, not to Behaviour Driven Development itself.
         | 
| 100 101 |  | 
| 101 102 | 
             
            As you can see, writing expectations can be rather verbose, even for a simple
         | 
| 102 103 | 
             
            project like the example above. For clarity, your expectations will be grouped
         | 
| @@ -104,11 +105,12 @@ into specifications, which are described in the next section. | |
| 104 105 |  | 
| 105 106 | 
             
            == Specifications
         | 
| 106 107 |  | 
| 107 | 
            -
            Your software will be specified by writing expectations, which were explained | 
| 108 | 
            -
            the previous section. Your expectations will be grouped into specifications | 
| 109 | 
            -
            clarity. A specification is simply a method that contains expectations. | 
| 110 | 
            -
            of your specification will be used by the Spec Runner (see Running | 
| 111 | 
            -
            Reporting) to inform you of unmet expectations, so choose your names | 
| 108 | 
            +
            Your software will be specified by writing expectations, which were explained
         | 
| 109 | 
            +
            in the previous section. Your expectations will be grouped into specifications
         | 
| 110 | 
            +
            for clarity. A specification is simply a method that contains expectations.
         | 
| 111 | 
            +
            The name of your specification will be used by the Spec Runner (see Running
         | 
| 112 | 
            +
            and Reporting) to inform you of unmet expectations, so choose your names
         | 
| 113 | 
            +
            wisely.
         | 
| 112 114 |  | 
| 113 115 | 
             
            Consider the robot example from the previous example, but divided into
         | 
| 114 116 | 
             
            specification methods:
         | 
| @@ -137,40 +139,37 @@ specification methods: | |
| 137 139 | 
             
                  rob.move_west(15).should_equal [-5, 5]
         | 
| 138 140 | 
             
                end
         | 
| 139 141 |  | 
| 140 | 
            -
            By dividing expectations into specification methods, our specifications for | 
| 141 | 
            -
            behaviour of our software are far easier to read and clearly express the | 
| 142 | 
            -
            Even those who are unfamiliar with Ruby specifically (and perhaps even | 
| 143 | 
            -
            are relatively unfamiliar with software development in general) can | 
| 144 | 
            -
            our specifications.
         | 
| 142 | 
            +
            By dividing expectations into specification methods, our specifications for
         | 
| 143 | 
            +
            the behaviour of our software are far easier to read and clearly express the
         | 
| 144 | 
            +
            intent. Even those who are unfamiliar with Ruby specifically (and perhaps even
         | 
| 145 | 
            +
            some who are relatively unfamiliar with software development in general) can
         | 
| 146 | 
            +
            easily read our specifications.
         | 
| 145 147 |  | 
| 146 | 
            -
            ==  | 
| 148 | 
            +
            == Contexts
         | 
| 147 149 |  | 
| 148 150 | 
             
            As you can see, there is some duplicated code in the example from the last
         | 
| 149 151 | 
             
            section in the creation of the Robot objects. You will find that the
         | 
| 150 | 
            -
            initialization of objects will often be duplicated when writing | 
| 152 | 
            +
            initialization of objects will often be duplicated when writing
         | 
| 153 | 
            +
            specifications.
         | 
| 154 | 
            +
             | 
| 151 155 | 
             
            RSpec provides you with a way of setting up this data ahead of time, by
         | 
| 152 156 | 
             
            providing two methods: setup and teardown.
         | 
| 153 157 |  | 
| 154 158 | 
             
            The setup method is called before invoking each specification to allow you to
         | 
| 155 159 | 
             
            set up resources which are required for each specification, and the teardown
         | 
| 156 160 | 
             
            method is called after invoking each specification, to allow you to
         | 
| 157 | 
            -
            appropriately deallocate or close resources  | 
| 161 | 
            +
            appropriately deallocate or close resources which were required for the
         | 
| 158 162 | 
             
            specifications.
         | 
| 159 163 |  | 
| 160 | 
            -
            The example in the next section include a demonstration of the usage of fixtures
         | 
| 161 | 
            -
            in Contexts.
         | 
| 162 | 
            -
             | 
| 163 | 
            -
            == Contexts
         | 
| 164 | 
            -
             | 
| 165 164 | 
             
            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 | 
| 167 | 
            -
            number of specifications for your software, you will want a way to | 
| 168 | 
            -
            into logical groups. Specification methods are grouped within | 
| 169 | 
            -
            Context. You can define as many contexts as you wish, and you | 
| 170 | 
            -
            divide your software into many well-defined contexts.
         | 
| 165 | 
            +
            useless if they're not placed in a context. Because you will be writing a
         | 
| 166 | 
            +
            large number of specifications for your software, you will want a way to
         | 
| 167 | 
            +
            divide them into logical groups. Specification methods are grouped within
         | 
| 168 | 
            +
            subclasses of Context. You can define as many contexts as you wish, and you
         | 
| 169 | 
            +
            are encouraged to divide your software into many well-defined contexts.
         | 
| 171 170 |  | 
| 172 | 
            -
            The following Context is a complete specification for the movement of the | 
| 173 | 
            -
            and if it were run, would produce useful output.
         | 
| 171 | 
            +
            The following Context is a complete specification for the movement of the
         | 
| 172 | 
            +
            robot, and if it were run, would produce useful output.
         | 
| 174 173 |  | 
| 175 174 | 
             
                require 'spec'
         | 
| 176 175 | 
             
                class RobotMovement < Spec::Context
         | 
| @@ -193,16 +192,16 @@ and if it were run, would produce useful output. | |
| 193 192 | 
             
            === Specification Naming
         | 
| 194 193 |  | 
| 195 194 | 
             
            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 | 
| 197 | 
            -
            will be executed. The only exceptions are currently methods which are | 
| 198 | 
            -
            internally by RSpec. The forbidden names are initialize, mock, violated, | 
| 199 | 
            -
            run. Because of Ruby's dynamic nature, you will not see a warning if you
         | 
| 195 | 
            +
            When a context is run, all of the public methods which you define in the
         | 
| 196 | 
            +
            context will be executed. The only exceptions are currently methods which are
         | 
| 197 | 
            +
            used internally by RSpec. The forbidden names are initialize, mock, violated,
         | 
| 198 | 
            +
            and run. Because of Ruby's dynamic nature, you will not see a warning if you
         | 
| 200 199 | 
             
            override any of these methods, and unexpected behaviour may ensue.
         | 
| 201 200 |  | 
| 202 201 | 
             
            In addition to the four aforementioned forbidden specification method names,
         | 
| 203 | 
            -
            methods named with a leading underscore will also not be run as | 
| 204 | 
            -
            This allows you a way to define methods for your own use | 
| 205 | 
            -
            not have them run as specifications.
         | 
| 202 | 
            +
            methods named with a leading underscore will also not be run as
         | 
| 203 | 
            +
            specifications. This allows you a way to define methods for your own use
         | 
| 204 | 
            +
            within the Context and not have them run as specifications.
         | 
| 206 205 |  | 
| 207 206 | 
             
            == Running and Reporting
         | 
| 208 207 |  | 
| @@ -223,10 +222,11 @@ examples, you will get the following output: | |
| 223 222 |  | 
| 224 223 | 
             
            The spec runner counts the specification as it executes them by printing a
         | 
| 225 224 | 
             
            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 | 
| 227 | 
            -
            failure  | 
| 228 | 
            -
            raised by the software you're specifying, by Ruby itself (such as | 
| 229 | 
            -
            RuntimeError), or it will be an unmet expectation | 
| 225 | 
            +
            failure, the specification runner will provide a backtrace indicating where
         | 
| 226 | 
            +
            the failure occurred. A failure is basically a raised exception. Either an
         | 
| 227 | 
            +
            exception raised by the software you're specifying, by Ruby itself (such as
         | 
| 228 | 
            +
            SyntaxError or RuntimeError), or it will be an unmet expectation
         | 
| 229 | 
            +
            (ExpectationNotMet).
         | 
| 230 230 |  | 
| 231 231 | 
             
            For instance, if you expect "Space Balls" to be in OneMovieList which actually
         | 
| 232 232 | 
             
            includes "Star Wars", you will get the following error:
         | 
| @@ -244,8 +244,8 @@ includes "Star Wars", you will get the following error: | |
| 244 244 |  | 
| 245 245 | 
             
                4 specifications, 4 expectations, 1 failures
         | 
| 246 246 |  | 
| 247 | 
            -
            This informs you that the MovieList object should include "Space Balls", but | 
| 248 | 
            -
            an ExpectationNotMet error. The backtrace also informs you that the unmet
         | 
| 247 | 
            +
            This informs you that the MovieList object should include "Space Balls", but
         | 
| 248 | 
            +
            got an ExpectationNotMet error. The backtrace also informs you that the unmet
         | 
| 249 249 | 
             
            expectation can be found in the file 'movie_spec.rb' on line 34, in the
         | 
| 250 250 | 
             
            `should_include_space_balls' method.
         | 
| 251 251 |  | 
| @@ -253,7 +253,7 @@ expectation can be found in the file 'movie_spec.rb' on line 34, in the | |
| 253 253 |  | 
| 254 254 | 
             
            This document was by no means intended to provide an exhaustive overview of
         | 
| 255 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 | 
| 257 | 
            -
            with RSpec. More information can be found in the API documentation of | 
| 258 | 
            -
            itself. Further documentation on BDD, and RSpec is on the way.
         | 
| 256 | 
            +
            as a tutorial to get you started with specifying the behaviour of your
         | 
| 257 | 
            +
            software with RSpec. More information can be found in the API documentation of
         | 
| 258 | 
            +
            RSpec itself. Further documentation on BDD, and RSpec is on the way.
         | 
| 259 259 |  | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            require 'spec'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class AddSpecification < Spec::Context
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def a_passing_spec
         | 
| 6 | 
            +
                true.should_equal true
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
              
         | 
| 9 | 
            +
              def a_failing_spec
         | 
| 10 | 
            +
                true.should_equal false
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
              
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            AddSpecification.add_specification('another_failing_spec') { false.should_equal true }
         | 
    
        data/lib/spec.rb
    CHANGED
    
    
    
        data/lib/spec/context.rb
    CHANGED
    
    | @@ -50,13 +50,21 @@ module Spec | |
| 50 50 | 
             
                  rescue Exception
         | 
| 51 51 | 
             
                    result_listener.failure(@specification, $!)
         | 
| 52 52 | 
             
                  ensure
         | 
| 53 | 
            -
                     | 
| 54 | 
            -
             | 
| 53 | 
            +
                    begin
         | 
| 54 | 
            +
                      teardown
         | 
| 55 | 
            +
                      verify_mocks
         | 
| 56 | 
            +
                    rescue Exception
         | 
| 57 | 
            +
                      result_listener.failure(@specification, $!)
         | 
| 58 | 
            +
                    end
         | 
| 55 59 | 
             
                  end
         | 
| 56 60 |  | 
| 57 61 | 
             
                  return result
         | 
| 58 62 | 
             
                end
         | 
| 59 63 |  | 
| 64 | 
            +
                def self.add_specification(name, &block)
         | 
| 65 | 
            +
                  self.send(:define_method, name.to_sym, Proc.new { || block.call })
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 60 68 | 
             
              private
         | 
| 61 69 |  | 
| 62 70 | 
             
                def self.my_methods
         | 
    
        data/lib/spec/dsl.rb
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'spec'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module DSLExtensions
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def context(name)
         | 
| 6 | 
            +
                eval "$#{name} = Class.new(Spec::Context)"
         | 
| 7 | 
            +
                $current_context = eval "$#{name}"
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def specification(name, &block)
         | 
| 11 | 
            +
                $default_context ||= Class.new(Spec::Context)
         | 
| 12 | 
            +
                $current_context = $default_context if $current_context.nil?
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                $current_context.add_specification(name.to_sym, &block)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            class Object
         | 
| 20 | 
            +
              include DSLExtensions
         | 
| 21 | 
            +
            end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            alias example specification if ENV['USER'] == 'marick'
         | 
    
        data/lib/spec/expectations.rb
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            module Spec
         | 
| 2 | 
            -
              module  | 
| 3 | 
            -
             | 
| 2 | 
            +
              module ExpectationHelperMethods
         | 
| 4 3 | 
             
                def should(message=nil)
         | 
| 5 4 | 
             
                  message ||= "Expectation not met."
         | 
| 6 5 | 
             
                  if (! yield)
         | 
| @@ -11,6 +10,10 @@ module Spec | |
| 11 10 | 
             
                def default_message(expectation, expected)
         | 
| 12 11 | 
             
                  "<#{self.inspect}:#{self.class}>\n#{expectation}:\n<#{expected.inspect}:#{expected.class}>"
         | 
| 13 12 | 
             
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
              
         | 
| 15 | 
            +
              module ObjectExpectations
         | 
| 16 | 
            +
                include ExpectationHelperMethods
         | 
| 14 17 |  | 
| 15 18 | 
             
                def should_equal(expected, message=nil)
         | 
| 16 19 | 
             
                  message ||= default_message("should be equal to", expected)
         | 
| @@ -81,11 +84,50 @@ module Spec | |
| 81 84 | 
             
                  message ||= "<#{self}> should be false"
         | 
| 82 85 | 
             
                  should(message) { not self }
         | 
| 83 86 | 
             
                end
         | 
| 87 | 
            +
                
         | 
| 84 88 | 
             
              end
         | 
| 85 | 
            -
             | 
| 89 | 
            +
              
         | 
| 90 | 
            +
              
         | 
| 91 | 
            +
              module ProcExpectations
         | 
| 92 | 
            +
                include ExpectationHelperMethods
         | 
| 93 | 
            +
                
         | 
| 94 | 
            +
                def should_raise(exception=Exception, message=nil)
         | 
| 95 | 
            +
                  message ||= default_message("should raise", exception.class.to_s)
         | 
| 96 | 
            +
                  should(message) do
         | 
| 97 | 
            +
                    begin
         | 
| 98 | 
            +
                      self.call
         | 
| 99 | 
            +
                      false
         | 
| 100 | 
            +
                    rescue exception
         | 
| 101 | 
            +
                      true
         | 
| 102 | 
            +
                    rescue
         | 
| 103 | 
            +
                      false
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
                
         | 
| 108 | 
            +
                def should_not_raise(exception=Exception, message=nil)
         | 
| 109 | 
            +
                  message ||= default_message("should not raise", exception.class.to_s)
         | 
| 110 | 
            +
                  should(message) do
         | 
| 111 | 
            +
                    begin
         | 
| 112 | 
            +
                      self.call
         | 
| 113 | 
            +
                      true
         | 
| 114 | 
            +
                    rescue exception
         | 
| 115 | 
            +
                      false
         | 
| 116 | 
            +
                    rescue
         | 
| 117 | 
            +
                      true
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
              
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
              
         | 
| 86 124 | 
             
            end
         | 
| 87 125 |  | 
| 88 126 |  | 
| 89 127 | 
             
            class Object
         | 
| 90 | 
            -
              include Spec:: | 
| 128 | 
            +
              include Spec::ObjectExpectations
         | 
| 129 | 
            +
            end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            class Proc
         | 
| 132 | 
            +
              include Spec::ProcExpectations
         | 
| 91 133 | 
             
            end
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            require 'socket' 
         | 
| 2 | 
            +
            @socket
         | 
| 3 | 
            +
            module Spec
         | 
| 4 | 
            +
              class GuiRunner
         | 
| 5 | 
            +
             
         | 
| 6 | 
            +
                def initialize(port)
         | 
| 7 | 
            +
                  @failures = Array.new
         | 
| 8 | 
            +
                  @specification_count = 0
         | 
| 9 | 
            +
                  @failure_count = 0
         | 
| 10 | 
            +
                  @failed = false
         | 
| 11 | 
            +
                  @socket = TCPSocket.new("127.0.0.1", port)
         | 
| 12 | 
            +
            			@socket << "connected\n"
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def run(context_or_collection = Spec::Collector)
         | 
| 16 | 
            +
            			specs = context_or_collection.collection
         | 
| 17 | 
            +
                  start_run specs.size
         | 
| 18 | 
            +
                  specs.each {|spec| spec.run(self)}
         | 
| 19 | 
            +
                  end_run
         | 
| 20 | 
            +
            			@socket.shutdown
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def spec(spec)
         | 
| 24 | 
            +
                  @failed = false
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
                def pass(spec)
         | 
| 28 | 
            +
                  @socket << "passed\n"
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def failure(spec, exception)
         | 
| 32 | 
            +
            			return if @failed
         | 
| 33 | 
            +
                  @socket << "failed\n"
         | 
| 34 | 
            +
                  @failed = true
         | 
| 35 | 
            +
                  dump_failure(exception)
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              
         | 
| 38 | 
            +
                def start_run(number_of_specs)
         | 
| 39 | 
            +
                  @socket << "start #{number_of_specs.to_i}\n"
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              
         | 
| 42 | 
            +
                def end_run
         | 
| 43 | 
            +
                  @socket << "end\n"
         | 
| 44 | 
            +
                end    
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def dump_failure(exception)
         | 
| 47 | 
            +
               		@socket << "#{exception.message} (#{exception.class.name})\n"
         | 
| 48 | 
            +
                  dump_backtrace(exception.backtrace)
         | 
| 49 | 
            +
            			@socket << "!\n"
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def dump_backtrace(trace)
         | 
| 53 | 
            +
                	lines = trace.reject {|line| line.include? "lib/spec"}.reject {|line | line.include? "./spec:"}
         | 
| 54 | 
            +
                  @socket << lines.join("\n")
         | 
| 55 | 
            +
            			@socket << "\n"
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
                
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
    
        data/lib/spec/mock.rb
    CHANGED
    
    | @@ -39,7 +39,7 @@ class Mock | |
| 39 39 | 
             
                    # act as null object if method is missing and we ignore them. return value too!
         | 
| 40 40 | 
             
                    @options[:null_object] ? self : super(sym, *args, &block)
         | 
| 41 41 | 
             
                  rescue NoMethodError
         | 
| 42 | 
            -
                    raise Spec::Exceptions::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}'"
         | 
| 42 | 
            +
                    raise Spec::Exceptions::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with " + (args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", "))
         | 
| 43 43 | 
             
                  end
         | 
| 44 44 | 
             
                end
         | 
| 45 45 | 
             
              end
         | 
| @@ -47,7 +47,7 @@ class Mock | |
| 47 47 | 
             
            private
         | 
| 48 48 |  | 
| 49 49 | 
             
              def find_matching_expectation(sym, *args)
         | 
| 50 | 
            -
                expectation = @expectations.find {|expectation| expectation.matches(sym,  | 
| 50 | 
            +
                expectation = @expectations.find {|expectation| expectation.matches(sym, args)}
         | 
| 51 51 | 
             
                expectation
         | 
| 52 52 | 
             
              end
         | 
| 53 53 |  | 
| @@ -65,28 +65,38 @@ class MessageExpectation | |
| 65 65 | 
             
                @received_count = 0
         | 
| 66 66 | 
             
                @expected_received_count = 1
         | 
| 67 67 | 
             
                @expected_params = nil
         | 
| 68 | 
            +
                @consecutive = false
         | 
| 68 69 | 
             
              end
         | 
| 69 70 |  | 
| 70 | 
            -
              def matches(sym,  | 
| 71 | 
            -
                @sym == sym
         | 
| 71 | 
            +
              def matches(sym, args)
         | 
| 72 | 
            +
                @sym == sym and (@expected_params.nil? or @expected_params == args)
         | 
| 72 73 | 
             
              end
         | 
| 73 74 |  | 
| 74 75 | 
             
              # This method is called at the end of a spec, after teardown.
         | 
| 75 76 | 
             
              def verify_messages_received
         | 
| 76 77 | 
             
                # TODO: this doesn't provide good enough error messages to fix the error.
         | 
| 77 78 | 
             
                # Error msg should tell exactly what went wrong. (AH).
         | 
| 78 | 
            -
                 | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
                   | 
| 86 | 
            -
             | 
| 79 | 
            +
                
         | 
| 80 | 
            +
                return if @expected_received_count == -2
         | 
| 81 | 
            +
                return if (@expected_received_count == -1) && (@received_count > 0)
         | 
| 82 | 
            +
                return if @expected_received_count == @received_count
         | 
| 83 | 
            +
                
         | 
| 84 | 
            +
                expected_signature = nil
         | 
| 85 | 
            +
                if @expected_params.nil?
         | 
| 86 | 
            +
                  expected_signature = @sym
         | 
| 87 | 
            +
                else
         | 
| 88 | 
            +
                  params = @expected_params.collect{|param| "<#{param}:#{param.class.name}>"}.join(", ")
         | 
| 89 | 
            +
                  expected_signature = "#{@sym}(#{params})"
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
                
         | 
| 92 | 
            +
                count_message = "{@expected_received_count} times"
         | 
| 93 | 
            +
                count_message = "at least once" if (@expected_received_count == -1)
         | 
| 94 | 
            +
                count_message = "never" if (@expected_received_count == 0)
         | 
| 95 | 
            +
                count_message = "once" if (@expected_received_count == 1)
         | 
| 96 | 
            +
                count_message = "twice" if (@expected_received_count == 2)
         | 
| 87 97 |  | 
| 98 | 
            +
                message = "#{@expected_from}: Mock '#{@mock_name}' expected #{expected_signature} #{count_message}, but received it #{@received_count} times"
         | 
| 88 99 | 
             
                  raise Spec::Exceptions::MockExpectationError, message
         | 
| 89 | 
            -
                end
         | 
| 90 100 | 
             
              end
         | 
| 91 101 |  | 
| 92 102 | 
             
              # This method is called when a method is invoked on a mock
         | 
| @@ -103,11 +113,15 @@ class MessageExpectation | |
| 103 113 |  | 
| 104 114 | 
             
                unless @expected_params.nil? or @expected_params == args
         | 
| 105 115 | 
             
                  raise Spec::Exceptions::MockExpectationError,
         | 
| 106 | 
            -
                    "#{@sym}: Parameter mismatch: Expected <#{@expected_params}>, got <#{ | 
| 116 | 
            +
                    "#{@sym}: Parameter mismatch: Expected <#{@expected_params}>, got <#{args}>" 
         | 
| 107 117 | 
             
                end
         | 
| 108 118 | 
             
                args << block unless block.nil?
         | 
| 109 119 | 
             
                @received_count += 1
         | 
| 110 | 
            -
                @block.call(*args)
         | 
| 120 | 
            +
                value = @block.call(*args)
         | 
| 121 | 
            +
                
         | 
| 122 | 
            +
                return value unless @consecutive
         | 
| 123 | 
            +
                
         | 
| 124 | 
            +
                value[[@received_count, value.size].min - 1]
         | 
| 111 125 | 
             
              end
         | 
| 112 126 |  | 
| 113 127 | 
             
              def with(*args)
         | 
| @@ -126,8 +140,14 @@ class MessageExpectation | |
| 126 140 | 
             
              end
         | 
| 127 141 |  | 
| 128 142 | 
             
              def at_least_once
         | 
| 143 | 
            +
                @expected_received_count = -1
         | 
| 129 144 | 
             
                self
         | 
| 130 145 | 
             
              end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
               def any_number_of_times
         | 
| 148 | 
            +
                 @expected_received_count = -2
         | 
| 149 | 
            +
                 self
         | 
| 150 | 
            +
               end
         | 
| 131 151 |  | 
| 132 152 | 
             
              def never
         | 
| 133 153 | 
             
                @expected_received_count = 0
         | 
| @@ -147,9 +167,16 @@ class MessageExpectation | |
| 147 167 | 
             
              def returns(value=nil,&block)
         | 
| 148 168 | 
             
                @block = block_given? ? block : proc { value }
         | 
| 149 169 | 
             
              end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
              def returns_consecutively(value=[nil],&block)
         | 
| 172 | 
            +
                @consecutive = true
         | 
| 173 | 
            +
                @block = block_given? ? block : proc { value }
         | 
| 174 | 
            +
              end
         | 
| 175 | 
            +
              
         | 
| 150 176 | 
             
              # this reads better in English IMHO: (AH)
         | 
| 151 177 | 
             
              # uri_specs.should_receive(:[]).with(:overview).and_return("http://some.host/look_here/\#{path}")
         | 
| 152 178 | 
             
              alias :and_return :returns
         | 
| 179 | 
            +
              alias :and_return_consecutively :returns_consecutively
         | 
| 153 180 |  | 
| 154 181 | 
             
            end
         | 
| 155 182 |  | 
    
        data/lib/spec/text_runner.rb
    CHANGED
    
    | @@ -4,8 +4,8 @@ module Spec | |
| 4 4 | 
             
                def initialize(appendable = $stdout)
         | 
| 5 5 | 
             
                  @failures = Array.new
         | 
| 6 6 | 
             
                  @specification_count = 0
         | 
| 7 | 
            -
                  @expectation_count = 0
         | 
| 8 7 | 
             
                  @failure_count = 0
         | 
| 8 | 
            +
                  @failed = false
         | 
| 9 9 | 
             
                  @output = appendable
         | 
| 10 10 | 
             
                end
         | 
| 11 11 |  | 
| @@ -14,22 +14,23 @@ module Spec | |
| 14 14 | 
             
                  context_or_collection.collection.each {|context| context.run(self)}
         | 
| 15 15 | 
             
                  end_run
         | 
| 16 16 | 
             
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def spec(spec)
         | 
| 19 | 
            +
                  @specification_count += 1
         | 
| 20 | 
            +
                  @failed = false
         | 
| 21 | 
            +
                end
         | 
| 17 22 |  | 
| 18 23 | 
             
                def pass(spec)
         | 
| 19 24 | 
             
                  @output << "."
         | 
| 20 | 
            -
                  @expectation_count += 1
         | 
| 21 25 | 
             
                end
         | 
| 22 26 |  | 
| 23 27 | 
             
                def failure(spec, exception)
         | 
| 24 | 
            -
                  @output << "X"
         | 
| 25 | 
            -
                  @ | 
| 28 | 
            +
                  @output << "X" unless @failed
         | 
| 29 | 
            +
                  @failure_count += 1 unless @failed
         | 
| 30 | 
            +
                  @failed = true
         | 
| 26 31 | 
             
                  @failures << exception
         | 
| 27 32 | 
             
                end
         | 
| 28 33 |  | 
| 29 | 
            -
                def spec(spec)
         | 
| 30 | 
            -
                  @specification_count += 1
         | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
              
         | 
| 33 34 | 
             
                def start_run
         | 
| 34 35 | 
             
                  @output << "\n"
         | 
| 35 36 | 
             
                  @start_time = Time.new
         | 
| @@ -67,8 +68,7 @@ module Spec | |
| 67 68 |  | 
| 68 69 | 
             
                def dump_counts
         | 
| 69 70 | 
             
                  @output << "\n" << @specification_count.to_s << " specifications, "
         | 
| 70 | 
            -
                  @output << @ | 
| 71 | 
            -
                  @output << @failures.length.to_s << " failures\n"
         | 
| 71 | 
            +
                  @output << @failure_count.to_s << " failures\n"
         | 
| 72 72 | 
             
                end
         | 
| 73 73 |  | 
| 74 74 | 
             
              end
         | 
    
        data/test/dsl_test.rb
    ADDED
    
    | @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'test/unit'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'spec'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class DSLTest < Test::Unit::TestCase
         | 
| 6 | 
            +
              
         | 
| 7 | 
            +
              def setup
         | 
| 8 | 
            +
                $default_context = nil
         | 
| 9 | 
            +
                $current_context = nil
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              def test_should_have_specification_method_defined
         | 
| 13 | 
            +
                assert_equal true, Object.public_method_defined?(:specification)
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
              
         | 
| 16 | 
            +
              def test_should_add_specification_to_default_context
         | 
| 17 | 
            +
                specification('foobar') { true.should_equal true }
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                assert_equal true, $default_context.specifications.include?('foobar')
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              def test_should_create_new_context
         | 
| 23 | 
            +
                context 'my_context'
         | 
| 24 | 
            +
                
         | 
| 25 | 
            +
                assert_equal Spec::Context, $my_context.superclass
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              
         | 
| 28 | 
            +
              def test_should_set_current_context_to_new_context
         | 
| 29 | 
            +
                context 'bar'
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
                assert_equal $current_context, $bar
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
              
         | 
| 34 | 
            +
              def test_should_add_bar_specification_to_foo_context
         | 
| 35 | 
            +
                context 'foo'
         | 
| 36 | 
            +
                specification('bar') { true.should_equal true }
         | 
| 37 | 
            +
                
         | 
| 38 | 
            +
                assert_equal true, $foo.specifications.include?('bar')
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              def test_should_add_bar_specification_to_current_context
         | 
| 42 | 
            +
                context 'foo'
         | 
| 43 | 
            +
                specification('bar') { true.should_equal true }
         | 
| 44 | 
            +
                
         | 
| 45 | 
            +
                assert_equal true, $current_context.specifications.include?('bar')
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            end
         | 
    
        data/test/expectations_test.rb
    CHANGED
    
    | @@ -423,5 +423,45 @@ class ExpectationsTest < Test::Unit::TestCase | |
| 423 423 | 
             
                  self.should_be_false
         | 
| 424 424 | 
             
                end
         | 
| 425 425 | 
             
              end
         | 
| 426 | 
            +
              
         | 
| 427 | 
            +
              # should_raise
         | 
| 428 | 
            +
              
         | 
| 429 | 
            +
              def test_should_raise_should_pass_when_proper_exception_is_raised
         | 
| 430 | 
            +
                assert_nothing_raised do
         | 
| 431 | 
            +
                  proc { ''.nonexistant_method }.should_raise(NoMethodError)
         | 
| 432 | 
            +
                end
         | 
| 433 | 
            +
              end
         | 
| 434 | 
            +
              
         | 
| 435 | 
            +
              def test_should_raise_should_not_pass_when_wrong_exception_is_raised
         | 
| 436 | 
            +
                assert_raise(Spec::Exceptions::ExpectationNotMetError) do
         | 
| 437 | 
            +
                  proc { ''.nonexistant_method }.should_raise(SyntaxError)
         | 
| 438 | 
            +
                end
         | 
| 439 | 
            +
              end
         | 
| 440 | 
            +
              
         | 
| 441 | 
            +
              def test_should_raise_should_not_pass_with_no_exception
         | 
| 442 | 
            +
                assert_raise(Spec::Exceptions::ExpectationNotMetError) do
         | 
| 443 | 
            +
                  not proc {''.to_s}.should_raise(NoMethodError)
         | 
| 444 | 
            +
                end
         | 
| 445 | 
            +
              end
         | 
| 446 | 
            +
              
         | 
| 447 | 
            +
              # should_not_raise
         | 
| 448 | 
            +
              
         | 
| 449 | 
            +
              def test_should_not_raise_should_pass_when_proper_exception_is_raised
         | 
| 450 | 
            +
                assert_raise(Spec::Exceptions::ExpectationNotMetError) do
         | 
| 451 | 
            +
                  proc { ''.nonexistant_method }.should_not_raise(NoMethodError)
         | 
| 452 | 
            +
                end
         | 
| 453 | 
            +
              end
         | 
| 454 | 
            +
              
         | 
| 455 | 
            +
              def test_should_not_raise_should_not_pass_when_wrong_exception_is_raised
         | 
| 456 | 
            +
                assert_nothing_raised do
         | 
| 457 | 
            +
                  proc { ''.nonexistant_method }.should_not_raise(SyntaxError)
         | 
| 458 | 
            +
                end
         | 
| 459 | 
            +
              end
         | 
| 460 | 
            +
              
         | 
| 461 | 
            +
              def test_should_not_raise_should_not_pass_with_no_exception
         | 
| 462 | 
            +
                assert_nothing_raised do
         | 
| 463 | 
            +
                  not proc { ''.to_s }.should_not_raise(NoMethodError)
         | 
| 464 | 
            +
                end
         | 
| 465 | 
            +
              end
         | 
| 426 466 |  | 
| 427 467 | 
             
            end
         | 
| @@ -0,0 +1,162 @@ | |
| 1 | 
            +
            require 'test/unit'
         | 
| 2 | 
            +
            require 'socket'
         | 
| 3 | 
            +
            require 'spec'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class PassingCon < Spec::Context
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              def ex1
         | 
| 8 | 
            +
                true.should_be_true
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def ex2
         | 
| 12 | 
            +
                true.should_be_true
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def ex3
         | 
| 16 | 
            +
                true.should_be_true
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
             | 
| 22 | 
            +
            class FailingCon < Spec::Context
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def fail1
         | 
| 25 | 
            +
                false.should_be_true
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def fail2
         | 
| 29 | 
            +
                false.should_be_true
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def fail3
         | 
| 33 | 
            +
                false.should_be_true
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
            class ErringCon < Spec::Context
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              def error1
         | 
| 42 | 
            +
                raise "boom"
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def error2
         | 
| 46 | 
            +
                raise "boom"
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def error3
         | 
| 50 | 
            +
                raise "boom"
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            class SocketListener
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            	def initialize(port)
         | 
| 58 | 
            +
            	  @server_socket = TCPServer.new("127.0.0.1", port)
         | 
| 59 | 
            +
            		@expectations = Array.new
         | 
| 60 | 
            +
            		@next_expectation_index = 0 
         | 
| 61 | 
            +
            		@expectations_met = false
         | 
| 62 | 
            +
            	end
         | 
| 63 | 
            +
            	
         | 
| 64 | 
            +
            	def shutdown
         | 
| 65 | 
            +
            		@th.kill
         | 
| 66 | 
            +
            		@server_socket.shutdown
         | 
| 67 | 
            +
            	end
         | 
| 68 | 
            +
            	
         | 
| 69 | 
            +
            	def expects(expected_regex)
         | 
| 70 | 
            +
            		@expectations << expected_regex
         | 
| 71 | 
            +
            	end
         | 
| 72 | 
            +
            	
         | 
| 73 | 
            +
            	def verify
         | 
| 74 | 
            +
            		sleep 1
         | 
| 75 | 
            +
            		return if @expectations_met
         | 
| 76 | 
            +
            		msg = "Nothing matching /#{@expectations[@next_expectation_index].source}/ was seen"
         | 
| 77 | 
            +
            		raise  Test::Unit::AssertionFailedError.new(msg)
         | 
| 78 | 
            +
            	end
         | 
| 79 | 
            +
            	
         | 
| 80 | 
            +
            	def run
         | 
| 81 | 
            +
            		@socket = @server_socket.accept
         | 
| 82 | 
            +
            		@th = Thread.new("socket listener") do
         | 
| 83 | 
            +
            			until @expectations_met
         | 
| 84 | 
            +
            				msg, sender = @socket.readline
         | 
| 85 | 
            +
            				msg.chomp!
         | 
| 86 | 
            +
            				next unless @expectations[@next_expectation_index] =~ msg
         | 
| 87 | 
            +
            				@next_expectation_index += 1
         | 
| 88 | 
            +
            				remaining = @expectations.size - @next_expectation_index
         | 
| 89 | 
            +
            				@expectations_met = (remaining == 0)
         | 
| 90 | 
            +
            			end
         | 
| 91 | 
            +
            		end
         | 
| 92 | 
            +
            	end
         | 
| 93 | 
            +
            end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            class TestGuiRunner < Test::Unit::TestCase
         | 
| 96 | 
            +
             | 
| 97 | 
            +
              def setup
         | 
| 98 | 
            +
            		port = 13001
         | 
| 99 | 
            +
            		@listener = SocketListener.new(port)
         | 
| 100 | 
            +
            		@listener.expects /connected/
         | 
| 101 | 
            +
                @runner = Spec::GuiRunner.new(port)
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            	def teardown
         | 
| 105 | 
            +
            		@listener.shutdown
         | 
| 106 | 
            +
            	end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            	def test_size_on_start
         | 
| 109 | 
            +
            		@listener.expects /start 3/
         | 
| 110 | 
            +
            		@listener.run
         | 
| 111 | 
            +
            		@runner.run(PassingCon)
         | 
| 112 | 
            +
            		@listener.verify
         | 
| 113 | 
            +
            	end
         | 
| 114 | 
            +
            	
         | 
| 115 | 
            +
              def test_passing_example_outputs_period
         | 
| 116 | 
            +
            		@listener.expects /start/
         | 
| 117 | 
            +
            		@listener.expects /passed/
         | 
| 118 | 
            +
            		@listener.expects /passed/
         | 
| 119 | 
            +
            		@listener.expects /passed/
         | 
| 120 | 
            +
            		@listener.expects /end/
         | 
| 121 | 
            +
            		@listener.run
         | 
| 122 | 
            +
                @runner.run(PassingCon)
         | 
| 123 | 
            +
                @listener.verify
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
              def test_failing_example_outputs_X
         | 
| 127 | 
            +
            		@listener.expects /start/
         | 
| 128 | 
            +
            		@listener.expects /failed/
         | 
| 129 | 
            +
            		@listener.expects /failed/
         | 
| 130 | 
            +
            		@listener.expects /failed/
         | 
| 131 | 
            +
            		@listener.expects /end/
         | 
| 132 | 
            +
            		@listener.run
         | 
| 133 | 
            +
                @runner.run(FailingCon)
         | 
| 134 | 
            +
                @listener.verify
         | 
| 135 | 
            +
              end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
              def test_erring_example_outputs_X
         | 
| 138 | 
            +
            		@listener.expects /start/
         | 
| 139 | 
            +
            		@listener.expects /failed/
         | 
| 140 | 
            +
            		@listener.expects /failed/
         | 
| 141 | 
            +
            		@listener.expects /failed/
         | 
| 142 | 
            +
            		@listener.expects /end/
         | 
| 143 | 
            +
            		@listener.run
         | 
| 144 | 
            +
                @runner.run(ErringCon)
         | 
| 145 | 
            +
                @listener.verify
         | 
| 146 | 
            +
              end
         | 
| 147 | 
            +
              
         | 
| 148 | 
            +
              def test_failure_backtrace
         | 
| 149 | 
            +
            		@listener.expects /.*in `fail1'.*/
         | 
| 150 | 
            +
            		@listener.run
         | 
| 151 | 
            +
                @runner.run(FailingCon)
         | 
| 152 | 
            +
                @listener.verify
         | 
| 153 | 
            +
              end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              def test_error_backtrace
         | 
| 156 | 
            +
            		@listener.expects /.*in `error3'.*/
         | 
| 157 | 
            +
            		@listener.run
         | 
| 158 | 
            +
                @runner.run(ErringCon)
         | 
| 159 | 
            +
                @listener.verify
         | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
            end
         | 
    
        data/test/mock_test.rb
    CHANGED
    
    | @@ -13,7 +13,7 @@ class MockTest < Test::Unit::TestCase | |
| 13 13 | 
             
                begin
         | 
| 14 14 | 
             
                  @mock.__verify
         | 
| 15 15 | 
             
                rescue Spec::Exceptions::MockExpectationError => e
         | 
| 16 | 
            -
                  e.message.should_equal "./test/mock_test.rb:11:in `test_should_report_line_number_of_expectaion_of_unreceived_message': Mock 'test mock' expected wont_happen(<x:String>, <3:Fixnum>)  | 
| 16 | 
            +
                  e.message.should_equal "./test/mock_test.rb:11:in `test_should_report_line_number_of_expectaion_of_unreceived_message': Mock 'test mock' expected wont_happen(<x:String>, <3:Fixnum>) once, but received it 0 times"
         | 
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| 19 19 | 
             
              end
         | 
| @@ -89,4 +89,69 @@ class MockTest < Test::Unit::TestCase | |
| 89 89 | 
             
                end
         | 
| 90 90 | 
             
              end
         | 
| 91 91 |  | 
| 92 | 
            +
              def test_two_return_values
         | 
| 93 | 
            +
                @mock.should_receive(:multi_call).twice.with_no_args.and_return_consecutively([1, 2])
         | 
| 94 | 
            +
                assert_equal(1, @mock.multi_call)
         | 
| 95 | 
            +
                assert_equal(2, @mock.multi_call)
         | 
| 96 | 
            +
                @mock.__verify
         | 
| 97 | 
            +
              end
         | 
| 98 | 
            +
              
         | 
| 99 | 
            +
              def test_repeating_final_return_value
         | 
| 100 | 
            +
                @mock.should_receive(:multi_call).at_least_once.with_no_args.and_return_consecutively([1, 2])
         | 
| 101 | 
            +
                assert_equal(1, @mock.multi_call)
         | 
| 102 | 
            +
                assert_equal(2, @mock.multi_call)
         | 
| 103 | 
            +
                assert_equal(2, @mock.multi_call)
         | 
| 104 | 
            +
                @mock.__verify
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
              
         | 
| 107 | 
            +
              def test_should_throw_on_call_of_never_method
         | 
| 108 | 
            +
                @mock.should_receive(:random_call).never
         | 
| 109 | 
            +
                assert_raise(Spec::Exceptions::MockExpectationError) do
         | 
| 110 | 
            +
                  @mock.random_call
         | 
| 111 | 
            +
                  @mock.__verify
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
              
         | 
| 115 | 
            +
              def test_should_throw_if_at_least_once_method_not_called
         | 
| 116 | 
            +
                @mock.should_receive(:random_call).at_least_once
         | 
| 117 | 
            +
                assert_raise(Spec::Exceptions::MockExpectationError) do
         | 
| 118 | 
            +
                  @mock.__verify
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
              
         | 
| 122 | 
            +
              def test_should_not_throw_if_any_number_of_times_method_not_called
         | 
| 123 | 
            +
                @mock.should_receive(:random_call).any_number_of_times
         | 
| 124 | 
            +
                @mock.__verify
         | 
| 125 | 
            +
              end
         | 
| 126 | 
            +
              
         | 
| 127 | 
            +
              def test_should_not_throw_if_any_number_of_times_method_is_called
         | 
| 128 | 
            +
                @mock.should_receive(:random_call).any_number_of_times
         | 
| 129 | 
            +
                @mock.random_call
         | 
| 130 | 
            +
                @mock.__verify
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
              
         | 
| 133 | 
            +
              def test_should_not_throw_if_at_least_once_method_is_called_twice
         | 
| 134 | 
            +
                @mock.should_receive(:random_call).at_least_once
         | 
| 135 | 
            +
                @mock.random_call
         | 
| 136 | 
            +
                @mock.random_call
         | 
| 137 | 
            +
                @mock.__verify
         | 
| 138 | 
            +
              end
         | 
| 139 | 
            +
              
         | 
| 140 | 
            +
              def test_should_support_mutiple_calls_with_different_args
         | 
| 141 | 
            +
                @mock.should_receive(:random_call).once.with(1)
         | 
| 142 | 
            +
                @mock.should_receive(:random_call).once.with(2)
         | 
| 143 | 
            +
                @mock.random_call(1)
         | 
| 144 | 
            +
                @mock.random_call(2)
         | 
| 145 | 
            +
                @mock.__verify
         | 
| 146 | 
            +
              end
         | 
| 147 | 
            +
              
         | 
| 148 | 
            +
              def test_should_support_multiple_calls_with_different_args_and_counts
         | 
| 149 | 
            +
                @mock.should_receive(:random_call).twice.with(1)
         | 
| 150 | 
            +
                @mock.should_receive(:random_call).once.with(2)
         | 
| 151 | 
            +
                @mock.random_call(1)
         | 
| 152 | 
            +
                @mock.random_call(2)
         | 
| 153 | 
            +
                @mock.random_call(1)
         | 
| 154 | 
            +
                @mock.__verify
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
              
         | 
| 92 157 | 
             
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require 'test/unit'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'spec'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
             | 
| 6 | 
            +
            class AddToMe < Spec::Context
         | 
| 7 | 
            +
              
         | 
| 8 | 
            +
              def orig_spec
         | 
| 9 | 
            +
                true.should_equal true
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            class SpecificationAdditionTest < Test::Unit::TestCase
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def test_should_add_foo_specification_to_context
         | 
| 18 | 
            +
                AddToMe.add_specification(:added_spec) { false.should_equal false }
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                assert_equal true, AddToMe.specifications.include?('added_spec')
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
              
         | 
| 23 | 
            +
              def test_should_add_another_specification_to_context
         | 
| 24 | 
            +
                AddToMe.add_specification(:another_added_spec) { true.should_equal false }
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                assert_equal true, AddToMe.specifications.include?('another_added_spec')
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
            end
         | 
    
        data/test/text_runner_test.rb
    CHANGED
    
    | @@ -97,19 +97,44 @@ class TestTextRunner < Test::Unit::TestCase | |
| 97 97 |  | 
| 98 98 | 
             
              def test_summary_with_no_failures
         | 
| 99 99 | 
             
                @runner.run(PassingCon)
         | 
| 100 | 
            -
                assert_buffer_includes "3 specifications,  | 
| 100 | 
            +
                assert_buffer_includes "3 specifications, 0 failures"
         | 
| 101 101 | 
             
              end
         | 
| 102 102 |  | 
| 103 103 | 
             
            	def test_should_run_all_specifications
         | 
| 104 104 | 
             
            		@runner.run(Spec::Collector)
         | 
| 105 | 
            -
            		assert_buffer_includes "9 specifications,  | 
| 105 | 
            +
            		assert_buffer_includes "9 specifications, 6 failures"
         | 
| 106 106 | 
             
            	end
         | 
| 107 107 |  | 
| 108 108 | 
             
            	def test_should_run_all_specifications_when_no_args_provided
         | 
| 109 109 | 
             
            		@runner.run
         | 
| 110 | 
            -
            		assert_buffer_includes "9 specifications,  | 
| 110 | 
            +
            		assert_buffer_includes "9 specifications, 6 failures"
         | 
| 111 111 | 
             
            	end
         | 
| 112 112 |  | 
| 113 | 
            +
              def test_should_only_report_first_failure
         | 
| 114 | 
            +
                ex = Spec::Exceptions::ExpectationNotMetError.new("1")
         | 
| 115 | 
            +
                ex.set_backtrace(["1", "2"])
         | 
| 116 | 
            +
                @runner.start_run
         | 
| 117 | 
            +
                @runner.spec(nil)
         | 
| 118 | 
            +
                @runner.failure(nil, ex)
         | 
| 119 | 
            +
                @runner.failure(nil, ex)
         | 
| 120 | 
            +
                @runner.end_run
         | 
| 121 | 
            +
                assert_buffer_includes "1 specifications, 1 failure"
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              def test_should_only_report_first_failure_over_multiple_specs
         | 
| 125 | 
            +
                ex = Spec::Exceptions::ExpectationNotMetError.new("1")
         | 
| 126 | 
            +
                ex.set_backtrace(["1", "2"])
         | 
| 127 | 
            +
                @runner.start_run
         | 
| 128 | 
            +
                @runner.spec(nil)
         | 
| 129 | 
            +
                @runner.failure(nil, ex)
         | 
| 130 | 
            +
                @runner.failure(nil, ex)
         | 
| 131 | 
            +
                @runner.spec(nil)
         | 
| 132 | 
            +
                @runner.failure(nil, ex)
         | 
| 133 | 
            +
                @runner.failure(nil, ex)
         | 
| 134 | 
            +
                @runner.end_run
         | 
| 135 | 
            +
                assert_buffer_includes "2 specifications, 2 failure"
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
             | 
| 113 138 | 
             
              def assert_buffer_includes(substring)
         | 
| 114 139 | 
             
                assert(@buffer.include?(substring), _buffer_message(substring))
         | 
| 115 140 | 
             
              end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,10 +1,10 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 | 
            -
            rubygems_version: 0.8. | 
| 2 | 
            +
            rubygems_version: 0.8.11
         | 
| 3 3 | 
             
            specification_version: 1
         | 
| 4 4 | 
             
            name: rspec
         | 
| 5 5 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 6 | 
            -
              version: 0. | 
| 7 | 
            -
            date:  | 
| 6 | 
            +
              version: 0.3.0
         | 
| 7 | 
            +
            date: 2006-01-20 00:00:00 -08:00
         | 
| 8 8 | 
             
            summary: Behaviour Specification Framework for Ruby
         | 
| 9 9 | 
             
            require_paths: 
         | 
| 10 10 | 
             
              - lib
         | 
| @@ -27,33 +27,41 @@ 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: 
         | 
| 30 32 | 
             
            authors: 
         | 
| 31 33 | 
             
              - Steven Baker
         | 
| 32 34 | 
             
            files: 
         | 
| 33 35 | 
             
              - CHANGES
         | 
| 34 | 
            -
              -  | 
| 35 | 
            -
              - Rakefile.rb
         | 
| 36 | 
            +
              - Rakefile
         | 
| 36 37 | 
             
              - README
         | 
| 37 38 | 
             
              - TODO
         | 
| 38 39 | 
             
              - TUTORIAL
         | 
| 39 40 | 
             
              - lib/spec.rb
         | 
| 40 41 | 
             
              - lib/spec/collector.rb
         | 
| 41 42 | 
             
              - lib/spec/context.rb
         | 
| 43 | 
            +
              - lib/spec/dsl.rb
         | 
| 42 44 | 
             
              - lib/spec/exceptions.rb
         | 
| 43 45 | 
             
              - lib/spec/expectations.rb
         | 
| 46 | 
            +
              - lib/spec/gui_runner.rb
         | 
| 44 47 | 
             
              - lib/spec/mock.rb
         | 
| 45 48 | 
             
              - lib/spec/text_runner.rb
         | 
| 46 49 | 
             
              - test/context_fixtures_test.rb
         | 
| 47 50 | 
             
              - test/context_run_test.rb
         | 
| 51 | 
            +
              - test/dsl_test.rb
         | 
| 48 52 | 
             
              - test/error_reporting_test.rb
         | 
| 49 53 | 
             
              - test/expectations_test.rb
         | 
| 50 54 | 
             
              - test/get_classes.rb
         | 
| 55 | 
            +
              - test/gui_runner_test.rb
         | 
| 51 56 | 
             
              - test/mock_test.rb
         | 
| 52 57 | 
             
              - test/spec_collection_test.rb
         | 
| 58 | 
            +
              - test/specification_addition_test.rb
         | 
| 53 59 | 
             
              - test/specification_identification_test.rb
         | 
| 54 60 | 
             
              - test/text_runner_test.rb
         | 
| 61 | 
            +
              - examples/add_specification_spec.rb
         | 
| 55 62 | 
             
              - examples/craps.rb
         | 
| 56 63 | 
             
              - examples/craps_spec.rb
         | 
| 64 | 
            +
              - examples/dsl_spec.rb
         | 
| 57 65 | 
             
              - examples/movie.rb
         | 
| 58 66 | 
             
              - examples/movie_list.rb
         | 
| 59 67 | 
             
              - examples/movie_spec.rb
         |