dfect 1.1.0 → 2.0.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/CREDITS +2 -2
- data/HISTORY +306 -0
- data/INSTALL +35 -0
- data/README +95 -0
- data/USAGE +393 -0
- data/doc/api/Dfect.html +3179 -0
- data/doc/api/Object.html +107 -0
- data/doc/api/_index.html +107 -0
- data/doc/api/class_list.html +36 -0
- data/doc/api/css/common.css +1 -0
- data/doc/api/css/full_list.css +50 -0
- data/doc/api/css/style.css +268 -0
- data/doc/api/file.LICENSE.html +73 -0
- data/doc/api/file_list.html +38 -0
- data/doc/api/frames.html +13 -0
- data/doc/api/index.html +72 -13
- data/doc/api/js/app.js +99 -0
- data/doc/api/js/full_list.js +106 -0
- data/doc/api/js/{jquery-1.3.2.min.js → jquery.js} +0 -0
- data/doc/api/method_list.html +339 -0
- data/doc/api/top-level-namespace.html +87 -0
- data/doc/index.erb +16 -9
- data/doc/index.html +1057 -726
- data/lib/dfect.rb +431 -284
- data/lib/dfect/auto.rb +2 -6
- data/lib/dfect/inochi.rb +48 -0
- data/lib/dfect/inochi.yaml +75 -0
- data/lib/dfect/mini.rb +1 -5
- data/lib/dfect/spec.rb +6 -13
- data/lib/dfect/unit.rb +21 -33
- data/test/dfect/inochi_test.rb +17 -0
- data/test/{dfect.rb → dfect_test.rb} +167 -7
- data/test/runner +25 -0
- data/test/test_helper.rb +1 -0
- metadata +43 -55
- data/doc/api/apple-touch-icon.png +0 -0
- data/doc/api/classes/Class.html +0 -73
- data/doc/api/classes/Dfect.html +0 -1245
- data/doc/api/classes/Kernel.html +0 -322
- data/doc/api/classes/Object.html +0 -72
- data/doc/api/created.rid +0 -1
- data/doc/api/css/main.css +0 -263
- data/doc/api/css/panel.css +0 -383
- data/doc/api/css/reset.css +0 -53
- data/doc/api/favicon.ico +0 -0
- data/doc/api/files/CREDITS.html +0 -65
- data/doc/api/files/LICENSE.html +0 -76
- data/doc/api/files/lib/dfect/auto_rb.html +0 -80
- data/doc/api/files/lib/dfect/mini_rb.html +0 -77
- data/doc/api/files/lib/dfect/spec_rb.html +0 -73
- data/doc/api/files/lib/dfect/unit_rb.html +0 -73
- data/doc/api/files/lib/dfect_rb.html +0 -74
- data/doc/api/i/arrows.png +0 -0
- data/doc/api/i/results_bg.png +0 -0
- data/doc/api/i/tree_bg.png +0 -0
- data/doc/api/js/jquery-effect.js +0 -593
- data/doc/api/js/main.js +0 -22
- data/doc/api/js/searchdoc.js +0 -628
- data/doc/api/panel/index.html +0 -71
- data/doc/api/panel/search_index.js +0 -1
- data/doc/api/panel/tree.js +0 -1
- data/doc/history.erb +0 -161
- data/doc/intro.erb +0 -104
- data/doc/setup.erb +0 -107
- data/doc/usage.erb +0 -310
- data/rakefile +0 -21
    
        data/lib/dfect.rb
    CHANGED
    
    | @@ -1,8 +1,3 @@ | |
| 1 | 
            -
            #--
         | 
| 2 | 
            -
            # Copyright protects this work.
         | 
| 3 | 
            -
            # See LICENSE file for details.
         | 
| 4 | 
            -
            #++
         | 
| 5 | 
            -
             | 
| 6 1 | 
             
            require 'yaml'
         | 
| 7 2 | 
             
            #
         | 
| 8 3 | 
             
            # YAML raises this error when we try to serialize a class:
         | 
| @@ -11,7 +6,7 @@ require 'yaml' | |
| 11 6 | 
             
            #
         | 
| 12 7 | 
             
            # Work around this by representing a class by its name.
         | 
| 13 8 | 
             
            #
         | 
| 14 | 
            -
            class Class  | 
| 9 | 
            +
            class Class # @private
         | 
| 15 10 | 
             
              alias __to_yaml__ to_yaml
         | 
| 16 11 | 
             
              undef to_yaml
         | 
| 17 12 |  | 
| @@ -19,7 +14,6 @@ class Class #:nodoc: all | |
| 19 14 | 
             
                begin
         | 
| 20 15 | 
             
                  __to_yaml__
         | 
| 21 16 | 
             
                rescue TypeError => e
         | 
| 22 | 
            -
                  warn e
         | 
| 23 17 | 
             
                  self.name.to_yaml opts
         | 
| 24 18 | 
             
                end
         | 
| 25 19 | 
             
              end
         | 
| @@ -42,37 +36,40 @@ end | |
| 42 36 | 
             
            module Dfect
         | 
| 43 37 | 
             
              class << self
         | 
| 44 38 | 
             
                ##
         | 
| 45 | 
            -
                # Hash of test results, assembled by  | 
| 39 | 
            +
                # Hash of test results, assembled by {Dfect.run}.
         | 
| 46 40 | 
             
                #
         | 
| 47 | 
            -
                # [: | 
| 41 | 
            +
                # [:trace]
         | 
| 48 42 | 
             
                #   Hierarchical trace of all tests executed, where each test is
         | 
| 49 43 | 
             
                #   represented by its description, is mapped to an Array of
         | 
| 50 44 | 
             
                #   nested tests, and may contain zero or more assertion failures.
         | 
| 51 45 | 
             
                #
         | 
| 52 46 | 
             
                #   Assertion failures are represented as a Hash:
         | 
| 53 47 | 
             
                #
         | 
| 54 | 
            -
                #   [ | 
| 48 | 
            +
                #   [:fail]
         | 
| 55 49 | 
             
                #     Description of the assertion failure.
         | 
| 56 50 | 
             
                #
         | 
| 57 | 
            -
                #   [ | 
| 51 | 
            +
                #   [:code]
         | 
| 58 52 | 
             
                #     Source code surrounding the point of failure.
         | 
| 59 53 | 
             
                #
         | 
| 60 | 
            -
                #   [ | 
| 54 | 
            +
                #   [:vars]
         | 
| 61 55 | 
             
                #     Local variables visible at the point of failure.
         | 
| 62 56 | 
             
                #
         | 
| 63 | 
            -
                #   [ | 
| 57 | 
            +
                #   [:call]
         | 
| 64 58 | 
             
                #     Stack trace leading to the point of failure.
         | 
| 65 59 | 
             
                #
         | 
| 66 | 
            -
                # [: | 
| 60 | 
            +
                # [:stats]
         | 
| 67 61 | 
             
                #   Hash of counts of major events in test execution:
         | 
| 68 62 | 
             
                #
         | 
| 69 | 
            -
                #   [: | 
| 63 | 
            +
                #   [:time]
         | 
| 64 | 
            +
                #     Number of seconds elapsed for test execution.
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                #   [:pass]
         | 
| 70 67 | 
             
                #     Number of assertions that held true.
         | 
| 71 68 | 
             
                #
         | 
| 72 | 
            -
                #   [: | 
| 69 | 
            +
                #   [:fail]
         | 
| 73 70 | 
             
                #     Number of assertions that did not hold true.
         | 
| 74 71 | 
             
                #
         | 
| 75 | 
            -
                #   [: | 
| 72 | 
            +
                #   [:error]
         | 
| 76 73 | 
             
                #     Number of exceptions that were not rescued.
         | 
| 77 74 | 
             
                #
         | 
| 78 75 | 
             
                attr_reader :report
         | 
| @@ -85,7 +82,7 @@ module Dfect | |
| 85 82 | 
             
                #   during assertion failures so
         | 
| 86 83 | 
             
                #   the user can investigate them.
         | 
| 87 84 | 
             
                #
         | 
| 88 | 
            -
                #   The default value is  | 
| 85 | 
            +
                #   The default value is $DEBUG.
         | 
| 89 86 | 
             
                #
         | 
| 90 87 | 
             
                # [:quiet]
         | 
| 91 88 | 
             
                #   Do not print the report
         | 
| @@ -96,17 +93,20 @@ module Dfect | |
| 96 93 | 
             
                attr_accessor :options
         | 
| 97 94 |  | 
| 98 95 | 
             
                ##
         | 
| 99 | 
            -
                # Defines a new test | 
| 96 | 
            +
                # Defines a new test composed of the given
         | 
| 100 97 | 
             
                # description and the given block to execute.
         | 
| 101 98 | 
             
                #
         | 
| 102 | 
            -
                #  | 
| 99 | 
            +
                # This test may contain nested tests.
         | 
| 100 | 
            +
                #
         | 
| 101 | 
            +
                # Tests at the outer-most level are automatically
         | 
| 102 | 
            +
                # insulated from the top-level Ruby environment.
         | 
| 103 103 | 
             
                #
         | 
| 104 | 
            -
                #  | 
| 104 | 
            +
                # @param [Object, Array<Object>] description
         | 
| 105 105 | 
             
                #
         | 
| 106 | 
            -
                #  | 
| 107 | 
            -
                #    | 
| 106 | 
            +
                #   A brief title or a series of objects
         | 
| 107 | 
            +
                #   that describe the test being defined.
         | 
| 108 108 | 
             
                #
         | 
| 109 | 
            -
                #  | 
| 109 | 
            +
                # @example
         | 
| 110 110 | 
             
                #
         | 
| 111 111 | 
             
                #   D "a new array" do
         | 
| 112 112 | 
             
                #     D .< { @array = [] }
         | 
| @@ -124,18 +124,54 @@ module Dfect | |
| 124 124 | 
             
                #     end
         | 
| 125 125 | 
             
                #   end
         | 
| 126 126 | 
             
                #
         | 
| 127 | 
            -
                def D description | 
| 128 | 
            -
                   | 
| 129 | 
            -
                  @curr_suite.tests << Suite::Test.new(description.to_s, block)
         | 
| 127 | 
            +
                def D *description, &block
         | 
| 128 | 
            +
                  create_test @tests.empty?, *description, &block
         | 
| 130 129 | 
             
                end
         | 
| 131 130 |  | 
| 132 131 | 
             
                ##
         | 
| 133 | 
            -
                #  | 
| 132 | 
            +
                # Defines a new test that is explicitly insulated from the tests
         | 
| 133 | 
            +
                # that contain it and also from the top-level Ruby environment.
         | 
| 134 | 
            +
                #
         | 
| 135 | 
            +
                # This test may contain nested tests.
         | 
| 136 | 
            +
                #
         | 
| 137 | 
            +
                # @param description (see Dfect.D)
         | 
| 138 | 
            +
                #
         | 
| 139 | 
            +
                # @example
         | 
| 140 | 
            +
                #
         | 
| 141 | 
            +
                #   D "a root-level test" do
         | 
| 142 | 
            +
                #     @outside = 1
         | 
| 143 | 
            +
                #     T { defined? @outside }
         | 
| 144 | 
            +
                #     T { @outside == 1 }
         | 
| 145 | 
            +
                #
         | 
| 146 | 
            +
                #     D "an inner, non-insulated test" do
         | 
| 147 | 
            +
                #       T { defined? @outside }
         | 
| 148 | 
            +
                #       T { @outside == 1 }
         | 
| 149 | 
            +
                #     end
         | 
| 150 | 
            +
                #
         | 
| 151 | 
            +
                #     D! "an inner, insulated test" do
         | 
| 152 | 
            +
                #       F { defined? @outside }
         | 
| 153 | 
            +
                #       F { @outside == 1 }
         | 
| 154 | 
            +
                #
         | 
| 155 | 
            +
                #       @inside = 2
         | 
| 156 | 
            +
                #       T { defined? @inside }
         | 
| 157 | 
            +
                #       T { @inside == 2 }
         | 
| 158 | 
            +
                #     end
         | 
| 159 | 
            +
                #
         | 
| 160 | 
            +
                #     F { defined? @inside }
         | 
| 161 | 
            +
                #     F { @inside == 2 }
         | 
| 162 | 
            +
                #   end
         | 
| 163 | 
            +
                #
         | 
| 164 | 
            +
                def D! *description, &block
         | 
| 165 | 
            +
                  create_test true, *description, &block
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                ##
         | 
| 169 | 
            +
                # @overload def <(&block)
         | 
| 134 170 | 
             
                #
         | 
| 135 171 | 
             
                # Registers the given block to be executed
         | 
| 136 172 | 
             
                # before each nested test inside this test.
         | 
| 137 173 | 
             
                #
         | 
| 138 | 
            -
                #  | 
| 174 | 
            +
                # @example
         | 
| 139 175 | 
             
                #
         | 
| 140 176 | 
             
                #   D .< { puts "before each nested test" }
         | 
| 141 177 | 
             
                #
         | 
| @@ -146,7 +182,7 @@ module Dfect | |
| 146 182 | 
             
                def <(*args, &block)
         | 
| 147 183 | 
             
                  if args.empty?
         | 
| 148 184 | 
             
                    raise ArgumentError, 'block must be given' unless block
         | 
| 149 | 
            -
                    @ | 
| 185 | 
            +
                    @suite.before_each << block
         | 
| 150 186 | 
             
                  else
         | 
| 151 187 | 
             
                    # the < method is being used as a check for inheritance
         | 
| 152 188 | 
             
                    super
         | 
| @@ -157,7 +193,7 @@ module Dfect | |
| 157 193 | 
             
                # Registers the given block to be executed
         | 
| 158 194 | 
             
                # after each nested test inside this test.
         | 
| 159 195 | 
             
                #
         | 
| 160 | 
            -
                #  | 
| 196 | 
            +
                # @example
         | 
| 161 197 | 
             
                #
         | 
| 162 198 | 
             
                #   D .> { puts "after each nested test" }
         | 
| 163 199 | 
             
                #
         | 
| @@ -167,14 +203,14 @@ module Dfect | |
| 167 203 | 
             
                #
         | 
| 168 204 | 
             
                def > &block
         | 
| 169 205 | 
             
                  raise ArgumentError, 'block must be given' unless block
         | 
| 170 | 
            -
                  @ | 
| 206 | 
            +
                  @suite.after_each << block
         | 
| 171 207 | 
             
                end
         | 
| 172 208 |  | 
| 173 209 | 
             
                ##
         | 
| 174 210 | 
             
                # Registers the given block to be executed
         | 
| 175 211 | 
             
                # before all nested tests inside this test.
         | 
| 176 212 | 
             
                #
         | 
| 177 | 
            -
                #  | 
| 213 | 
            +
                # @example
         | 
| 178 214 | 
             
                #
         | 
| 179 215 | 
             
                #   D .<< { puts "before all nested tests" }
         | 
| 180 216 | 
             
                #
         | 
| @@ -184,14 +220,14 @@ module Dfect | |
| 184 220 | 
             
                #
         | 
| 185 221 | 
             
                def << &block
         | 
| 186 222 | 
             
                  raise ArgumentError, 'block must be given' unless block
         | 
| 187 | 
            -
                  @ | 
| 223 | 
            +
                  @suite.before_all << block
         | 
| 188 224 | 
             
                end
         | 
| 189 225 |  | 
| 190 226 | 
             
                ##
         | 
| 191 227 | 
             
                # Registers the given block to be executed
         | 
| 192 228 | 
             
                # after all nested tests inside this test.
         | 
| 193 229 | 
             
                #
         | 
| 194 | 
            -
                #  | 
| 230 | 
            +
                # @example
         | 
| 195 231 | 
             
                #
         | 
| 196 232 | 
             
                #   D .>> { puts "after all nested tests" }
         | 
| 197 233 | 
             
                #
         | 
| @@ -201,84 +237,84 @@ module Dfect | |
| 201 237 | 
             
                #
         | 
| 202 238 | 
             
                def >> &block
         | 
| 203 239 | 
             
                  raise ArgumentError, 'block must be given' unless block
         | 
| 204 | 
            -
                  @ | 
| 240 | 
            +
                  @suite.after_all << block
         | 
| 205 241 | 
             
                end
         | 
| 206 242 |  | 
| 207 243 | 
             
                ##
         | 
| 208 | 
            -
                # Asserts that the  | 
| 209 | 
            -
                #  | 
| 244 | 
            +
                # Asserts that the given condition or the
         | 
| 245 | 
            +
                # result of the given block is neither
         | 
| 246 | 
            +
                # nil nor false and returns that result.
         | 
| 247 | 
            +
                #
         | 
| 248 | 
            +
                # @param condition
         | 
| 249 | 
            +
                #
         | 
| 250 | 
            +
                #   The condition to be asserted.  A block
         | 
| 251 | 
            +
                #   may be given in place of this parameter.
         | 
| 210 252 | 
             
                #
         | 
| 211 | 
            -
                #  | 
| 253 | 
            +
                # @param message
         | 
| 212 254 | 
             
                #
         | 
| 213 | 
            -
                # [message]
         | 
| 214 255 | 
             
                #   Optional message to show in the
         | 
| 215 256 | 
             
                #   report if this assertion fails.
         | 
| 216 257 | 
             
                #
         | 
| 217 | 
            -
                #  | 
| 218 | 
            -
                #
         | 
| 219 | 
            -
                #   # no message specified:
         | 
| 258 | 
            +
                # @example no message given
         | 
| 220 259 | 
             
                #
         | 
| 221 260 | 
             
                #   T { true }  # passes
         | 
| 222 261 | 
             
                #   T { false } # fails
         | 
| 223 262 | 
             
                #   T { nil }   # fails
         | 
| 224 263 | 
             
                #
         | 
| 225 | 
            -
                # | 
| 264 | 
            +
                # @example message is given
         | 
| 226 265 | 
             
                #
         | 
| 227 | 
            -
                #   T( | 
| 266 | 
            +
                #   T("computers do not doublethink") { 2 + 2 != 5 } # passes
         | 
| 228 267 | 
             
                #
         | 
| 229 | 
            -
                def T message = nil, &block
         | 
| 230 | 
            -
                  assert_yield :assert, message, &block
         | 
| 268 | 
            +
                def T condition = nil, message = nil, &block
         | 
| 269 | 
            +
                  assert_yield :assert, condition, message, &block
         | 
| 231 270 | 
             
                end
         | 
| 232 271 |  | 
| 233 272 | 
             
                ##
         | 
| 234 | 
            -
                # Asserts that the  | 
| 235 | 
            -
                #  | 
| 236 | 
            -
                #
         | 
| 237 | 
            -
                # ==== Parameters
         | 
| 273 | 
            +
                # Asserts that the given condition or the
         | 
| 274 | 
            +
                # result of the given block is either nil
         | 
| 275 | 
            +
                # or false and returns that result.
         | 
| 238 276 | 
             
                #
         | 
| 239 | 
            -
                #  | 
| 240 | 
            -
                #   Optional message to show in the
         | 
| 241 | 
            -
                #   report if this assertion fails.
         | 
| 277 | 
            +
                # @param condition (see Dfect.T)
         | 
| 242 278 | 
             
                #
         | 
| 243 | 
            -
                #  | 
| 279 | 
            +
                # @param message (see Dfect.T)
         | 
| 244 280 | 
             
                #
         | 
| 245 | 
            -
                # | 
| 281 | 
            +
                # @example no message given
         | 
| 246 282 | 
             
                #
         | 
| 247 283 | 
             
                #   T! { true }  # fails
         | 
| 248 284 | 
             
                #   T! { false } # passes
         | 
| 249 285 | 
             
                #   T! { nil }   # passes
         | 
| 250 286 | 
             
                #
         | 
| 251 | 
            -
                # | 
| 287 | 
            +
                # @example message is given
         | 
| 252 288 | 
             
                #
         | 
| 253 | 
            -
                #   T!( | 
| 289 | 
            +
                #   T!("computers do not doublethink") { 2 + 2 == 5 } # passes
         | 
| 254 290 | 
             
                #
         | 
| 255 | 
            -
                def T! message = nil, &block
         | 
| 256 | 
            -
                  assert_yield :negate, message, &block
         | 
| 291 | 
            +
                def T! condition = nil, message = nil, &block
         | 
| 292 | 
            +
                  assert_yield :negate, condition, message, &block
         | 
| 257 293 | 
             
                end
         | 
| 258 294 |  | 
| 259 295 | 
             
                ##
         | 
| 260 | 
            -
                # Returns true if the  | 
| 261 | 
            -
                #  | 
| 296 | 
            +
                # Returns true if the given condition or
         | 
| 297 | 
            +
                # the result of the given block is neither
         | 
| 298 | 
            +
                # nil nor false.  Otherwise, returns false.
         | 
| 262 299 | 
             
                #
         | 
| 263 | 
            -
                #  | 
| 300 | 
            +
                # @param condition (see Dfect.T)
         | 
| 264 301 | 
             
                #
         | 
| 265 | 
            -
                #  | 
| 266 | 
            -
                #   This parameter is optional and completely ignored.
         | 
| 302 | 
            +
                # @param message
         | 
| 267 303 | 
             
                #
         | 
| 268 | 
            -
                #  | 
| 304 | 
            +
                #   This parameter is optional and completely ignored.
         | 
| 269 305 | 
             
                #
         | 
| 270 | 
            -
                # | 
| 306 | 
            +
                # @example no message given
         | 
| 271 307 | 
             
                #
         | 
| 272 308 | 
             
                #   T? { true }  # => true
         | 
| 273 309 | 
             
                #   T? { false } # => false
         | 
| 274 310 | 
             
                #   T? { nil }   # => false
         | 
| 275 311 | 
             
                #
         | 
| 276 | 
            -
                # | 
| 312 | 
            +
                # @example message is given
         | 
| 277 313 | 
             
                #
         | 
| 278 | 
            -
                #   T?( | 
| 314 | 
            +
                #   T?("computers do not doublethink") { 2 + 2 != 5 } # => true
         | 
| 279 315 | 
             
                #
         | 
| 280 | 
            -
                def T? message = nil, &block
         | 
| 281 | 
            -
                  assert_yield :sample, message, &block
         | 
| 316 | 
            +
                def T? condition = nil, message = nil, &block
         | 
| 317 | 
            +
                  assert_yield :sample, condition, message, &block
         | 
| 282 318 | 
             
                end
         | 
| 283 319 |  | 
| 284 320 | 
             
                alias F T!
         | 
| @@ -289,20 +325,15 @@ module Dfect | |
| 289 325 | 
             
                # Returns true if the result of the given block is
         | 
| 290 326 | 
             
                # either nil or false.  Otherwise, returns false.
         | 
| 291 327 | 
             
                #
         | 
| 292 | 
            -
                #  | 
| 293 | 
            -
                #
         | 
| 294 | 
            -
                # [message]
         | 
| 295 | 
            -
                #   This parameter is optional and completely ignored.
         | 
| 296 | 
            -
                #
         | 
| 297 | 
            -
                # ==== Examples
         | 
| 328 | 
            +
                # @param message (see Dfect.T?)
         | 
| 298 329 | 
             
                #
         | 
| 299 | 
            -
                # | 
| 330 | 
            +
                # @example no message given
         | 
| 300 331 | 
             
                #
         | 
| 301 332 | 
             
                #   F? { true }  # => false
         | 
| 302 333 | 
             
                #   F? { false } # => true
         | 
| 303 334 | 
             
                #   F? { nil }   # => true
         | 
| 304 335 | 
             
                #
         | 
| 305 | 
            -
                # | 
| 336 | 
            +
                # @example message is given
         | 
| 306 337 | 
             
                #
         | 
| 307 338 | 
             
                #   F?( "computers do not doublethink" ) { 2 + 2 == 5 } # => true
         | 
| 308 339 | 
             
                #
         | 
| @@ -315,84 +346,67 @@ module Dfect | |
| 315 346 | 
             
                # kinds of exceptions is raised
         | 
| 316 347 | 
             
                # when the given block is executed.
         | 
| 317 348 | 
             
                #
         | 
| 318 | 
            -
                #  | 
| 319 | 
            -
                # then that exception is returned.
         | 
| 349 | 
            +
                # @return
         | 
| 320 350 | 
             
                #
         | 
| 321 | 
            -
                #  | 
| 351 | 
            +
                #   If the block raises an exception,
         | 
| 352 | 
            +
                #   then that exception is returned.
         | 
| 322 353 | 
             
                #
         | 
| 323 | 
            -
                #  | 
| 354 | 
            +
                #   Otherwise, nil is returned.
         | 
| 324 355 | 
             
                #
         | 
| 325 | 
            -
                # [ | 
| 326 | 
            -
                #   Optional message to show in the
         | 
| 327 | 
            -
                #   report if this assertion fails.
         | 
| 356 | 
            +
                # @param [...] kinds_then_message
         | 
| 328 357 | 
             
                #
         | 
| 329 | 
            -
                #  | 
| 330 | 
            -
                #    | 
| 358 | 
            +
                #   Exception classes that must be raised by the given block, optionally
         | 
| 359 | 
            +
                #   followed by a message to show in the report if this assertion fails.
         | 
| 331 360 | 
             
                #
         | 
| 332 | 
            -
                #   If  | 
| 333 | 
            -
                #    | 
| 361 | 
            +
                #   If no exception classes are given, then
         | 
| 362 | 
            +
                #   StandardError is assumed (similar to
         | 
| 363 | 
            +
                #   how a plain 'rescue' statement without
         | 
| 364 | 
            +
                #   any arguments catches StandardError).
         | 
| 334 365 | 
             
                #
         | 
| 335 | 
            -
                #  | 
| 336 | 
            -
                #
         | 
| 337 | 
            -
                #   # no exceptions specified:
         | 
| 366 | 
            +
                # @example no exceptions given
         | 
| 338 367 | 
             
                #
         | 
| 339 368 | 
             
                #   E { }       # fails
         | 
| 340 369 | 
             
                #   E { raise } # passes
         | 
| 341 370 | 
             
                #
         | 
| 342 | 
            -
                # | 
| 371 | 
            +
                # @example single exception given
         | 
| 343 372 | 
             
                #
         | 
| 344 | 
            -
                #   E( | 
| 345 | 
            -
                #   E( "argument must be invalid" | 
| 373 | 
            +
                #   E(ArgumentError) { raise ArgumentError }
         | 
| 374 | 
            +
                #   E(ArgumentError, "argument must be invalid") { raise ArgumentError }
         | 
| 346 375 | 
             
                #
         | 
| 347 | 
            -
                # | 
| 376 | 
            +
                # @example multiple exceptions given
         | 
| 348 377 | 
             
                #
         | 
| 349 | 
            -
                #   E( | 
| 350 | 
            -
                #   E( "string must compile" | 
| 378 | 
            +
                #   E(SyntaxError, NameError) { eval "..." }
         | 
| 379 | 
            +
                #   E(SyntaxError, NameError, "string must compile") { eval "..." }
         | 
| 351 380 | 
             
                #
         | 
| 352 | 
            -
                def E  | 
| 353 | 
            -
                  assert_raise :assert,  | 
| 381 | 
            +
                def E *kinds_then_message, &block
         | 
| 382 | 
            +
                  assert_raise :assert, *kinds_then_message, &block
         | 
| 354 383 | 
             
                end
         | 
| 355 384 |  | 
| 356 385 | 
             
                ##
         | 
| 357 386 | 
             
                # Asserts that one of the given kinds of exceptions
         | 
| 358 387 | 
             
                # is not raised when the given block is executed.
         | 
| 359 388 | 
             
                #
         | 
| 360 | 
            -
                #  | 
| 361 | 
            -
                # then that exception is returned.
         | 
| 362 | 
            -
                #
         | 
| 363 | 
            -
                # Otherwise, nil is returned.
         | 
| 364 | 
            -
                #
         | 
| 365 | 
            -
                # ==== Parameters
         | 
| 366 | 
            -
                #
         | 
| 367 | 
            -
                # [message]
         | 
| 368 | 
            -
                #   Optional message to show in the
         | 
| 369 | 
            -
                #   report if this assertion fails.
         | 
| 370 | 
            -
                #
         | 
| 371 | 
            -
                # [kinds]
         | 
| 372 | 
            -
                #   Exception classes that must not be raised by the given block.
         | 
| 373 | 
            -
                #
         | 
| 374 | 
            -
                #   If none are given, then StandardError is assumed (similar to how a
         | 
| 375 | 
            -
                #   plain 'rescue' statement without any arguments catches StandardError).
         | 
| 389 | 
            +
                # @return (see Dfect.E)
         | 
| 376 390 | 
             
                #
         | 
| 377 | 
            -
                #  | 
| 391 | 
            +
                # @param kinds_then_message (see Dfect.E)
         | 
| 378 392 | 
             
                #
         | 
| 379 | 
            -
                # | 
| 393 | 
            +
                # @example no exceptions given
         | 
| 380 394 | 
             
                #
         | 
| 381 395 | 
             
                #   E! { }       # passes
         | 
| 382 396 | 
             
                #   E! { raise } # fails
         | 
| 383 397 | 
             
                #
         | 
| 384 | 
            -
                # | 
| 398 | 
            +
                # @example single exception given
         | 
| 385 399 | 
             
                #
         | 
| 386 | 
            -
                #   E!( | 
| 387 | 
            -
                #   E!( "argument must be invalid" | 
| 400 | 
            +
                #   E!(ArgumentError) { raise ArgumentError } # fails
         | 
| 401 | 
            +
                #   E!(ArgumentError, "argument must be invalid") { raise ArgumentError }
         | 
| 388 402 | 
             
                #
         | 
| 389 | 
            -
                # | 
| 403 | 
            +
                # @example multiple exceptions given
         | 
| 390 404 | 
             
                #
         | 
| 391 | 
            -
                #   E!( | 
| 392 | 
            -
                #   E!( "string must compile" | 
| 405 | 
            +
                #   E!(SyntaxError, NameError) { eval "..." }
         | 
| 406 | 
            +
                #   E!(SyntaxError, NameError, "string must compile") { eval "..." }
         | 
| 393 407 | 
             
                #
         | 
| 394 | 
            -
                def E!  | 
| 395 | 
            -
                  assert_raise :negate,  | 
| 408 | 
            +
                def E! *kinds_then_message, &block
         | 
| 409 | 
            +
                  assert_raise :negate, *kinds_then_message, &block
         | 
| 396 410 | 
             
                end
         | 
| 397 411 |  | 
| 398 412 | 
             
                ##
         | 
| @@ -400,203 +414,306 @@ module Dfect | |
| 400 414 | 
             
                # exceptions is raised when the given block
         | 
| 401 415 | 
             
                # is executed.  Otherwise, returns false.
         | 
| 402 416 | 
             
                #
         | 
| 403 | 
            -
                #  | 
| 417 | 
            +
                # @param [...] kinds_then_message
         | 
| 404 418 | 
             
                #
         | 
| 405 | 
            -
                #  | 
| 406 | 
            -
                #    | 
| 407 | 
            -
                #
         | 
| 408 | 
            -
                # [kinds]
         | 
| 409 | 
            -
                #   Exception classes that must be raised by the given block.
         | 
| 419 | 
            +
                #   Exception classes that must be raised by
         | 
| 420 | 
            +
                #   the given block, optionally followed by
         | 
| 421 | 
            +
                #   a message that is completely ignored.
         | 
| 410 422 | 
             
                #
         | 
| 411 | 
            -
                #   If  | 
| 412 | 
            -
                #    | 
| 423 | 
            +
                #   If no exception classes are given, then
         | 
| 424 | 
            +
                #   StandardError is assumed (similar to
         | 
| 425 | 
            +
                #   how a plain 'rescue' statement without
         | 
| 426 | 
            +
                #   any arguments catches StandardError).
         | 
| 413 427 | 
             
                #
         | 
| 414 | 
            -
                #  | 
| 415 | 
            -
                #
         | 
| 416 | 
            -
                #   # no exceptions specified:
         | 
| 428 | 
            +
                # @example no exceptions given
         | 
| 417 429 | 
             
                #
         | 
| 418 430 | 
             
                #   E? { }       # => false
         | 
| 419 431 | 
             
                #   E? { raise } # => true
         | 
| 420 432 | 
             
                #
         | 
| 421 | 
            -
                # | 
| 433 | 
            +
                # @example single exception given
         | 
| 422 434 | 
             
                #
         | 
| 423 | 
            -
                #   E?( | 
| 435 | 
            +
                #   E?(ArgumentError) { raise ArgumentError } # => true
         | 
| 424 436 | 
             
                #
         | 
| 425 | 
            -
                # | 
| 437 | 
            +
                # @example multiple exceptions given
         | 
| 426 438 | 
             
                #
         | 
| 427 | 
            -
                #   E?( | 
| 439 | 
            +
                #   E?(SyntaxError, NameError) { eval "..." } # => true
         | 
| 440 | 
            +
                #   E!(SyntaxError, NameError, "string must compile") { eval "..." }
         | 
| 428 441 | 
             
                #
         | 
| 429 | 
            -
                def E?  | 
| 430 | 
            -
                  assert_raise :sample,  | 
| 442 | 
            +
                def E? *kinds_then_message, &block
         | 
| 443 | 
            +
                  assert_raise :sample, *kinds_then_message, &block
         | 
| 431 444 | 
             
                end
         | 
| 432 445 |  | 
| 433 446 | 
             
                ##
         | 
| 434 447 | 
             
                # Asserts that the given symbol is thrown
         | 
| 435 448 | 
             
                # when the given block is executed.
         | 
| 436 449 | 
             
                #
         | 
| 437 | 
            -
                #  | 
| 438 | 
            -
                # with the expected symbol,
         | 
| 439 | 
            -
                # then that value is returned.
         | 
| 450 | 
            +
                # @return
         | 
| 440 451 | 
             
                #
         | 
| 441 | 
            -
                #  | 
| 452 | 
            +
                #   If a value is thrown along
         | 
| 453 | 
            +
                #   with the expected symbol,
         | 
| 454 | 
            +
                #   then that value is returned.
         | 
| 442 455 | 
             
                #
         | 
| 443 | 
            -
                #  | 
| 456 | 
            +
                #   Otherwise, nil is returned.
         | 
| 444 457 | 
             
                #
         | 
| 445 | 
            -
                # [ | 
| 446 | 
            -
                #   Optional message to show in the
         | 
| 447 | 
            -
                #   report if this assertion fails.
         | 
| 458 | 
            +
                # @param [Symbol] symbol
         | 
| 448 459 | 
             
                #
         | 
| 449 | 
            -
                # [symbol]
         | 
| 450 460 | 
             
                #   Symbol that must be thrown by the given block.
         | 
| 451 461 | 
             
                #
         | 
| 452 | 
            -
                #  | 
| 462 | 
            +
                # @param message (see Dfect.T)
         | 
| 453 463 | 
             
                #
         | 
| 454 | 
            -
                # | 
| 464 | 
            +
                # @example no message given
         | 
| 455 465 | 
             
                #
         | 
| 456 466 | 
             
                #   C(:foo) { throw :foo, 123 } # passes, => 123
         | 
| 457 467 | 
             
                #   C(:foo) { throw :bar, 456 } # fails,  => 456
         | 
| 458 468 | 
             
                #   C(:foo) { }                 # fails,  => nil
         | 
| 459 469 | 
             
                #
         | 
| 460 | 
            -
                # | 
| 470 | 
            +
                # @example message is given
         | 
| 461 471 | 
             
                #
         | 
| 462 | 
            -
                #   C( ":foo must be thrown" | 
| 472 | 
            +
                #   C(:foo, ":foo must be thrown") { throw :bar, 789 } # fails, => nil
         | 
| 463 473 | 
             
                #
         | 
| 464 | 
            -
                def C  | 
| 465 | 
            -
                  assert_catch :assert,  | 
| 474 | 
            +
                def C symbol, message = nil, &block
         | 
| 475 | 
            +
                  assert_catch :assert, symbol, message, &block
         | 
| 466 476 | 
             
                end
         | 
| 467 477 |  | 
| 468 478 | 
             
                ##
         | 
| 469 479 | 
             
                # Asserts that the given symbol is not
         | 
| 470 480 | 
             
                # thrown when the given block is executed.
         | 
| 471 481 | 
             
                #
         | 
| 472 | 
            -
                #  | 
| 473 | 
            -
                #
         | 
| 474 | 
            -
                # ==== Parameters
         | 
| 482 | 
            +
                # @return nil, always.
         | 
| 475 483 | 
             
                #
         | 
| 476 | 
            -
                # [ | 
| 477 | 
            -
                #   Optional message to show in the
         | 
| 478 | 
            -
                #   report if this assertion fails.
         | 
| 484 | 
            +
                # @param [Symbol] symbol
         | 
| 479 485 | 
             
                #
         | 
| 480 | 
            -
                # [symbol]
         | 
| 481 486 | 
             
                #   Symbol that must not be thrown by the given block.
         | 
| 482 487 | 
             
                #
         | 
| 483 | 
            -
                #  | 
| 488 | 
            +
                # @param message (see Dfect.T)
         | 
| 484 489 | 
             
                #
         | 
| 485 | 
            -
                # | 
| 490 | 
            +
                # @example no message given
         | 
| 486 491 | 
             
                #
         | 
| 487 492 | 
             
                #   C!(:foo) { throw :foo, 123 } # fails,  => nil
         | 
| 488 493 | 
             
                #   C!(:foo) { throw :bar, 456 } # passes, => nil
         | 
| 489 494 | 
             
                #   C!(:foo) { }                 # passes, => nil
         | 
| 490 495 | 
             
                #
         | 
| 491 | 
            -
                # | 
| 496 | 
            +
                # @example message is given
         | 
| 492 497 | 
             
                #
         | 
| 493 | 
            -
                #   C!( ":foo must be thrown" | 
| 498 | 
            +
                #   C!(:foo, ":foo must be thrown") { throw :bar, 789 } # passes, => nil
         | 
| 494 499 | 
             
                #
         | 
| 495 | 
            -
                def C!  | 
| 496 | 
            -
                  assert_catch :negate,  | 
| 500 | 
            +
                def C! symbol, message = nil, &block
         | 
| 501 | 
            +
                  assert_catch :negate, symbol, message, &block
         | 
| 497 502 | 
             
                end
         | 
| 498 503 |  | 
| 499 504 | 
             
                ##
         | 
| 500 505 | 
             
                # Returns true if the given symbol is thrown when the
         | 
| 501 506 | 
             
                # given block is executed.  Otherwise, returns false.
         | 
| 502 507 | 
             
                #
         | 
| 503 | 
            -
                #  | 
| 508 | 
            +
                # @param symbol (see Dfect.C)
         | 
| 504 509 | 
             
                #
         | 
| 505 | 
            -
                #  | 
| 506 | 
            -
                #   This parameter is optional and completely ignored.
         | 
| 507 | 
            -
                #
         | 
| 508 | 
            -
                # [symbol]
         | 
| 509 | 
            -
                #   Symbol that must be thrown by the given block.
         | 
| 510 | 
            -
                #
         | 
| 511 | 
            -
                # ==== Examples
         | 
| 510 | 
            +
                # @param message (see Dfect.T?)
         | 
| 512 511 | 
             
                #
         | 
| 513 | 
            -
                # | 
| 512 | 
            +
                # @example no message given
         | 
| 514 513 | 
             
                #
         | 
| 515 514 | 
             
                #   C?(:foo) { throw :foo, 123 } # => true
         | 
| 516 515 | 
             
                #   C?(:foo) { throw :bar, 456 } # => false
         | 
| 517 516 | 
             
                #   C?(:foo) { }                 # => false
         | 
| 518 517 | 
             
                #
         | 
| 519 | 
            -
                # | 
| 518 | 
            +
                # @example message is given
         | 
| 520 519 | 
             
                #
         | 
| 521 | 
            -
                #   C?( ":foo must be thrown" | 
| 520 | 
            +
                #   C?(:foo, ":foo must be thrown") { throw :bar, 789 } # => false
         | 
| 522 521 | 
             
                #
         | 
| 523 | 
            -
                def C?  | 
| 524 | 
            -
                  assert_catch :sample,  | 
| 522 | 
            +
                def C? symbol, message = nil, &block
         | 
| 523 | 
            +
                  assert_catch :sample, symbol, message, &block
         | 
| 525 524 | 
             
                end
         | 
| 526 525 |  | 
| 527 526 | 
             
                ##
         | 
| 528 | 
            -
                # Adds the given  | 
| 527 | 
            +
                # Adds the given messages to the report inside
         | 
| 529 528 | 
             
                # the section of the currently running test.
         | 
| 530 529 | 
             
                #
         | 
| 531 | 
            -
                # You can think of " | 
| 530 | 
            +
                # You can think of "L" as "to log something".
         | 
| 532 531 | 
             
                #
         | 
| 533 | 
            -
                #  | 
| 532 | 
            +
                # @param messages
         | 
| 534 533 | 
             
                #
         | 
| 535 | 
            -
                # [message]
         | 
| 536 534 | 
             
                #   Objects to be added to the report.
         | 
| 537 535 | 
             
                #
         | 
| 538 | 
            -
                #  | 
| 536 | 
            +
                # @example single message given
         | 
| 537 | 
            +
                #
         | 
| 538 | 
            +
                #   L "establishing connection..."
         | 
| 539 | 
            +
                #
         | 
| 540 | 
            +
                # @example multiple messages given
         | 
| 541 | 
            +
                #
         | 
| 542 | 
            +
                #   L "beginning calculation...", Math::PI, [1, 2, 3, ['a', 'b', 'c']]
         | 
| 543 | 
            +
                #
         | 
| 544 | 
            +
                def L *messages
         | 
| 545 | 
            +
                  @trace.concat messages
         | 
| 546 | 
            +
                end
         | 
| 547 | 
            +
             | 
| 548 | 
            +
                ##
         | 
| 549 | 
            +
                # Mechanism for sharing code between tests.
         | 
| 550 | 
            +
                #
         | 
| 551 | 
            +
                # If a block is given, it is shared under
         | 
| 552 | 
            +
                # the given identifier.  Otherwise, the
         | 
| 553 | 
            +
                # code block that was previously shared
         | 
| 554 | 
            +
                # under the given identifier is injected
         | 
| 555 | 
            +
                # into the closest insulated Dfect test
         | 
| 556 | 
            +
                # that contains the call to this method.
         | 
| 557 | 
            +
                #
         | 
| 558 | 
            +
                # @param [Symbol, Object] identifier
         | 
| 559 | 
            +
                #
         | 
| 560 | 
            +
                #   An object that identifies shared code.  This must be common
         | 
| 561 | 
            +
                #   knowledge to all parties that want to partake in the sharing.
         | 
| 562 | 
            +
                #
         | 
| 563 | 
            +
                # @example
         | 
| 564 | 
            +
                #
         | 
| 565 | 
            +
                #   S :knowledge do
         | 
| 566 | 
            +
                #     #...
         | 
| 567 | 
            +
                #   end
         | 
| 539 568 | 
             
                #
         | 
| 540 | 
            -
                #    | 
| 569 | 
            +
                #   D "some test" do
         | 
| 570 | 
            +
                #     S :knowledge
         | 
| 571 | 
            +
                #   end
         | 
| 541 572 | 
             
                #
         | 
| 542 | 
            -
                #    | 
| 573 | 
            +
                #   D "another test" do
         | 
| 574 | 
            +
                #     S :knowledge
         | 
| 575 | 
            +
                #   end
         | 
| 543 576 | 
             
                #
         | 
| 544 | 
            -
                def S  | 
| 545 | 
            -
                   | 
| 577 | 
            +
                def S identifier, &block
         | 
| 578 | 
            +
                  if block_given?
         | 
| 579 | 
            +
                    if already_shared = @share[identifier]
         | 
| 580 | 
            +
                      raise ArgumentError, "A code block #{already_shared.inspect} has already been shared under the identifier #{identifier.inspect}."
         | 
| 581 | 
            +
                    end
         | 
| 582 | 
            +
             | 
| 583 | 
            +
                    @share[identifier] = block
         | 
| 584 | 
            +
             | 
| 585 | 
            +
                  elsif block = @share[identifier]
         | 
| 586 | 
            +
                    if @tests.empty?
         | 
| 587 | 
            +
                      raise "Cannot inject code block #{block.inspect} shared under identifier #{identifier.inspect} outside of a Dfect test."
         | 
| 588 | 
            +
                    else
         | 
| 589 | 
            +
                      # find the closest insulated parent test; this should always
         | 
| 590 | 
            +
                      # succeed because root-level tests are insulated by default
         | 
| 591 | 
            +
                      test = @tests.reverse.find {|t| t.sandbox }
         | 
| 592 | 
            +
                      test.sandbox.instance_eval(&block)
         | 
| 593 | 
            +
                    end
         | 
| 594 | 
            +
             | 
| 595 | 
            +
                  else
         | 
| 596 | 
            +
                    raise ArgumentError, "No code block is shared under identifier #{identifier.inspect}."
         | 
| 597 | 
            +
                  end
         | 
| 546 598 | 
             
                end
         | 
| 547 599 |  | 
| 548 600 | 
             
                ##
         | 
| 549 | 
            -
                #  | 
| 601 | 
            +
                # Shares the given code block under the given
         | 
| 602 | 
            +
                # identifier and then immediately injects that
         | 
| 603 | 
            +
                # code block into the closest insulated Dfect
         | 
| 604 | 
            +
                # test that contains the call to this method.
         | 
| 605 | 
            +
                #
         | 
| 606 | 
            +
                # @param identifier (see Dfect.S)
         | 
| 607 | 
            +
                #
         | 
| 608 | 
            +
                # @example
         | 
| 550 609 | 
             
                #
         | 
| 551 | 
            -
                #  | 
| 610 | 
            +
                #   D "some test" do
         | 
| 611 | 
            +
                #     S! :knowledge do
         | 
| 612 | 
            +
                #       #...
         | 
| 613 | 
            +
                #     end
         | 
| 614 | 
            +
                #   end
         | 
| 615 | 
            +
                #
         | 
| 616 | 
            +
                #   D "another test" do
         | 
| 617 | 
            +
                #     S :knowledge
         | 
| 618 | 
            +
                #   end
         | 
| 619 | 
            +
                #
         | 
| 620 | 
            +
                def S! identifier, &block
         | 
| 621 | 
            +
                  raise 'block must be given' unless block_given?
         | 
| 622 | 
            +
                  S identifier, &block
         | 
| 623 | 
            +
                  S identifier
         | 
| 624 | 
            +
                end
         | 
| 625 | 
            +
             | 
| 626 | 
            +
                ##
         | 
| 627 | 
            +
                # Checks whether any code has been shared under the given identifier.
         | 
| 628 | 
            +
                #
         | 
| 629 | 
            +
                def S? identifier
         | 
| 630 | 
            +
                  @share.key? identifier
         | 
| 631 | 
            +
                end
         | 
| 632 | 
            +
             | 
| 633 | 
            +
                ##
         | 
| 634 | 
            +
                # Executes all tests defined thus far and
         | 
| 635 | 
            +
                # stores the results in {Dfect.report}.
         | 
| 636 | 
            +
                #
         | 
| 637 | 
            +
                # @param [Boolean] continue
         | 
| 552 638 | 
             
                #
         | 
| 553 | 
            -
                # [continue]
         | 
| 554 639 | 
             
                #   If true, results from previous executions will not be cleared.
         | 
| 555 640 | 
             
                #
         | 
| 556 641 | 
             
                def run continue = true
         | 
| 557 642 | 
             
                  # clear previous results
         | 
| 558 643 | 
             
                  unless continue
         | 
| 559 | 
            -
                    @ | 
| 560 | 
            -
                    @ | 
| 561 | 
            -
                    @ | 
| 644 | 
            +
                    @stats.clear
         | 
| 645 | 
            +
                    @trace.clear
         | 
| 646 | 
            +
                    @tests.clear
         | 
| 562 647 | 
             
                  end
         | 
| 563 648 |  | 
| 564 649 | 
             
                  # make new results
         | 
| 650 | 
            +
                  start = Time.now
         | 
| 565 651 | 
             
                  catch(:stop_dfect_execution) { execute }
         | 
| 652 | 
            +
                  finish = Time.now
         | 
| 653 | 
            +
                  @stats[:time] = finish - start
         | 
| 566 654 |  | 
| 567 655 | 
             
                  # print new results
         | 
| 568 | 
            -
                   | 
| 656 | 
            +
                  unless @stats.key? :fail or @stats.key? :error
         | 
| 657 | 
            +
                    #
         | 
| 658 | 
            +
                    # show execution trace only if all tests passed.
         | 
| 659 | 
            +
                    # otherwise, we will be repeating already printed
         | 
| 660 | 
            +
                    # failure details and obstructing the developer!
         | 
| 661 | 
            +
                    #
         | 
| 662 | 
            +
                    display @trace
         | 
| 663 | 
            +
                  end
         | 
| 664 | 
            +
             | 
| 665 | 
            +
                  display @stats
         | 
| 569 666 | 
             
                end
         | 
| 570 667 |  | 
| 571 668 | 
             
                ##
         | 
| 572 | 
            -
                # Stops the execution of the  | 
| 573 | 
            -
                # exception if that method is not currently executing.
         | 
| 669 | 
            +
                # Stops the execution of the {Dfect.run} method or raises
         | 
| 670 | 
            +
                # an exception if that method is not currently executing.
         | 
| 574 671 | 
             
                #
         | 
| 575 672 | 
             
                def stop
         | 
| 576 673 | 
             
                  throw :stop_dfect_execution
         | 
| 577 674 | 
             
                end
         | 
| 578 675 |  | 
| 676 | 
            +
                ##
         | 
| 677 | 
            +
                # Returns the details of the failure that
         | 
| 678 | 
            +
                # is currently being debugged by the user.
         | 
| 679 | 
            +
                #
         | 
| 680 | 
            +
                def info
         | 
| 681 | 
            +
                  @trace.last
         | 
| 682 | 
            +
                end
         | 
| 683 | 
            +
             | 
| 579 684 | 
             
                private
         | 
| 580 685 |  | 
| 581 | 
            -
                def  | 
| 686 | 
            +
                def create_test insulate, *description, &block
         | 
| 582 687 | 
             
                  raise ArgumentError, 'block must be given' unless block
         | 
| 583 688 |  | 
| 584 | 
            -
                   | 
| 689 | 
            +
                  description = description.join(' ')
         | 
| 690 | 
            +
                  sandbox = Object.new if insulate
         | 
| 691 | 
            +
             | 
| 692 | 
            +
                  @suite.tests << Suite::Test.new(description, block, sandbox)
         | 
| 693 | 
            +
                end
         | 
| 694 | 
            +
             | 
| 695 | 
            +
                def assert_yield mode, condition = nil, message = nil, &block
         | 
| 696 | 
            +
                  # first parameter is actually the message when block is given
         | 
| 697 | 
            +
                  message = condition if block
         | 
| 698 | 
            +
             | 
| 699 | 
            +
                  message ||= (
         | 
| 700 | 
            +
                    prefix = block ? 'block must yield' : 'condition must be'
         | 
| 585 701 | 
             
                    case mode
         | 
| 586 | 
            -
                    when :assert then  | 
| 587 | 
            -
                    when :negate then  | 
| 702 | 
            +
                    when :assert then "#{prefix} true (!nil && !false)"
         | 
| 703 | 
            +
                    when :negate then "#{prefix} false (nil || false)"
         | 
| 588 704 | 
             
                    end
         | 
| 705 | 
            +
                  )
         | 
| 589 706 |  | 
| 590 707 | 
             
                  passed = lambda do
         | 
| 591 | 
            -
                    @ | 
| 708 | 
            +
                    @stats[:pass] += 1
         | 
| 592 709 | 
             
                  end
         | 
| 593 710 |  | 
| 594 711 | 
             
                  failed = lambda do
         | 
| 595 | 
            -
                    @ | 
| 712 | 
            +
                    @stats[:fail] += 1
         | 
| 596 713 | 
             
                    debug block, message
         | 
| 597 714 | 
             
                  end
         | 
| 598 715 |  | 
| 599 | 
            -
                  result = call(block)
         | 
| 716 | 
            +
                  result = block ? call(block) : condition
         | 
| 600 717 |  | 
| 601 718 | 
             
                  case mode
         | 
| 602 719 | 
             
                  when :sample then return result ? true : false
         | 
| @@ -607,11 +724,14 @@ module Dfect | |
| 607 724 | 
             
                  result
         | 
| 608 725 | 
             
                end
         | 
| 609 726 |  | 
| 610 | 
            -
                def assert_raise mode,  | 
| 727 | 
            +
                def assert_raise mode, *kinds_then_message, &block
         | 
| 611 728 | 
             
                  raise ArgumentError, 'block must be given' unless block
         | 
| 612 729 |  | 
| 613 | 
            -
                   | 
| 614 | 
            -
             | 
| 730 | 
            +
                  message = kinds_then_message.pop
         | 
| 731 | 
            +
                  kinds = kinds_then_message
         | 
| 732 | 
            +
             | 
| 733 | 
            +
                  if message.kind_of? Class
         | 
| 734 | 
            +
                    kinds << message
         | 
| 615 735 | 
             
                    message = nil
         | 
| 616 736 | 
             
                  end
         | 
| 617 737 |  | 
| @@ -624,11 +744,11 @@ module Dfect | |
| 624 744 | 
             
                    end
         | 
| 625 745 |  | 
| 626 746 | 
             
                  passed = lambda do
         | 
| 627 | 
            -
                    @ | 
| 747 | 
            +
                    @stats[:pass] += 1
         | 
| 628 748 | 
             
                  end
         | 
| 629 749 |  | 
| 630 750 | 
             
                  failed = lambda do |exception|
         | 
| 631 | 
            -
                    @ | 
| 751 | 
            +
                    @stats[:fail] += 1
         | 
| 632 752 |  | 
| 633 753 | 
             
                    if exception
         | 
| 634 754 | 
             
                      # debug the uncaught exception...
         | 
| @@ -665,25 +785,18 @@ module Dfect | |
| 665 785 | 
             
                  exception
         | 
| 666 786 | 
             
                end
         | 
| 667 787 |  | 
| 668 | 
            -
                def assert_catch mode,  | 
| 788 | 
            +
                def assert_catch mode, symbol, message = nil, &block
         | 
| 669 789 | 
             
                  raise ArgumentError, 'block must be given' unless block
         | 
| 670 790 |  | 
| 671 | 
            -
                  if message.is_a? Symbol and not symbol
         | 
| 672 | 
            -
                    symbol  = message
         | 
| 673 | 
            -
                    message = nil
         | 
| 674 | 
            -
                  end
         | 
| 675 | 
            -
             | 
| 676 | 
            -
                  raise ArgumentError, 'symbol must be given' unless symbol
         | 
| 677 | 
            -
             | 
| 678 791 | 
             
                  symbol = symbol.to_sym
         | 
| 679 792 | 
             
                  message ||= "block must throw #{symbol.inspect}"
         | 
| 680 793 |  | 
| 681 794 | 
             
                  passed = lambda do
         | 
| 682 | 
            -
                    @ | 
| 795 | 
            +
                    @stats[:pass] += 1
         | 
| 683 796 | 
             
                  end
         | 
| 684 797 |  | 
| 685 798 | 
             
                  failed = lambda do
         | 
| 686 | 
            -
                    @ | 
| 799 | 
            +
                    @stats[:fail] += 1
         | 
| 687 800 | 
             
                    debug block, message
         | 
| 688 801 | 
             
                  end
         | 
| 689 802 |  | 
| @@ -718,40 +831,50 @@ module Dfect | |
| 718 831 | 
             
                  result
         | 
| 719 832 | 
             
                end
         | 
| 720 833 |  | 
| 834 | 
            +
                ##
         | 
| 835 | 
            +
                # Prints the given object in YAML format.
         | 
| 836 | 
            +
                #
         | 
| 837 | 
            +
                def display object
         | 
| 838 | 
            +
                  unless @options[:quiet]
         | 
| 839 | 
            +
                    # stringify symbols in YAML output for better readability
         | 
| 840 | 
            +
                    puts object.to_yaml.gsub(/^([[:blank:]]*(- )?):(?=@?\w+: )/, '\1')
         | 
| 841 | 
            +
                  end
         | 
| 842 | 
            +
                end
         | 
| 843 | 
            +
             | 
| 721 844 | 
             
                ##
         | 
| 722 845 | 
             
                # Executes the current test suite recursively.
         | 
| 723 846 | 
             
                #
         | 
| 724 847 | 
             
                def execute
         | 
| 725 | 
            -
                  suite = @ | 
| 726 | 
            -
                  trace = @ | 
| 848 | 
            +
                  suite = @suite
         | 
| 849 | 
            +
                  trace = @trace
         | 
| 727 850 |  | 
| 728 851 | 
             
                  suite.before_all.each {|b| call b }
         | 
| 729 852 |  | 
| 730 853 | 
             
                  suite.tests.each do |test|
         | 
| 731 854 | 
             
                    suite.before_each.each {|b| call b }
         | 
| 732 855 |  | 
| 733 | 
            -
                    @ | 
| 856 | 
            +
                    @tests.push test
         | 
| 734 857 |  | 
| 735 858 | 
             
                    begin
         | 
| 736 859 | 
             
                      # create nested suite
         | 
| 737 | 
            -
                      @ | 
| 738 | 
            -
                      @ | 
| 860 | 
            +
                      @suite = Suite.new
         | 
| 861 | 
            +
                      @trace = []
         | 
| 739 862 |  | 
| 740 863 | 
             
                      # populate nested suite
         | 
| 741 | 
            -
                      call test.block
         | 
| 864 | 
            +
                      call test.block, test.sandbox
         | 
| 742 865 |  | 
| 743 866 | 
             
                      # execute nested suite
         | 
| 744 867 | 
             
                      execute
         | 
| 745 868 |  | 
| 746 869 | 
             
                    ensure
         | 
| 747 870 | 
             
                      # restore outer values
         | 
| 748 | 
            -
                      @ | 
| 871 | 
            +
                      @suite = suite
         | 
| 749 872 |  | 
| 750 | 
            -
                      trace <<  | 
| 751 | 
            -
                      @ | 
| 873 | 
            +
                      trace << build_exec_trace(@trace)
         | 
| 874 | 
            +
                      @trace = trace
         | 
| 752 875 | 
             
                    end
         | 
| 753 876 |  | 
| 754 | 
            -
                    @ | 
| 877 | 
            +
                    @tests.pop
         | 
| 755 878 |  | 
| 756 879 | 
             
                    suite.after_each.each {|b| call b }
         | 
| 757 880 | 
             
                  end
         | 
| @@ -763,36 +886,51 @@ module Dfect | |
| 763 886 | 
             
                # Invokes the given block and debugs any
         | 
| 764 887 | 
             
                # exceptions that may arise as a result.
         | 
| 765 888 | 
             
                #
         | 
| 766 | 
            -
                def call block
         | 
| 889 | 
            +
                def call block, sandbox = nil
         | 
| 767 890 | 
             
                  begin
         | 
| 768 | 
            -
                    block | 
| 891 | 
            +
                    @calls.push block
         | 
| 892 | 
            +
             | 
| 893 | 
            +
                    if sandbox
         | 
| 894 | 
            +
                      sandbox.instance_eval(&block)
         | 
| 895 | 
            +
                    else
         | 
| 896 | 
            +
                      block.call
         | 
| 897 | 
            +
                    end
         | 
| 898 | 
            +
             | 
| 769 899 | 
             
                  rescue Exception => e
         | 
| 770 900 | 
             
                    debug_uncaught_exception block, e
         | 
| 901 | 
            +
             | 
| 902 | 
            +
                  ensure
         | 
| 903 | 
            +
                    @calls.pop
         | 
| 771 904 | 
             
                  end
         | 
| 772 905 | 
             
                end
         | 
| 773 906 |  | 
| 774 | 
            -
                INTERNALS = File.dirname(__FILE__)  | 
| 907 | 
            +
                INTERNALS = File.dirname(__FILE__) # @private
         | 
| 775 908 |  | 
| 776 909 | 
             
                ##
         | 
| 777 910 | 
             
                # Adds debugging information to the report.
         | 
| 778 911 | 
             
                #
         | 
| 779 | 
            -
                #  | 
| 912 | 
            +
                # @param [Binding, Proc, #binding] context
         | 
| 913 | 
            +
                #
         | 
| 914 | 
            +
                #   Binding of code being debugged.  This can be either a Binding or
         | 
| 915 | 
            +
                #   Proc object, or nil if no binding is available---in which case,
         | 
| 916 | 
            +
                #   the binding of the inner-most enclosing test or hook will be used.
         | 
| 780 917 | 
             
                #
         | 
| 781 | 
            -
                #  | 
| 782 | 
            -
                #   Binding of code being debugged.  This
         | 
| 783 | 
            -
                #   can be either a Binding or Proc object.
         | 
| 918 | 
            +
                # @param message
         | 
| 784 919 | 
             
                #
         | 
| 785 | 
            -
                # [message]
         | 
| 786 920 | 
             
                #   Message describing the failure
         | 
| 787 921 | 
             
                #   in the code being debugged.
         | 
| 788 922 | 
             
                #
         | 
| 789 | 
            -
                # [backtrace | 
| 923 | 
            +
                # @param [Array<String>] backtrace
         | 
| 924 | 
            +
                #
         | 
| 790 925 | 
             
                #   Stack trace corresponding to point of
         | 
| 791 926 | 
             
                #   failure in the code being debugged.
         | 
| 792 927 | 
             
                #
         | 
| 793 928 | 
             
                def debug context, message = nil, backtrace = caller
         | 
| 929 | 
            +
                  # inherit binding of enclosing test or hook
         | 
| 930 | 
            +
                  context ||= @calls.last
         | 
| 931 | 
            +
             | 
| 794 932 | 
             
                  # allow a Proc to be passed instead of a binding
         | 
| 795 | 
            -
                  if context.respond_to? :binding
         | 
| 933 | 
            +
                  if context and context.respond_to? :binding
         | 
| 796 934 | 
             
                    context = context.binding
         | 
| 797 935 | 
             
                  end
         | 
| 798 936 |  | 
| @@ -800,21 +938,16 @@ module Dfect | |
| 800 938 | 
             
                  backtrace = backtrace.reject {|s| s.include? INTERNALS }
         | 
| 801 939 |  | 
| 802 940 | 
             
                  # record failure details in the report
         | 
| 803 | 
            -
                  #
         | 
| 804 | 
            -
                  # NOTE: using string keys here instead
         | 
| 805 | 
            -
                  #       of symbols because they make
         | 
| 806 | 
            -
                  #       the YAML output easier to read
         | 
| 807 | 
            -
                  #
         | 
| 808 941 | 
             
                  details = {
         | 
| 809 942 | 
             
                    # user message
         | 
| 810 | 
            -
                     | 
| 943 | 
            +
                    :fail => message,
         | 
| 811 944 |  | 
| 812 945 | 
             
                    # code snippet
         | 
| 813 | 
            -
                     | 
| 946 | 
            +
                    :code => (
         | 
| 814 947 | 
             
                      if frame = backtrace.first
         | 
| 815 948 | 
             
                        file, line = frame.scan(/(.+?):(\d+(?=:|\z))/).first
         | 
| 816 949 |  | 
| 817 | 
            -
                        if source = @ | 
| 950 | 
            +
                        if source = @files[file]
         | 
| 818 951 | 
             
                          line = line.to_i
         | 
| 819 952 |  | 
| 820 953 | 
             
                          radius = 5 # number of surrounding lines to show
         | 
| @@ -838,31 +971,35 @@ module Dfect | |
| 838 971 | 
             
                    ),
         | 
| 839 972 |  | 
| 840 973 | 
             
                    # variable values
         | 
| 841 | 
            -
                     | 
| 842 | 
            -
                      names = eval('::Kernel.local_variables', context, __FILE__, __LINE__)
         | 
| 974 | 
            +
                    :vars => if context
         | 
| 975 | 
            +
                      names = eval('::Kernel.local_variables + self.instance_variables', context, __FILE__, __LINE__)
         | 
| 843 976 |  | 
| 844 977 | 
             
                      pairs = names.inject([]) do |pair, name|
         | 
| 845 978 | 
             
                        variable = name.to_s
         | 
| 846 979 | 
             
                        value    = eval(variable, context, __FILE__, __LINE__)
         | 
| 847 980 |  | 
| 848 | 
            -
                        pair.push variable, value
         | 
| 981 | 
            +
                        pair.push variable.to_sym, value
         | 
| 849 982 | 
             
                      end
         | 
| 850 983 |  | 
| 851 984 | 
             
                      Hash[*pairs]
         | 
| 852 | 
            -
                     | 
| 985 | 
            +
                    end,
         | 
| 853 986 |  | 
| 854 987 | 
             
                    # stack trace
         | 
| 855 | 
            -
                     | 
| 988 | 
            +
                    :call => backtrace,
         | 
| 856 989 | 
             
                  }
         | 
| 857 990 |  | 
| 858 | 
            -
                  @ | 
| 991 | 
            +
                  @trace << details
         | 
| 859 992 |  | 
| 860 993 | 
             
                  # allow user to investigate the failure
         | 
| 861 | 
            -
                  if @options[:debug]
         | 
| 862 | 
            -
                    # show the  | 
| 863 | 
            -
                     | 
| 994 | 
            +
                  if @options[:debug] and context
         | 
| 995 | 
            +
                    # show only the most helpful subset of the
         | 
| 996 | 
            +
                    # failure details, because the rest can be
         | 
| 997 | 
            +
                    # queried (on demand) inside the debugger
         | 
| 998 | 
            +
                    overview = details.dup
         | 
| 999 | 
            +
                    overview.delete :vars
         | 
| 1000 | 
            +
                    overview.delete :call
         | 
| 1001 | 
            +
                    display build_fail_trace(overview)
         | 
| 864 1002 |  | 
| 865 | 
            -
                    # start the investigation
         | 
| 866 1003 | 
             
                    if Kernel.respond_to? :debugger
         | 
| 867 1004 | 
             
                      eval '::Kernel.debugger', context, __FILE__, __LINE__
         | 
| 868 1005 | 
             
                    else
         | 
| @@ -876,6 +1013,9 @@ module Dfect | |
| 876 1013 | 
             
                        irb.eval_input
         | 
| 877 1014 | 
             
                      end
         | 
| 878 1015 | 
             
                    end
         | 
| 1016 | 
            +
                  else
         | 
| 1017 | 
            +
                    # show all failure details to the user
         | 
| 1018 | 
            +
                    display build_fail_trace(details)
         | 
| 879 1019 | 
             
                  end
         | 
| 880 1020 |  | 
| 881 1021 | 
             
                  nil
         | 
| @@ -885,7 +1025,7 @@ module Dfect | |
| 885 1025 | 
             
                # Debugs the given uncaught exception inside the given context.
         | 
| 886 1026 | 
             
                #
         | 
| 887 1027 | 
             
                def debug_uncaught_exception context, exception
         | 
| 888 | 
            -
                  @ | 
| 1028 | 
            +
                  @stats[:error] += 1
         | 
| 889 1029 | 
             
                  debug context, exception, exception.backtrace
         | 
| 890 1030 | 
             
                end
         | 
| 891 1031 |  | 
| @@ -893,17 +1033,25 @@ module Dfect | |
| 893 1033 | 
             
                # Returns a report that associates the given
         | 
| 894 1034 | 
             
                # failure details with the currently running test.
         | 
| 895 1035 | 
             
                #
         | 
| 896 | 
            -
                def  | 
| 897 | 
            -
                  if @ | 
| 1036 | 
            +
                def build_exec_trace details
         | 
| 1037 | 
            +
                  if @tests.empty?
         | 
| 898 1038 | 
             
                    details
         | 
| 899 1039 | 
             
                  else
         | 
| 900 | 
            -
                    { @ | 
| 1040 | 
            +
                    { @tests.last.desc => details }
         | 
| 901 1041 | 
             
                  end
         | 
| 902 1042 | 
             
                end
         | 
| 903 1043 |  | 
| 904 | 
            -
                 | 
| 1044 | 
            +
                ##
         | 
| 1045 | 
            +
                # Returns a report that qualifies the given
         | 
| 1046 | 
            +
                # failure details with the current test stack.
         | 
| 1047 | 
            +
                #
         | 
| 1048 | 
            +
                def build_fail_trace details
         | 
| 1049 | 
            +
                  @tests.reverse.inject(details) do |inner, outer|
         | 
| 1050 | 
            +
                    { outer.desc => inner }
         | 
| 1051 | 
            +
                  end
         | 
| 1052 | 
            +
                end
         | 
| 905 1053 |  | 
| 906 | 
            -
                class Suite
         | 
| 1054 | 
            +
                class Suite # @private
         | 
| 907 1055 | 
             
                  attr_reader :tests, :before_each, :after_each, :before_all, :after_all
         | 
| 908 1056 |  | 
| 909 1057 | 
             
                  def initialize
         | 
| @@ -914,26 +1062,25 @@ module Dfect | |
| 914 1062 | 
             
                    @after_all   = []
         | 
| 915 1063 | 
             
                  end
         | 
| 916 1064 |  | 
| 917 | 
            -
                  Test = Struct.new | 
| 1065 | 
            +
                  Test = Struct.new(:desc, :block, :sandbox) # @private
         | 
| 918 1066 | 
             
                end
         | 
| 919 | 
            -
             | 
| 920 | 
            -
                #:startdoc:
         | 
| 921 1067 | 
             
              end
         | 
| 922 1068 |  | 
| 923 | 
            -
              @options | 
| 924 | 
            -
             | 
| 925 | 
            -
              @exec_stats = Hash.new {|h,k| h[k] = 0 }
         | 
| 926 | 
            -
              @exec_trace = []
         | 
| 927 | 
            -
              @report     = {:execution => @exec_trace, :statistics => @exec_stats}.freeze
         | 
| 1069 | 
            +
              @options = {:debug => $DEBUG, :quiet => false}
         | 
| 928 1070 |  | 
| 929 | 
            -
              @ | 
| 1071 | 
            +
              @stats  = Hash.new {|h,k| h[k] = 0 }
         | 
| 1072 | 
            +
              @trace  = []
         | 
| 1073 | 
            +
              @report = {:trace => @trace, :stats => @stats}.freeze
         | 
| 930 1074 |  | 
| 931 | 
            -
              @ | 
| 932 | 
            -
              @ | 
| 1075 | 
            +
              @suite = class << self; Suite.new; end
         | 
| 1076 | 
            +
              @share = {}
         | 
| 1077 | 
            +
              @tests = []
         | 
| 1078 | 
            +
              @calls = []
         | 
| 1079 | 
            +
              @files = Hash.new {|h,k| h[k] = File.readlines(k) rescue nil }
         | 
| 933 1080 |  | 
| 934 1081 | 
             
              ##
         | 
| 935 | 
            -
              # Allows before and after hooks to be specified via
         | 
| 936 | 
            -
              #  | 
| 1082 | 
            +
              # Allows before and after hooks to be specified via the
         | 
| 1083 | 
            +
              # following method syntax when this module is mixed-in:
         | 
| 937 1084 | 
             
              #
         | 
| 938 1085 | 
             
              #   D .<< { puts "before all nested tests" }
         | 
| 939 1086 | 
             
              #   D .<  { puts "before each nested test" }
         | 
| @@ -943,11 +1090,11 @@ module Dfect | |
| 943 1090 | 
             
              D = self
         | 
| 944 1091 |  | 
| 945 1092 | 
             
              # provide mixin-able assertion methods
         | 
| 946 | 
            -
              methods(false).grep(/^[[:upper:]][[:punct:]] | 
| 1093 | 
            +
              methods(false).grep(/^[[:upper:]]?[[:punct:]]*$/).each do |name|
         | 
| 947 1094 | 
             
                #
         | 
| 948 1095 | 
             
                # XXX: using eval() on a string because Ruby 1.8's
         | 
| 949 1096 | 
             
                #      define_method() cannot take a block parameter
         | 
| 950 1097 | 
             
                #
         | 
| 951 | 
            -
                 | 
| 1098 | 
            +
                module_eval "def #{name}(*a, &b) ::#{self.name}.#{name}(*a, &b) end", __FILE__, __LINE__
         | 
| 952 1099 | 
             
              end
         | 
| 953 1100 | 
             
            end
         |