rspec 0.7.2 → 0.7.5.1
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 +72 -1
- data/EXAMPLES.rd +6 -0
- data/README +27 -6
- data/Rakefile +32 -81
- data/bin/drbspec +3 -0
- data/bin/spec +2 -3
- data/examples/file_accessor_spec.rb +1 -1
- data/examples/greeter_spec.rb +30 -0
- data/examples/helper_method_example.rb +1 -1
- data/examples/io_processor_spec.rb +1 -1
- data/examples/mocking_example.rb +1 -1
- data/examples/partial_mock_example.rb +1 -1
- data/examples/predicate_example.rb +1 -1
- data/examples/setup_teardown_example.rb +34 -0
- data/examples/spec_helper.rb +1 -0
- data/examples/stack_spec.rb +1 -1
- data/examples/stubbing_example.rb +1 -1
- data/examples/test_case_spec.rb +1 -1
- data/lib/spec/callback/callback_container.rb +60 -0
- data/lib/spec/callback/extensions/module.rb +24 -0
- data/lib/spec/callback/extensions/object.rb +33 -0
- data/lib/spec/callback.rb +3 -0
- data/lib/spec/expectations/diff.rb +10 -14
- data/lib/spec/expectations/extensions/numeric.rb +17 -3
- data/lib/spec/expectations/extensions/object.rb +145 -0
- data/lib/spec/expectations/extensions/proc.rb +57 -0
- data/lib/spec/expectations/extensions/string.rb +22 -0
- data/lib/spec/expectations/extensions.rb +2 -2
- data/lib/spec/expectations/message_builder.rb +13 -0
- data/lib/spec/expectations/should/base.rb +29 -10
- data/lib/spec/expectations/should/change.rb +69 -0
- data/lib/spec/expectations/should/have.rb +94 -37
- data/lib/spec/expectations/should/not.rb +6 -2
- data/lib/spec/expectations/should/should.rb +9 -5
- data/lib/spec/expectations/should.rb +1 -0
- data/lib/spec/expectations/sugar.rb +2 -2
- data/lib/spec/expectations.rb +28 -0
- data/lib/spec/mocks/error_generator.rb +23 -12
- data/lib/spec/mocks/message_expectation.rb +18 -15
- data/lib/spec/mocks/mock_handler.rb +10 -9
- data/lib/spec/mocks/mock_methods.rb +1 -1
- data/lib/spec/rake/spectask.rb +8 -2
- data/lib/spec/runner/backtrace_tweaker.rb +34 -25
- data/lib/spec/runner/context.rb +56 -7
- data/lib/spec/runner/context_eval.rb +33 -3
- data/lib/spec/runner/context_runner.rb +24 -11
- data/lib/spec/runner/drb_command_line.rb +21 -0
- data/lib/spec/runner/execution_context.rb +1 -0
- data/lib/spec/runner/extensions/kernel.rb +2 -0
- data/lib/spec/runner/extensions/object.rb +26 -18
- data/lib/spec/runner/formatter/base_text_formatter.rb +1 -1
- data/lib/spec/runner/formatter/html_formatter.rb +94 -74
- data/lib/spec/runner/heckle_runner.rb +55 -0
- data/lib/spec/runner/option_parser.rb +15 -3
- data/lib/spec/runner/reporter.rb +13 -8
- data/lib/spec/runner/specification.rb +67 -42
- data/lib/spec/runner.rb +1 -1
- data/lib/spec/version.rb +6 -5
- data/lib/spec.rb +1 -0
- metadata +20 -19
- data/lib/spec/expectations/extensions/inspect_for_expectation_not_met_error.rb +0 -14
- data/lib/spec/expectations/extensions/symbol.rb +0 -5
- data/vendor/selenium/README.txt +0 -23
- data/vendor/selenium/find_rspecs_home_page.rb +0 -23
- data/vendor/selenium/rspec_selenium.rb +0 -33
- data/vendor/selenium/start_browser_once.patch +0 -65
- data/vendor/watir/README.txt +0 -32
- data/vendor/watir/find_rspecs_home_page.rb +0 -21
- data/vendor/watir/find_rspecs_home_page.txt +0 -15
- data/vendor/watir/rspec_watir.rb +0 -45
| @@ -1,21 +1,29 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # Copyright (c) 2004 David Heinemeier Hansson
         | 
| 2 | 
            +
            # 
         | 
| 3 | 
            +
            # Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            # a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            # "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            # without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            # distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            # permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            # the following conditions:
         | 
| 10 | 
            +
            # 
         | 
| 11 | 
            +
            # The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            # included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
            # 
         | 
| 14 | 
            +
            # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
| 2 21 | 
             
            class Object
         | 
| 3 | 
            -
               | 
| 4 | 
            -
               | 
| 5 | 
            -
             | 
| 6 | 
            -
                 | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                  n += 1 while respond_to?(mname="__instance_exec#{n}")
         | 
| 10 | 
            -
                  InstanceExecHelper.module_eval{ define_method(mname, &block) }
         | 
| 11 | 
            -
                ensure
         | 
| 12 | 
            -
                  Thread.critical = old_critical
         | 
| 13 | 
            -
                end
         | 
| 14 | 
            -
                begin
         | 
| 15 | 
            -
                  ret = send(mname, *args)
         | 
| 16 | 
            -
                ensure
         | 
| 17 | 
            -
                  InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
                ret
         | 
| 22 | 
            +
              # From active_support
         | 
| 23 | 
            +
              def copy_instance_variables_from(object, exclude = [])
         | 
| 24 | 
            +
                exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
         | 
| 27 | 
            +
                instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
         | 
| 20 28 | 
             
              end
         | 
| 21 29 | 
             
            end
         | 
| @@ -4,83 +4,98 @@ module Spec | |
| 4 4 | 
             
                  class HtmlFormatter < BaseTextFormatter
         | 
| 5 5 | 
             
                    def initialize(output, dry_run=false, colour=false)
         | 
| 6 6 | 
             
                      super
         | 
| 7 | 
            -
                      @ | 
| 8 | 
            -
                      @ | 
| 7 | 
            +
                      @current_spec_number = 0
         | 
| 8 | 
            +
                      @current_context_number = 0
         | 
| 9 9 | 
             
                    end
         | 
| 10 | 
            -
             | 
| 10 | 
            +
             | 
| 11 11 | 
             
                    def start(spec_count)
         | 
| 12 12 | 
             
                      @spec_count = spec_count
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                      @output.puts  | 
| 13 | 
            +
             | 
| 14 | 
            +
                      @output.puts @@header
         | 
| 15 15 | 
             
                      STDOUT.flush
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 |  | 
| 18 18 | 
             
                    def add_context(name, first)
         | 
| 19 | 
            +
                      @current_context_number += 1
         | 
| 19 20 | 
             
                      unless first
         | 
| 20 | 
            -
                        @output.puts "  </ | 
| 21 | 
            +
                        @output.puts "  </dl>"
         | 
| 21 22 | 
             
                        @output.puts "</div>"
         | 
| 22 23 | 
             
                      end
         | 
| 23 24 | 
             
                      @output.puts "<div class=\"context\">"
         | 
| 24 | 
            -
                      @output.puts "  < | 
| 25 | 
            -
                      @output.puts "  < | 
| 25 | 
            +
                      @output.puts "  <dl>"
         | 
| 26 | 
            +
                      @output.puts "  <dt id=\"context_#{@current_context_number}\">#{name}</dt>"
         | 
| 26 27 | 
             
                      STDOUT.flush
         | 
| 27 28 | 
             
                    end
         | 
| 28 29 |  | 
| 29 30 | 
             
                    def start_dump
         | 
| 30 | 
            -
                      @output.puts "  </ | 
| 31 | 
            +
                      @output.puts "  </dl>"
         | 
| 31 32 | 
             
                      @output.puts "</div>"
         | 
| 32 33 | 
             
                      STDOUT.flush
         | 
| 33 34 | 
             
                    end
         | 
| 34 35 |  | 
| 35 36 | 
             
                    def spec_started(name)
         | 
| 36 37 | 
             
                      @current_spec = name
         | 
| 37 | 
            -
                      @ | 
| 38 | 
            +
                      @current_spec_number += 1
         | 
| 38 39 | 
             
                      STDOUT.flush
         | 
| 39 40 | 
             
                    end
         | 
| 40 41 |  | 
| 41 42 | 
             
                    def spec_passed(name)
         | 
| 42 43 | 
             
                      move_progress
         | 
| 43 | 
            -
                      @output.puts "    < | 
| 44 | 
            +
                      @output.puts "    <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{escape(@current_spec)}</span></dd>"
         | 
| 44 45 | 
             
                      STDOUT.flush
         | 
| 45 46 | 
             
                    end
         | 
| 46 47 |  | 
| 47 48 | 
             
                    def spec_failed(name, counter, failure)
         | 
| 48 | 
            -
                      @output.puts "    <script type=\"text/javascript\"> | 
| 49 | 
            +
                      @output.puts "    <script type=\"text/javascript\">makeRed('header');</script>"
         | 
| 50 | 
            +
                      @output.puts "    <script type=\"text/javascript\">makeRed('context_#{@current_context_number}');</script>"
         | 
| 49 51 | 
             
                      move_progress
         | 
| 50 | 
            -
                      @output.puts "    < | 
| 51 | 
            -
                      @output.puts "      < | 
| 52 | 
            +
                      @output.puts "    <dd class=\"spec failed\">"
         | 
| 53 | 
            +
                      @output.puts "      <span class=\"failed_spec_name\">#{escape(@current_spec)}</span>"
         | 
| 52 54 | 
             
                      @output.puts "      <div class=\"failure\" id=\"failure_#{counter}\">"
         | 
| 53 55 | 
             
                      @output.puts "        <div class=\"message\"><pre>#{escape(failure.exception.message)}</pre></div>" unless failure.exception.nil?
         | 
| 54 56 | 
             
                      @output.puts "        <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil?
         | 
| 57 | 
            +
                      extra_failure_content
         | 
| 55 58 | 
             
                      @output.puts "      </div>"
         | 
| 56 | 
            -
                      @output.puts "    </ | 
| 59 | 
            +
                      @output.puts "    </dd>"
         | 
| 57 60 | 
             
                      STDOUT.flush
         | 
| 58 61 | 
             
                    end
         | 
| 59 62 |  | 
| 63 | 
            +
                    # Override this method if you wish to output extra HTML for a failed spec. For example, you
         | 
| 64 | 
            +
                    # could output links to images or other files produced during the specs. Example:
         | 
| 65 | 
            +
                    #
         | 
| 66 | 
            +
                    #
         | 
| 67 | 
            +
                    def extra_failure_content
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                    
         | 
| 60 70 | 
             
                    def move_progress
         | 
| 61 | 
            -
                      percent_done = @spec_count == 0 ? 100.0 : (@ | 
| 71 | 
            +
                      percent_done = @spec_count == 0 ? 100.0 : (@current_spec_number.to_f / @spec_count.to_f * 1000).to_i / 10.0
         | 
| 62 72 | 
             
                      @output.puts "    <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
         | 
| 63 73 | 
             
                    end
         | 
| 64 74 |  | 
| 65 75 | 
             
                    def escape(string)
         | 
| 66 76 | 
             
                      string.gsub(/&/n, '&').gsub(/\"/n, '"').gsub(/>/n, '>').gsub(/</n, '<')
         | 
| 67 77 | 
             
                    end
         | 
| 68 | 
            -
             | 
| 78 | 
            +
             | 
| 69 79 | 
             
                    def dump_failure(counter, failure)
         | 
| 70 80 | 
             
                    end
         | 
| 71 81 |  | 
| 72 82 | 
             
                    def dump_summary(duration, spec_count, failure_count)
         | 
| 83 | 
            +
                      if @dry_run
         | 
| 84 | 
            +
                        totals = "This was a dry-run"
         | 
| 85 | 
            +
                      else
         | 
| 86 | 
            +
                        totals = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
                      @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
         | 
| 89 | 
            +
                      @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
         | 
| 90 | 
            +
                      @output.puts "</div>"
         | 
| 73 91 | 
             
                      @output.puts "</body>"
         | 
| 74 92 | 
             
                      @output.puts "</html>"
         | 
| 75 93 | 
             
                      STDOUT.flush
         | 
| 76 94 | 
             
                    end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                     | 
| 79 | 
            -
                    GREEN_BACKGROUND = '#659D32'
         | 
| 80 | 
            -
                    
         | 
| 81 | 
            -
                    HEADER = <<-HEADER
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                    @@header = <<-HEADER
         | 
| 82 97 | 
             
            <?xml version="1.0" encoding="iso-8859-1"?>
         | 
| 83 | 
            -
            <!DOCTYPE html | 
| 98 | 
            +
            <!DOCTYPE html
         | 
| 84 99 | 
             
                 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         | 
| 85 100 | 
             
                 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
         | 
| 86 101 |  | 
| @@ -91,98 +106,103 @@ module Spec | |
| 91 106 | 
             
              <meta http-equiv="Content-Script-Type" content="text/javascript" />
         | 
| 92 107 | 
             
              <script type="text/javascript">
         | 
| 93 108 | 
             
              function moveProgressBar(percentDone) {
         | 
| 94 | 
            -
                document.getElementById(" | 
| 109 | 
            +
                document.getElementById("header").style.width = percentDone +"%";
         | 
| 95 110 | 
             
              }
         | 
| 96 | 
            -
              function  | 
| 97 | 
            -
                document.getElementById( | 
| 111 | 
            +
              function makeRed(element_id) {
         | 
| 112 | 
            +
                document.getElementById(element_id).style.background = '#C40D0D';
         | 
| 98 113 | 
             
              }
         | 
| 99 114 | 
             
              </script>
         | 
| 100 115 | 
             
              <style type="text/css">
         | 
| 101 116 | 
             
              body {
         | 
| 102 | 
            -
                 | 
| 103 | 
            -
                 | 
| 104 | 
            -
                width: 85%;
         | 
| 117 | 
            +
                margin: 0; padding: 0;
         | 
| 118 | 
            +
                background: #fff;
         | 
| 105 119 | 
             
              }
         | 
| 106 120 |  | 
| 107 | 
            -
              # | 
| 108 | 
            -
                background | 
| 109 | 
            -
                border-bottom: 1px solid gray; 
         | 
| 110 | 
            -
                border-right: 1px solid gray;
         | 
| 121 | 
            +
              #header {
         | 
| 122 | 
            +
                background: #65C400; color: #fff;
         | 
| 111 123 | 
             
              }
         | 
| 112 124 |  | 
| 113 | 
            -
               | 
| 114 | 
            -
                 | 
| 115 | 
            -
                 | 
| 125 | 
            +
              h1 {
         | 
| 126 | 
            +
                margin: 0 0 10px;
         | 
| 127 | 
            +
                padding: 10px;
         | 
| 128 | 
            +
                font: bold 18px "Lucida Grande", Helvetica, sans-serif;
         | 
| 116 129 | 
             
              }
         | 
| 117 130 |  | 
| 118 | 
            -
               | 
| 119 | 
            -
                padding:  | 
| 120 | 
            -
                 | 
| 121 | 
            -
                 | 
| 131 | 
            +
              #summary {
         | 
| 132 | 
            +
                margin: 0; padding: 5px 10px;
         | 
| 133 | 
            +
                font: bold 10px "Lucida Grande", Helvetica, sans-serif;
         | 
| 134 | 
            +
                text-align: right;
         | 
| 135 | 
            +
                position: absolute;
         | 
| 136 | 
            +
                top: 0px;
         | 
| 137 | 
            +
                right: 0px;
         | 
| 122 138 | 
             
              }
         | 
| 123 139 |  | 
| 124 | 
            -
               | 
| 125 | 
            -
                 | 
| 140 | 
            +
              #summary p {
         | 
| 141 | 
            +
                margin: 0 0 2px;
         | 
| 126 142 | 
             
              }
         | 
| 127 143 |  | 
| 128 | 
            -
               | 
| 129 | 
            -
                 | 
| 130 | 
            -
                margin: 0;
         | 
| 131 | 
            -
                border: 1px solid #fff;
         | 
| 144 | 
            +
              #summary #totals {
         | 
| 145 | 
            +
                font-size: 14px;
         | 
| 132 146 | 
             
              }
         | 
| 133 147 |  | 
| 134 | 
            -
               | 
| 135 | 
            -
                 | 
| 136 | 
            -
                 | 
| 137 | 
            -
                color: #589CCF;
         | 
| 148 | 
            +
              .context {
         | 
| 149 | 
            +
                margin: 0 10px 5px;
         | 
| 150 | 
            +
                background: #fff;
         | 
| 138 151 | 
             
              }
         | 
| 139 152 |  | 
| 140 | 
            -
               | 
| 141 | 
            -
                 | 
| 142 | 
            -
                 | 
| 153 | 
            +
              dl {
         | 
| 154 | 
            +
                margin: 0; padding: 0 0 5px;
         | 
| 155 | 
            +
                font: normal 11px "Lucida Grande", Helvetica, sans-serif;
         | 
| 143 156 | 
             
              }
         | 
| 144 157 |  | 
| 145 | 
            -
               | 
| 158 | 
            +
              dt {
         | 
| 159 | 
            +
                padding: 3px;
         | 
| 160 | 
            +
                background: #65C400;
         | 
| 161 | 
            +
                color: #fff;
         | 
| 146 162 | 
             
                font-weight: bold;
         | 
| 147 | 
            -
                color: #EEB4B4;
         | 
| 148 163 | 
             
              }
         | 
| 149 164 |  | 
| 150 | 
            -
               | 
| 151 | 
            -
                 | 
| 152 | 
            -
                 | 
| 153 | 
            -
                padding: 1px 4px; 
         | 
| 165 | 
            +
              dd {
         | 
| 166 | 
            +
                margin: 5px 0 5px 5px;
         | 
| 167 | 
            +
                padding: 3px 3px 3px 18px;
         | 
| 154 168 | 
             
              }
         | 
| 155 169 |  | 
| 156 | 
            -
               | 
| 157 | 
            -
                 | 
| 158 | 
            -
                 | 
| 159 | 
            -
                color: # | 
| 160 | 
            -
                padding: 2px 4px; 
         | 
| 170 | 
            +
              dd.spec.passed {
         | 
| 171 | 
            +
                border-left: 5px solid #65C400;
         | 
| 172 | 
            +
                border-bottom: 1px solid #65C400;
         | 
| 173 | 
            +
                background: #DBFFB4; color: #3D7700;
         | 
| 161 174 | 
             
              }
         | 
| 162 175 |  | 
| 163 | 
            -
               | 
| 164 | 
            -
                 | 
| 165 | 
            -
                 | 
| 176 | 
            +
              dd.spec.failed {
         | 
| 177 | 
            +
                border-left: 5px solid #C20000;
         | 
| 178 | 
            +
                border-bottom: 1px solid #C20000;
         | 
| 179 | 
            +
                color: #C20000; background: #FFFBD3;
         | 
| 166 180 | 
             
              }
         | 
| 167 181 |  | 
| 168 182 | 
             
              div.backtrace {
         | 
| 169 | 
            -
                color: # | 
| 183 | 
            +
                color: #000;
         | 
| 184 | 
            +
                font-size: 12px;
         | 
| 170 185 | 
             
              }
         | 
| 171 186 |  | 
| 172 | 
            -
               | 
| 173 | 
            -
                color: # | 
| 187 | 
            +
              a {
         | 
| 188 | 
            +
                color: #BE5C00;
         | 
| 174 189 | 
             
              }
         | 
| 175 | 
            -
             | 
| 176 190 | 
             
              </style>
         | 
| 177 191 | 
             
            </head>
         | 
| 178 192 | 
             
            <body>
         | 
| 179 193 |  | 
| 180 | 
            -
            <div id=" | 
| 181 | 
            -
              < | 
| 194 | 
            +
            <div id="header">
         | 
| 195 | 
            +
              <h1>RSpec Results</h1>
         | 
| 196 | 
            +
             | 
| 197 | 
            +
              <div id="summary">
         | 
| 198 | 
            +
                <p id="duration"> </p>
         | 
| 199 | 
            +
                <p id="totals"> </p>
         | 
| 200 | 
            +
              </div>
         | 
| 182 201 | 
             
            </div>
         | 
| 183 202 |  | 
| 203 | 
            +
            <div id="results">
         | 
| 184 204 | 
             
            HEADER
         | 
| 185 205 | 
             
                  end
         | 
| 186 206 | 
             
                end
         | 
| 187 207 | 
             
              end
         | 
| 188 | 
            -
            end
         | 
| 208 | 
            +
            end
         | 
| @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            begin
         | 
| 2 | 
            +
              require 'rubygems'
         | 
| 3 | 
            +
              require 'heckle'
         | 
| 4 | 
            +
            rescue LoadError ; raise "You must gem install heckle to use --heckle" ; end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Spec
         | 
| 7 | 
            +
              module Runner
         | 
| 8 | 
            +
                # Creates a new Heckler configured to heckle all methods in the classes
         | 
| 9 | 
            +
                # whose name matches +filter+
         | 
| 10 | 
            +
                class HeckleRunner
         | 
| 11 | 
            +
                  def initialize(filter, heckle_class=Heckler)
         | 
| 12 | 
            +
                    @filter = filter
         | 
| 13 | 
            +
                    @heckle_class = heckle_class
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  
         | 
| 16 | 
            +
                  # Runs all the contexts held by +context_runner+ once for each of the 
         | 
| 17 | 
            +
                  # methods in the matched classes.
         | 
| 18 | 
            +
                  def heckle_with(context_runner)
         | 
| 19 | 
            +
                    if @filter =~ /(.*)[#\.](.*)/
         | 
| 20 | 
            +
                      heckle = @heckle_class.new($1, $2, context_runner)
         | 
| 21 | 
            +
                      heckle.validate
         | 
| 22 | 
            +
                    else
         | 
| 23 | 
            +
                      heckle_module
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  
         | 
| 27 | 
            +
                  def heckle_module
         | 
| 28 | 
            +
                    filter = /^#{@filter}/
         | 
| 29 | 
            +
                    classes = []
         | 
| 30 | 
            +
                    ObjectSpace.each_object(Class) do |klass|
         | 
| 31 | 
            +
                      classes << klass if klass.name =~ filter
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                    
         | 
| 34 | 
            +
                    classes.each do |klass|
         | 
| 35 | 
            +
                      klass.instance_methods(false).each do |method_name|
         | 
| 36 | 
            +
                        heckle = @heckle_class.new(klass.name, method_name, context_runner)
         | 
| 37 | 
            +
                        heckle.validate
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                
         | 
| 43 | 
            +
                class Heckler < Heckle::Base
         | 
| 44 | 
            +
                  def initialize(klass_name, method_name, context_runner)
         | 
| 45 | 
            +
                    super(klass_name, method_name)
         | 
| 46 | 
            +
                    @context_runner = context_runner
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def tests_pass?
         | 
| 50 | 
            +
                    failure_count = @context_runner.run(false)
         | 
| 51 | 
            +
                    failure_count == 0
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
| @@ -13,7 +13,7 @@ module Spec | |
| 13 13 | 
             
                    options = parse(args, err, out, warn_if_no_files)
         | 
| 14 14 |  | 
| 15 15 | 
             
                    formatter = options.formatter_type.new(options.out, options.dry_run, options.colour)
         | 
| 16 | 
            -
                    reporter = Reporter.new(formatter, options.backtrace_tweaker) 
         | 
| 16 | 
            +
                    options.reporter = Reporter.new(formatter, options.backtrace_tweaker) 
         | 
| 17 17 |  | 
| 18 18 | 
             
                    # this doesn't really belong here.
         | 
| 19 19 | 
             
                    # it should, but the way things are coupled, it doesn't
         | 
| @@ -21,7 +21,7 @@ module Spec | |
| 21 21 | 
             
                      Spec::Expectations::Should::Base.differ = options.differ_class.new(options.diff_format, options.context_lines, options.colour)
         | 
| 22 22 | 
             
                    end
         | 
| 23 23 |  | 
| 24 | 
            -
                    ContextRunner.new( | 
| 24 | 
            +
                    ContextRunner.new(options)
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 |  | 
| 27 27 | 
             
                  def parse(args, err, out, warn_if_no_files)
         | 
| @@ -74,7 +74,7 @@ module Spec | |
| 74 74 | 
             
                      opts.on("-s", "--spec SPECIFICATION_NAME", "Execute context or specification with matching name") do |spec_name|
         | 
| 75 75 | 
             
                        options.spec_name = spec_name
         | 
| 76 76 | 
             
                      end
         | 
| 77 | 
            -
             | 
| 77 | 
            +
                      
         | 
| 78 78 | 
             
                      opts.on("-l", "--line LINE_NUMBER", Integer, "Execute context or specification at given line") do |line_number|
         | 
| 79 79 | 
             
                        options.line_number = line_number.to_i
         | 
| 80 80 | 
             
                      end
         | 
| @@ -110,11 +110,23 @@ module Spec | |
| 110 110 | 
             
                      opts.on("-b", "--backtrace", "Output full backtrace") do
         | 
| 111 111 | 
             
                        options.backtrace_tweaker = NoisyBacktraceTweaker.new
         | 
| 112 112 | 
             
                      end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                      opts.on("-H", "--heckle CODE", "If all specs pass, this will run your specs many times, mutating",
         | 
| 115 | 
            +
                                                     "the specced code a little each time. The intent is that specs",
         | 
| 116 | 
            +
                                                     "*should* fail, and RSpec will tell you if they don't.",
         | 
| 117 | 
            +
                                                     "CODE should be either Some::Module, Some::Class or Some::Fabulous#method}") do |heckle|
         | 
| 118 | 
            +
                        require 'spec/runner/heckle_runner'
         | 
| 119 | 
            +
                        options.heckle_runner = HeckleRunner.new(heckle)
         | 
| 120 | 
            +
                      end
         | 
| 113 121 |  | 
| 114 122 | 
             
                      opts.on("-d", "--dry-run", "Don't execute specs") do
         | 
| 115 123 | 
             
                        options.dry_run = true
         | 
| 116 124 | 
             
                      end
         | 
| 117 125 |  | 
| 126 | 
            +
                      opts.on("-o", "--out OUTPUT_FILE", "Path to output file (defaults to STDOUT)") do |outfile|
         | 
| 127 | 
            +
                        options.out = File.new(outfile, 'w')
         | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
                      
         | 
| 118 130 | 
             
                      opts.on("-v", "--version", "Show version") do
         | 
| 119 131 | 
             
                        out.puts ::Spec::VERSION::DESCRIPTION
         | 
| 120 132 | 
             
                        exit if out == $stdout
         | 
    
        data/lib/spec/runner/reporter.rb
    CHANGED
    
    | @@ -4,14 +4,10 @@ module Spec | |
| 4 4 |  | 
| 5 5 | 
             
                  def initialize(formatter, backtrace_tweaker)
         | 
| 6 6 | 
             
                    @formatter = formatter
         | 
| 7 | 
            -
                    @context_names = []
         | 
| 8 | 
            -
                    @failures = []
         | 
| 9 | 
            -
                    @spec_names = []
         | 
| 10 7 | 
             
                    @backtrace_tweaker = backtrace_tweaker
         | 
| 11 | 
            -
                     | 
| 12 | 
            -
                    @end_time = nil
         | 
| 8 | 
            +
                    clear!
         | 
| 13 9 | 
             
                  end
         | 
| 14 | 
            -
             | 
| 10 | 
            +
                  
         | 
| 15 11 | 
             
                  def add_context(name)
         | 
| 16 12 | 
             
                    #TODO - @context_names.empty? tells the formatter whether this is the first context or not - that's a little slippery
         | 
| 17 13 | 
             
                    @formatter.add_context(name, @context_names.empty?)
         | 
| @@ -31,8 +27,9 @@ module Spec | |
| 31 27 | 
             
                      spec_failed(name, Failure.new(@context_names.last, name, error))
         | 
| 32 28 | 
             
                    end
         | 
| 33 29 | 
             
                  end
         | 
| 34 | 
            -
             | 
| 30 | 
            +
             | 
| 35 31 | 
             
                  def start(number_of_specs)
         | 
| 32 | 
            +
                    clear!
         | 
| 36 33 | 
             
                    @start_time = Time.new
         | 
| 37 34 | 
             
                    @formatter.start(number_of_specs)
         | 
| 38 35 | 
             
                  end
         | 
| @@ -51,6 +48,14 @@ module Spec | |
| 51 48 |  | 
| 52 49 | 
             
                  private
         | 
| 53 50 |  | 
| 51 | 
            +
                  def clear!
         | 
| 52 | 
            +
                    @context_names = []
         | 
| 53 | 
            +
                    @failures = []
         | 
| 54 | 
            +
                    @spec_names = []
         | 
| 55 | 
            +
                    @start_time = nil
         | 
| 56 | 
            +
                    @end_time = nil
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
              
         | 
| 54 59 | 
             
                  def dump_failures
         | 
| 55 60 | 
             
                    return if @failures.empty?
         | 
| 56 61 | 
             
                    @failures.inject(1) do |index, failure|
         | 
| @@ -97,4 +102,4 @@ module Spec | |
| 97 102 | 
             
                  end
         | 
| 98 103 | 
             
                end
         | 
| 99 104 | 
             
              end
         | 
| 100 | 
            -
            end
         | 
| 105 | 
            +
            end
         | 
| @@ -1,70 +1,95 @@ | |
| 1 1 | 
             
            module Spec
         | 
| 2 2 | 
             
              module Runner
         | 
| 3 3 | 
             
                class Specification
         | 
| 4 | 
            -
                  
         | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
                     | 
| 4 | 
            +
                  module ClassMethods
         | 
| 5 | 
            +
                    attr_accessor :current
         | 
| 6 | 
            +
                    protected :current=
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                    callback_events :before_setup, :after_teardown
         | 
| 9 9 | 
             
                  end
         | 
| 10 | 
            -
                  
         | 
| 10 | 
            +
                  extend ClassMethods
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  attr_reader :command
         | 
| 13 | 
            +
                  callback_events :before_setup, :after_teardown
         | 
| 14 | 
            +
             | 
| 11 15 | 
             
                  def initialize(name, opts={}, &block)
         | 
| 12 16 | 
             
                    @from = caller(0)[3]
         | 
| 13 17 | 
             
                    @name = name
         | 
| 14 18 | 
             
                    @options = opts
         | 
| 15 | 
            -
                    @ | 
| 16 | 
            -
                    @listeners = []
         | 
| 19 | 
            +
                    @command = block
         | 
| 17 20 | 
             
                  end
         | 
| 18 21 |  | 
| 19 | 
            -
                  def run(reporter | 
| 20 | 
            -
                    reporter.spec_started(@name)  | 
| 22 | 
            +
                  def run(reporter, setup_block, teardown_block, dry_run, execution_context)
         | 
| 23 | 
            +
                    reporter.spec_started(@name) if reporter
         | 
| 21 24 | 
             
                    return reporter.spec_finished(@name) if dry_run
         | 
| 22 | 
            -
                    @@current_spec = self
         | 
| 23 | 
            -
                    execution_context = execution_context || ::Spec::Runner::ExecutionContext.new(self)
         | 
| 24 | 
            -
                    errors = []
         | 
| 25 | 
            -
                    begin
         | 
| 26 | 
            -
                      execution_context.instance_exec(&setup_block) unless setup_block.nil?
         | 
| 27 | 
            -
                      setup_ok = true
         | 
| 28 | 
            -
                      execution_context.instance_exec(&@block)
         | 
| 29 | 
            -
                      spec_ok = true
         | 
| 30 | 
            -
                    rescue => e
         | 
| 31 | 
            -
                      errors << e
         | 
| 32 | 
            -
                    end
         | 
| 33 25 |  | 
| 26 | 
            +
                    errors = []
         | 
| 34 27 | 
             
                    begin
         | 
| 35 | 
            -
                       | 
| 36 | 
            -
                       | 
| 37 | 
            -
             | 
| 38 | 
            -
                      errors  | 
| 28 | 
            +
                      set_current
         | 
| 29 | 
            +
                      setup_ok = setup_spec(execution_context, errors, &setup_block)
         | 
| 30 | 
            +
                      spec_ok = execute_spec(execution_context, errors) if setup_ok
         | 
| 31 | 
            +
                      teardown_ok = teardown_spec(execution_context, errors, &teardown_block)
         | 
| 39 32 | 
             
                    ensure
         | 
| 40 | 
            -
                       | 
| 41 | 
            -
                      @@current_spec = nil
         | 
| 33 | 
            +
                      clear_current
         | 
| 42 34 | 
             
                    end
         | 
| 43 | 
            -
                    
         | 
| 44 | 
            -
                    SpecShouldRaiseHandler.new(@from, @options).handle(errors)
         | 
| 45 35 |  | 
| 46 | 
            -
                     | 
| 36 | 
            +
                    SpecShouldRaiseHandler.new(@from, @options).handle(errors)
         | 
| 37 | 
            +
                    reporter.spec_finished(@name, errors.first, failure_location(setup_ok, spec_ok, teardown_ok)) if reporter
         | 
| 47 38 | 
             
                  end
         | 
| 48 39 |  | 
| 49 40 | 
             
                  def matches_matcher?(matcher)
         | 
| 50 41 | 
             
                    matcher.matches? @name 
         | 
| 51 42 | 
             
                  end
         | 
| 52 43 |  | 
| 53 | 
            -
                   | 
| 54 | 
            -
             | 
| 44 | 
            +
                  private
         | 
| 45 | 
            +
                  def setup_spec(execution_context, errors, &setup_block)
         | 
| 46 | 
            +
                    notify_before_setup(errors)
         | 
| 47 | 
            +
                    execution_context.instance_eval(&setup_block) if setup_block
         | 
| 48 | 
            +
                    return errors.empty?
         | 
| 49 | 
            +
                  rescue => e
         | 
| 50 | 
            +
                    errors << e
         | 
| 51 | 
            +
                    return false
         | 
| 55 52 | 
             
                  end
         | 
| 56 53 |  | 
| 57 | 
            -
                  def  | 
| 58 | 
            -
                     | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 54 | 
            +
                  def execute_spec(execution_context, errors)
         | 
| 55 | 
            +
                    execution_context.instance_eval(&command)
         | 
| 56 | 
            +
                    return true
         | 
| 57 | 
            +
                  rescue => e
         | 
| 58 | 
            +
                    errors << e
         | 
| 59 | 
            +
                    return false
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def teardown_spec(execution_context, errors, &teardown_block)
         | 
| 63 | 
            +
                    execution_context.instance_eval(&teardown_block) if teardown_block
         | 
| 64 | 
            +
                    notify_after_teardown(errors)
         | 
| 65 | 
            +
                    return errors.empty?
         | 
| 66 | 
            +
                  rescue => e
         | 
| 67 | 
            +
                    errors << e
         | 
| 68 | 
            +
                    return false
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def notify_before_setup(errors)
         | 
| 72 | 
            +
                    self.class.send(:notify_callbacks, :before_setup, self, &append_errors(errors))
         | 
| 73 | 
            +
                    notify_callbacks(:before_setup, self, &append_errors(errors))
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  
         | 
| 76 | 
            +
                  def notify_after_teardown(errors)
         | 
| 77 | 
            +
                    notify_callbacks(:after_teardown, self, &append_errors(errors))
         | 
| 78 | 
            +
                    self.class.send(:notify_callbacks, :after_teardown, self, &append_errors(errors))
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
                  
         | 
| 81 | 
            +
                  def append_errors(errors)
         | 
| 82 | 
            +
                    proc {|error| errors << error}
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                  
         | 
| 85 | 
            +
                  def set_current
         | 
| 86 | 
            +
                    self.class.send(:current=, self)
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  def clear_current
         | 
| 90 | 
            +
                    self.class.send(:current=, nil)
         | 
| 65 91 | 
             
                  end
         | 
| 66 92 |  | 
| 67 | 
            -
                  private
         | 
| 68 93 | 
             
                  def failure_location(setup_ok, spec_ok, teardown_ok)
         | 
| 69 94 | 
             
                    return 'setup' unless setup_ok
         | 
| 70 95 | 
             
                    return @name unless spec_ok
         | 
| @@ -72,4 +97,4 @@ module Spec | |
| 72 97 | 
             
                  end
         | 
| 73 98 | 
             
                end
         | 
| 74 99 | 
             
              end
         | 
| 75 | 
            -
            end
         | 
| 100 | 
            +
            end
         | 
    
        data/lib/spec/runner.rb
    CHANGED
    
    | @@ -6,10 +6,10 @@ require 'spec/runner/execution_context' | |
| 6 6 | 
             
            require 'spec/runner/context_runner'
         | 
| 7 7 | 
             
            require 'spec/runner/option_parser'
         | 
| 8 8 | 
             
            require 'spec/runner/command_line'
         | 
| 9 | 
            +
            require 'spec/runner/drb_command_line'
         | 
| 9 10 | 
             
            require 'spec/runner/backtrace_tweaker'
         | 
| 10 11 | 
             
            require 'spec/runner/reporter'
         | 
| 11 12 | 
             
            require 'spec/runner/spec_matcher'
         | 
| 12 13 | 
             
            require 'spec/runner/extensions/kernel'
         | 
| 13 | 
            -
            require 'spec/runner/extensions/object'
         | 
| 14 14 | 
             
            require 'spec/runner/spec_should_raise_handler'
         | 
| 15 15 | 
             
            require 'spec/runner/spec_parser'
         | 
    
        data/lib/spec/version.rb
    CHANGED
    
    | @@ -3,13 +3,14 @@ module Spec | |
| 3 3 | 
             
                unless defined? MAJOR
         | 
| 4 4 | 
             
                  MAJOR  = 0
         | 
| 5 5 | 
             
                  MINOR  = 7
         | 
| 6 | 
            -
                  TINY   =  | 
| 7 | 
            -
                   | 
| 8 | 
            -
                   | 
| 6 | 
            +
                  TINY   = 5
         | 
| 7 | 
            +
                  MINISCULE = 1
         | 
| 8 | 
            +
                  # RANDOM_TOKEN: 0.0543628986724853
         | 
| 9 | 
            +
                  REV    = "$LastChangedRevision: 1395 $".match(/LastChangedRevision: (\d+)/)[1]
         | 
| 9 10 |  | 
| 10 | 
            -
                  STRING = [MAJOR, MINOR, TINY].join('.')
         | 
| 11 | 
            +
                  STRING = [MAJOR, MINOR, TINY, MINISCULE].join('.')
         | 
| 11 12 | 
             
                  FULL_VERSION = "#{STRING} (r#{REV})"
         | 
| 12 | 
            -
                  TAG    = "REL_" + [MAJOR, MINOR, TINY].join('_')
         | 
| 13 | 
            +
                  TAG    = "REL_" + [MAJOR, MINOR, TINY, MINISCULE].join('_')
         | 
| 13 14 |  | 
| 14 15 | 
             
                  NAME   = "RSpec"
         | 
| 15 16 | 
             
                  URL    = "http://rspec.rubyforge.org/"  
         |