oktest 1.0.2 → 1.2.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.
- checksums.yaml +5 -5
- data/README.md +460 -51
- data/Rakefile.rb +5 -2
- data/benchmark/Rakefile.rb +4 -0
- data/lib/oktest.rb +557 -74
- data/oktest.gemspec +3 -3
- data/test/assertion_test.rb +70 -5
- data/test/filter_test.rb +2 -2
- data/test/fixture_test.rb +14 -1
- data/test/generator_test.rb +1 -1
- data/test/helper_test.rb +7 -7
- data/test/initialize.rb +8 -1
- data/test/mainapp_test.rb +95 -42
- data/test/matcher_test.rb +424 -0
- data/test/misc_test.rb +5 -5
- data/test/node_test.rb +27 -4
- data/test/reporter_test.rb +87 -29
- data/test/runner_test.rb +97 -25
- data/test/tc.rb +12 -0
- data/test/util_test.rb +71 -1
- data/test/utilhelper_test.rb +84 -0
- data/test/visitor_test.rb +1 -1
- metadata +9 -8
    
        data/README.md
    CHANGED
    
    | @@ -4,12 +4,13 @@ | |
| 4 4 |  | 
| 5 5 | 
             
            Oktest.rb is a new-style testing library for Ruby.
         | 
| 6 6 |  | 
| 7 | 
            -
            * `ok {actual} == expected` style assertion.
         | 
| 8 | 
            -
            *  | 
| 7 | 
            +
            * `ok {actual} == expected` style [assertion](#assertions).
         | 
| 8 | 
            +
            * [Fixture injection](#fixture-injection) inspired by dependency injection.
         | 
| 9 9 | 
             
            * Structured test specifications like RSpec.
         | 
| 10 | 
            -
            *  | 
| 10 | 
            +
            * [JSON Matcher](#json-matcher) similar to JSON Schema.
         | 
| 11 | 
            +
            * [Filtering](#tag-and-filtering) testcases by pattern or tags.
         | 
| 11 12 | 
             
            * Blue/red color instead of green/red for accesability.
         | 
| 12 | 
            -
            * Small code size ( | 
| 13 | 
            +
            * Small code size (less than 3000 lines) and good performance.
         | 
| 13 14 |  | 
| 14 15 | 
             
            ```ruby
         | 
| 15 16 | 
             
            ### Oktest                           ### Test::Unit
         | 
| @@ -42,7 +43,7 @@ Oktest.scope do                      # | |
| 42 43 | 
             
            end                                  #
         | 
| 43 44 | 
             
            ```
         | 
| 44 45 |  | 
| 45 | 
            -
            Oktest.rb requires Ruby 2. | 
| 46 | 
            +
            Oktest.rb requires Ruby 2.0 or later.
         | 
| 46 47 |  | 
| 47 48 |  | 
| 48 49 |  | 
| @@ -73,6 +74,7 @@ Oktest.rb requires Ruby 2.3 or later. | |
| 73 74 | 
             
                * <a href="#at_end-crean-up-handler"><code>at_end()</code>: Crean-up Handler</a>
         | 
| 74 75 | 
             
                * <a href="#named-fixtures">Named Fixtures</a>
         | 
| 75 76 | 
             
                * <a href="#fixture-injection">Fixture Injection</a>
         | 
| 77 | 
            +
                * <a href="#fixture-keyword-argument"><code>fixture:</code> keyword argument</a>
         | 
| 76 78 | 
             
                * <a href="#global-scope">Global Scope</a>
         | 
| 77 79 | 
             
              * <a href="#helpers">Helpers</a>
         | 
| 78 80 | 
             
                * <a href="#capture_sio"><code>capture_sio()</code></a>
         | 
| @@ -82,12 +84,19 @@ Oktest.rb requires Ruby 2.3 or later. | |
| 82 84 | 
             
                * <a href="#dummy_attrs"><code>dummy_attrs()</code></a>
         | 
| 83 85 | 
             
                * <a href="#dummy_ivars"><code>dummy_ivars()</code></a>
         | 
| 84 86 | 
             
                * <a href="#recorder"><code>recorder()</code></a>
         | 
| 87 | 
            +
                * <a href="#partial_regexp"><code>partial_regexp()</code></a>
         | 
| 88 | 
            +
              * <a href="#json-matcher">JSON Matcher</a>
         | 
| 89 | 
            +
                * <a href="#simple-example">Simple Example</a>
         | 
| 90 | 
            +
                * <a href="#nested-example">Nested Example</a>
         | 
| 91 | 
            +
                * <a href="#complex-example">Complex Example</a>
         | 
| 92 | 
            +
                * <a href="#helper-methods-for-json-matcher">Helper Methods for JSON Matcher</a>
         | 
| 85 93 | 
             
              * <a href="#tips">Tips</a>
         | 
| 86 94 | 
             
                * <a href="#ok--in-minitest"><code>ok {}</code> in MiniTest</a>
         | 
| 87 95 | 
             
                * <a href="#testing-rack-application">Testing Rack Application</a>
         | 
| 96 | 
            +
                * <a href="#environment-variale-oktest_rb">Environment Variale <code>$OKTEST_RB</code></a>
         | 
| 88 97 | 
             
                * <a href="#traverser-class">Traverser Class</a>
         | 
| 89 | 
            -
                * <a href="#benchmarks">Benchmarks</a>
         | 
| 90 98 | 
             
                * <a href="#--faster-option"><code>--faster</code> Option</a>
         | 
| 99 | 
            +
                * <a href="#benchmarks">Benchmarks</a>
         | 
| 91 100 | 
             
              * <a href="#change-log">Change Log</a>
         | 
| 92 101 | 
             
              * <a href="#license-and-copyright">License and Copyright</a>
         | 
| 93 102 |  | 
| @@ -109,7 +118,7 @@ $ oktest --help | |
| 109 118 | 
             
            $ mkdir test
         | 
| 110 119 |  | 
| 111 120 | 
             
            ### create test script
         | 
| 112 | 
            -
            $ oktest -- | 
| 121 | 
            +
            $ oktest --skeleton > test/example_test.rb
         | 
| 113 122 | 
             
            $ less test/example_test.rb
         | 
| 114 123 |  | 
| 115 124 | 
             
            ### run test script
         | 
| @@ -165,6 +174,7 @@ Result: | |
| 165 174 |  | 
| 166 175 | 
             
            ```terminal
         | 
| 167 176 | 
             
            $ oktest test/example01_test.rb   # or: ruby test/example01_test.rb
         | 
| 177 | 
            +
            ## test/example01_test.rb
         | 
| 168 178 | 
             
            * Hello
         | 
| 169 179 | 
             
              * #hello()
         | 
| 170 180 | 
             
                - [pass] returns greeting message.
         | 
| @@ -206,6 +216,7 @@ Result: | |
| 206 216 |  | 
| 207 217 | 
             
            ```terminal
         | 
| 208 218 | 
             
            $ oktest test/example02_test.rb   # or: ruby test/example02_test.rb
         | 
| 219 | 
            +
            ## test/example02_test.rb
         | 
| 209 220 | 
             
            * other examples
         | 
| 210 221 | 
             
              - [Fail] example of assertion failure
         | 
| 211 222 | 
             
              - [ERROR] example of something error
         | 
| @@ -260,6 +271,7 @@ Result: | |
| 260 271 |  | 
| 261 272 | 
             
            ```terminal
         | 
| 262 273 | 
             
            $ oktest test/example03_test.rb   # or: ruby test/example03_test.rb
         | 
| 274 | 
            +
            ## oktest test/example03_test.rb
         | 
| 263 275 | 
             
            * other examples
         | 
| 264 276 | 
             
              - [Skip] example of skip (reason: requires Ruby3)
         | 
| 265 277 | 
             
              - [TODO] example of todo
         | 
| @@ -280,6 +292,7 @@ Verbose mode (default): | |
| 280 292 |  | 
| 281 293 | 
             
            ```terminal
         | 
| 282 294 | 
             
            $ oktest test/example01_test.rb -s verbose  # or -sv
         | 
| 295 | 
            +
            ## test/example01_test.rb
         | 
| 283 296 | 
             
            * Hello
         | 
| 284 297 | 
             
              * #hello()
         | 
| 285 298 | 
             
                - [pass] returns greeting message.
         | 
| @@ -291,6 +304,16 @@ Simple mode: | |
| 291 304 |  | 
| 292 305 | 
             
            ```terminal
         | 
| 293 306 | 
             
            $ oktest test/example01_test.rb -s simple   # or -ss
         | 
| 307 | 
            +
            ## test/example01_test.rb
         | 
| 308 | 
            +
            * Hello: 
         | 
| 309 | 
            +
              * #hello(): ..
         | 
| 310 | 
            +
            ## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
         | 
| 311 | 
            +
            ```
         | 
| 312 | 
            +
             | 
| 313 | 
            +
            Compact mode:
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            ```terminal
         | 
| 316 | 
            +
            $ oktest test/example01_test.rb -s compact  # or -sc
         | 
| 294 317 | 
             
            test/example01_test.rb: ..
         | 
| 295 318 | 
             
            ## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
         | 
| 296 319 | 
             
            ```
         | 
| @@ -298,7 +321,7 @@ test/example01_test.rb: .. | |
| 298 321 | 
             
            Plain mode:
         | 
| 299 322 |  | 
| 300 323 | 
             
            ```terminal
         | 
| 301 | 
            -
            $ oktest test/example01_test.rb -s  | 
| 324 | 
            +
            $ oktest test/example01_test.rb -s plain    # or -sp
         | 
| 302 325 | 
             
            ..
         | 
| 303 326 | 
             
            ## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
         | 
| 304 327 | 
             
            ```
         | 
| @@ -315,6 +338,8 @@ Quiet mode reports progress only of failed or error test cases (and doesn't | |
| 315 338 | 
             
            report progress of passed ones), so it's output is very compact. This is
         | 
| 316 339 | 
             
            very useful for large project which contains large number of test cases.
         | 
| 317 340 |  | 
| 341 | 
            +
            (Note: `ruby test/example01_test.rb -s <STYLE>` is also available.)
         | 
| 342 | 
            +
             | 
| 318 343 |  | 
| 319 344 | 
             
            ### Run All Test Scripts Under Directory
         | 
| 320 345 |  | 
| @@ -324,7 +349,7 @@ How to run test scripts under `test` directory: | |
| 324 349 | 
             
            $ ls test/
         | 
| 325 350 | 
             
            example01_test.rb       example02_test.rb       example03_test.rb
         | 
| 326 351 |  | 
| 327 | 
            -
            $ oktest -s  | 
| 352 | 
            +
            $ oktest -s compact test  # or: ruby -r oktest -e 'Oktest.main' -- test -s compact
         | 
| 328 353 | 
             
            test/example01_test.rb: ..
         | 
| 329 354 | 
             
            test/example02_test.rb: fE
         | 
| 330 355 | 
             
            ----------------------------------------------------------------------
         | 
| @@ -457,6 +482,7 @@ Result: | |
| 457 482 |  | 
| 458 483 | 
             
            ```terminal
         | 
| 459 484 | 
             
            $ ruby test/example05_test.rb
         | 
| 485 | 
            +
            ## test/example05_test.rb
         | 
| 460 486 | 
             
            * Integer
         | 
| 461 487 | 
             
              * #abs()
         | 
| 462 488 | 
             
                - When value is negative...
         | 
| @@ -984,15 +1010,15 @@ end | |
| 984 1010 | 
             
            Result:
         | 
| 985 1011 |  | 
| 986 1012 | 
             
            ```terminal
         | 
| 987 | 
            -
            $ oktest -s  | 
| 1013 | 
            +
            $ oktest -s quiet test/example21a_test.rb
         | 
| 988 1014 | 
             
            *** before_all() ***
         | 
| 989 1015 | 
             
            === before() ===
         | 
| 990 1016 | 
             
            ---- example spec #1 ----
         | 
| 991 1017 | 
             
            === after() ===
         | 
| 992 | 
            -
             | 
| 1018 | 
            +
            === before() ===
         | 
| 993 1019 | 
             
            ---- example spec #2 ----
         | 
| 994 1020 | 
             
            === after() ===
         | 
| 995 | 
            -
             | 
| 1021 | 
            +
            *** after_all() ***
         | 
| 996 1022 |  | 
| 997 1023 | 
             
            ## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
         | 
| 998 1024 | 
             
            ```
         | 
| @@ -1022,8 +1048,8 @@ Oktest.scope do | |
| 1022 1048 | 
             
                    after  { puts "===== Inner: after =====" }  # !!!!!
         | 
| 1023 1049 |  | 
| 1024 1050 | 
             
                    spec "example" do
         | 
| 1025 | 
            -
             | 
| 1026 | 
            -
             | 
| 1051 | 
            +
                      ok {1+1} == 2
         | 
| 1052 | 
            +
                    end
         | 
| 1027 1053 |  | 
| 1028 1054 | 
             
                  end
         | 
| 1029 1055 |  | 
| @@ -1209,12 +1235,42 @@ end | |
| 1209 1235 | 
             
            -->
         | 
| 1210 1236 |  | 
| 1211 1237 |  | 
| 1238 | 
            +
            ### `fixture:` keyword argument
         | 
| 1239 | 
            +
             | 
| 1240 | 
            +
            `scope()` takes `fixture:` keyword argument which overwrites fixture value.
         | 
| 1241 | 
            +
             | 
| 1242 | 
            +
            test/example26_test.rb:
         | 
| 1243 | 
            +
             | 
| 1244 | 
            +
            ```ruby
         | 
| 1245 | 
            +
            require 'oktest'
         | 
| 1246 | 
            +
             | 
| 1247 | 
            +
            Oktest.scope do
         | 
| 1248 | 
            +
             | 
| 1249 | 
            +
              fixture :user do |uname, uid: 101|   # `uid` is keyword param
         | 
| 1250 | 
            +
                {name: uname, id: uid}
         | 
| 1251 | 
            +
              end
         | 
| 1252 | 
            +
             | 
| 1253 | 
            +
              fixture :uname do
         | 
| 1254 | 
            +
                "Alice"
         | 
| 1255 | 
            +
              end
         | 
| 1256 | 
            +
             | 
| 1257 | 
            +
              ## keyword argument `fixture:` overwrites fixture values
         | 
| 1258 | 
            +
              spec "example", fixture: {uname: "Bob", uid: 201} do   # !!!!!
         | 
| 1259 | 
            +
                |user|
         | 
| 1260 | 
            +
                ok {user[:name]} == "Bob"    # != "Alice"
         | 
| 1261 | 
            +
                ok {user[:id]}   == 201      # != 101
         | 
| 1262 | 
            +
              end
         | 
| 1263 | 
            +
             | 
| 1264 | 
            +
            end
         | 
| 1265 | 
            +
            ```
         | 
| 1266 | 
            +
             | 
| 1267 | 
            +
             | 
| 1212 1268 | 
             
            ### Global Scope
         | 
| 1213 1269 |  | 
| 1214 1270 | 
             
            It is a good idea to separate common fixtures into dedicated file.
         | 
| 1215 1271 | 
             
            In this case, use `Oktest.global_scope()` instead of `Oktest.scope()`.
         | 
| 1216 1272 |  | 
| 1217 | 
            -
            test/ | 
| 1273 | 
            +
            test/example27_test.rb:
         | 
| 1218 1274 |  | 
| 1219 1275 | 
             
            ```ruby
         | 
| 1220 1276 | 
             
            require 'oktest'
         | 
| @@ -1588,6 +1644,334 @@ end | |
| 1588 1644 | 
             
            ```
         | 
| 1589 1645 |  | 
| 1590 1646 |  | 
| 1647 | 
            +
            ### `partial_regexp()`
         | 
| 1648 | 
            +
             | 
| 1649 | 
            +
            `partial_regexp()` can embed regexp pattern into string, and compile it into Regexp object. This is very useful to validate multiline string with regexp.
         | 
| 1650 | 
            +
             | 
| 1651 | 
            +
            Assume that you are testing the following function `f1()`. It generates multiline string containing date and random string.
         | 
| 1652 | 
            +
             | 
| 1653 | 
            +
            ```ruby
         | 
| 1654 | 
            +
            def f1()
         | 
| 1655 | 
            +
              today  = Date.today.to_s                  # ex: '2021-12-31'
         | 
| 1656 | 
            +
              secret = Random.bytes(8).unpack('H*')[0]  # ex: "cd0b260ac728eda5"
         | 
| 1657 | 
            +
              return <<END
         | 
| 1658 | 
            +
            * [config.date]   #{today}
         | 
| 1659 | 
            +
            * [config.secret] #{secret}
         | 
| 1660 | 
            +
            END
         | 
| 1661 | 
            +
            end
         | 
| 1662 | 
            +
            ```ruby
         | 
| 1663 | 
            +
             | 
| 1664 | 
            +
            To test `f1()`, you may write the following test code.
         | 
| 1665 | 
            +
            As you can see, expected regexp literal is complicated.
         | 
| 1666 | 
            +
             | 
| 1667 | 
            +
            ```ruby
         | 
| 1668 | 
            +
              topic 'f1()' do
         | 
| 1669 | 
            +
                spec "generates multiline string." do
         | 
| 1670 | 
            +
                  expected = /\A\* \[config\.date\]   \d\d\d\d-\d\d-\d\d\n\* \[config\.secret\] [0-9a-f]+\n/
         | 
| 1671 | 
            +
                  ok {f1()} =~ expected
         | 
| 1672 | 
            +
                end
         | 
| 1673 | 
            +
              end
         | 
| 1674 | 
            +
            ```
         | 
| 1675 | 
            +
             | 
| 1676 | 
            +
            [`x` option](https://ruby-doc.org/core-2.7.0/Regexp.html#class-Regexp-label-Free-Spacing+Mode+and+Comments) of regexp (such as `/.../x`) allows you to write regexp literal in multiline format.
         | 
| 1677 | 
            +
            But you have to escape metachars (`*`, `.`, `[]`, and white space).
         | 
| 1678 | 
            +
             | 
| 1679 | 
            +
            ```ruby
         | 
| 1680 | 
            +
              topic 'f1()' do
         | 
| 1681 | 
            +
                spec "generates multiline string." do
         | 
| 1682 | 
            +
                  expected = /\A
         | 
| 1683 | 
            +
            \*\ \[config\.date\]\ \ \ \d\d\d\d-\d\d-\d\d\n
         | 
| 1684 | 
            +
            \*\ \[config\.secret\]\ [0-9a-f]+\n
         | 
| 1685 | 
            +
            \z/x      # !!!!!
         | 
| 1686 | 
            +
                  ok {f1()} =~ expected
         | 
| 1687 | 
            +
                end
         | 
| 1688 | 
            +
              end
         | 
| 1689 | 
            +
            ```
         | 
| 1690 | 
            +
             | 
| 1691 | 
            +
            In such case, `partial_regexp()` is very useful. It compiles string into Regexp object.
         | 
| 1692 | 
            +
            Using `partial_regexp()`, you can write expected regexp very easily.
         | 
| 1693 | 
            +
             | 
| 1694 | 
            +
            ```ruby
         | 
| 1695 | 
            +
              topic 'f1()' do
         | 
| 1696 | 
            +
                spec "generates multiline string." do
         | 
| 1697 | 
            +
                  # - Regexp can be in `{== ==}`.
         | 
| 1698 | 
            +
                  # - Other text part is escaped by `Regexp.escape()`.
         | 
| 1699 | 
            +
                  expected = partial_regexp <<'END'      # !!!!!
         | 
| 1700 | 
            +
            * [config.date]   {== \d\d\d\d-\d\d-\d\d ==}
         | 
| 1701 | 
            +
            * [config.secret] {== [0-9a-f]+ ==}
         | 
| 1702 | 
            +
            END
         | 
| 1703 | 
            +
                  ok {f1()} =~ expected
         | 
| 1704 | 
            +
                  ## above is equivarent to:
         | 
| 1705 | 
            +
                  #expected = /\A
         | 
| 1706 | 
            +
                  #\*\ \[config\.date\]\ \ \ \d\d\d\d-\d\d-\d\d\n
         | 
| 1707 | 
            +
                  #\*\ \[config\.secret\]\ [0-9a-f]+\n
         | 
| 1708 | 
            +
                  #\z/x      # !!!!!
         | 
| 1709 | 
            +
                  #ok {f1()} =~ expected
         | 
| 1710 | 
            +
                end
         | 
| 1711 | 
            +
              end
         | 
| 1712 | 
            +
            ```
         | 
| 1713 | 
            +
             | 
| 1714 | 
            +
            `partial_regexp()` takes 4 arguments.
         | 
| 1715 | 
            +
             | 
| 1716 | 
            +
            ```ruby
         | 
| 1717 | 
            +
            def partial_regexp(pattern, begin_='\A', end_='\z', mark='{== ==}')
         | 
| 1718 | 
            +
            ```
         | 
| 1719 | 
            +
             | 
| 1720 | 
            +
            `partial_regexp()` adds `\A` and `\z` automatically.
         | 
| 1721 | 
            +
            If you want not to add them, pass empty string or nil as 2nd and 3rd argument, like this:
         | 
| 1722 | 
            +
             | 
| 1723 | 
            +
            ```ruby
         | 
| 1724 | 
            +
            partial_regexp <<-'END', '', ''    # !!!!!
         | 
| 1725 | 
            +
            ...
         | 
| 1726 | 
            +
            END
         | 
| 1727 | 
            +
            ```
         | 
| 1728 | 
            +
             | 
| 1729 | 
            +
            If you want to change embed mark, specify 4th argument, like this:
         | 
| 1730 | 
            +
             | 
| 1731 | 
            +
            ```ruby
         | 
| 1732 | 
            +
            partial_regexp <<-'END', '\A', '\z', '%% %%'    # !!!!!
         | 
| 1733 | 
            +
            * [config.date]   %% \d\d\d\d-\d\d-\d\d %%
         | 
| 1734 | 
            +
            * [config.secret] %% [0-9a-f]+ %%
         | 
| 1735 | 
            +
            END
         | 
| 1736 | 
            +
            ```
         | 
| 1737 | 
            +
             | 
| 1738 | 
            +
            Oktest.rb provides `partial_regexp!()`, too.
         | 
| 1739 | 
            +
            Difference between `partial_regexp()` and `partial_regexp!()` is the result of `#inspect()`.
         | 
| 1740 | 
            +
            This is imortant only when assertion failed and error message reported.
         | 
| 1741 | 
            +
            You can use whichever you like.
         | 
| 1742 | 
            +
             | 
| 1743 | 
            +
            ```ruby
         | 
| 1744 | 
            +
            r1 = partial_regexp <<-'END'
         | 
| 1745 | 
            +
            * [config.date]   {== \d\d\d\d-\d\d-\d\d ==}
         | 
| 1746 | 
            +
            * [config.secret] {== [0-9a-f]+ ==}
         | 
| 1747 | 
            +
            END
         | 
| 1748 | 
            +
            p r1
         | 
| 1749 | 
            +
               #=> /\A
         | 
| 1750 | 
            +
               #   \*\ \[config\.date\]\ \ \ \d\d\d\d-\d\d-\d\d\n
         | 
| 1751 | 
            +
               #   \*\ \[config\.secret\]\ [0-9a-f]+\n
         | 
| 1752 | 
            +
               #   \z/x
         | 
| 1753 | 
            +
             | 
| 1754 | 
            +
            r2 = partial_regexp! <<-'END'                   # !!!!!
         | 
| 1755 | 
            +
            * [config.date]   {== \d\d\d\d-\d\d-\d\d ==}
         | 
| 1756 | 
            +
            * [config.secret] {== [0-9a-f]+ ==}
         | 
| 1757 | 
            +
            END
         | 
| 1758 | 
            +
            p r2
         | 
| 1759 | 
            +
               #=> partial_regexp(<<PREXP, '\A', '\z')
         | 
| 1760 | 
            +
               #   * [config.date]   {== \d\d\d\d-\d\d-\d\d ==}
         | 
| 1761 | 
            +
               #   * [config.secret] {== [0-9a-f]+ ==}
         | 
| 1762 | 
            +
               #   PREXP
         | 
| 1763 | 
            +
            ```
         | 
| 1764 | 
            +
             | 
| 1765 | 
            +
             | 
| 1766 | 
            +
            ## JSON Matcher
         | 
| 1767 | 
            +
             | 
| 1768 | 
            +
            Oktest.rb provides easy way to assert JSON data.
         | 
| 1769 | 
            +
            This is very convenient feature, but don't abuse it.
         | 
| 1770 | 
            +
             | 
| 1771 | 
            +
             | 
| 1772 | 
            +
            ### Simple Example
         | 
| 1773 | 
            +
             | 
| 1774 | 
            +
            <!--
         | 
| 1775 | 
            +
            test/example41_test.rb:
         | 
| 1776 | 
            +
            -->
         | 
| 1777 | 
            +
            ```ruby
         | 
| 1778 | 
            +
            require 'oktest'
         | 
| 1779 | 
            +
            require 'set'                               # !!!!!
         | 
| 1780 | 
            +
             | 
| 1781 | 
            +
            Oktest.scope do
         | 
| 1782 | 
            +
              topic 'JSON Example' do
         | 
| 1783 | 
            +
             | 
| 1784 | 
            +
                spec "simple example" do
         | 
| 1785 | 
            +
                  actual = {
         | 
| 1786 | 
            +
                    "name":     "Alice",
         | 
| 1787 | 
            +
                    "id":       1001,
         | 
| 1788 | 
            +
                    "age":      18,
         | 
| 1789 | 
            +
                    "email":    "alice@example.com",
         | 
| 1790 | 
            +
                    "gender":   "F",
         | 
| 1791 | 
            +
                    "deleted":  false,
         | 
| 1792 | 
            +
                    "tags":     ["aaa", "bbb", "ccc"],
         | 
| 1793 | 
            +
                   #"twitter":  "@alice",
         | 
| 1794 | 
            +
                  }
         | 
| 1795 | 
            +
                  ## assertion
         | 
| 1796 | 
            +
                  ok {JSON(actual)} === {               # requires `JSON()` and `===`
         | 
| 1797 | 
            +
                    "name":     "Alice",                # scalar value
         | 
| 1798 | 
            +
                    "id":       1000..9999,             # range object
         | 
| 1799 | 
            +
                    "age":      Integer,                # class object
         | 
| 1800 | 
            +
                    "email":    /^\w+@example\.com$/,   # regexp
         | 
| 1801 | 
            +
                    "gender":   Set.new(["M", "F"]),    # Set object ("M" or "F")
         | 
| 1802 | 
            +
                    "deleted":  Set.new([true, false]), # boolean (true or false)
         | 
| 1803 | 
            +
                    "tags":     [/^\w+$/].each,         # Enumerator object (!= Array obj)
         | 
| 1804 | 
            +
                    "twitter?": /^@\w+$/,               # key 'xxx?' means optional value
         | 
| 1805 | 
            +
                  }
         | 
| 1806 | 
            +
                end
         | 
| 1807 | 
            +
             | 
| 1808 | 
            +
              end
         | 
| 1809 | 
            +
            end
         | 
| 1810 | 
            +
            ```
         | 
| 1811 | 
            +
             | 
| 1812 | 
            +
            (Note: Ruby 2.4 or older doesn't have `Set#===()`, so above code will occur error
         | 
| 1813 | 
            +
             in Ruby 2.4 or older. Please add the folllowing hack in your test script.)
         | 
| 1814 | 
            +
             | 
| 1815 | 
            +
            ```ruby
         | 
| 1816 | 
            +
            require 'set'
         | 
| 1817 | 
            +
            unless Set.instance_methods(false).include?(:===)  # for Ruby 2.4 or older
         | 
| 1818 | 
            +
              class Set; alias === include?; end
         | 
| 1819 | 
            +
            end
         | 
| 1820 | 
            +
            ```
         | 
| 1821 | 
            +
             | 
| 1822 | 
            +
            Notice that `Enumerator` has different meaning from `Array` in JSON matcher.
         | 
| 1823 | 
            +
             | 
| 1824 | 
            +
            ```ruby
         | 
| 1825 | 
            +
              actual = {"tags": ["foo", "bar", "baz"]}
         | 
| 1826 | 
            +
             | 
| 1827 | 
            +
              ## Array
         | 
| 1828 | 
            +
              ok {JSON(actual)} == {"tags": ["foo", "bar", "baz"]}
         | 
| 1829 | 
            +
             | 
| 1830 | 
            +
              ## Enumerator
         | 
| 1831 | 
            +
              ok {JSON(actual)} == {"tags": [/^\w+$/].each}
         | 
| 1832 | 
            +
            ```
         | 
| 1833 | 
            +
             | 
| 1834 | 
            +
             | 
| 1835 | 
            +
            ### Nested Example
         | 
| 1836 | 
            +
             | 
| 1837 | 
            +
            <!--
         | 
| 1838 | 
            +
            test/example42_test.rb:
         | 
| 1839 | 
            +
            -->
         | 
| 1840 | 
            +
            ```ruby
         | 
| 1841 | 
            +
            require 'oktest'
         | 
| 1842 | 
            +
            require 'set'                            # !!!!!
         | 
| 1843 | 
            +
             | 
| 1844 | 
            +
            Oktest.scope do
         | 
| 1845 | 
            +
              topic 'JSON Example' do
         | 
| 1846 | 
            +
             | 
| 1847 | 
            +
                spec "nested example" do
         | 
| 1848 | 
            +
                  actual = {
         | 
| 1849 | 
            +
                    "teams": [
         | 
| 1850 | 
            +
                      {
         | 
| 1851 | 
            +
                        "team": "Section 9",
         | 
| 1852 | 
            +
                        "members": [
         | 
| 1853 | 
            +
                          {"id": 2500, "name": "Aramaki", "gender": "M"},
         | 
| 1854 | 
            +
                          {"id": 2501, "name": "Motoko" , "gender": "F"},
         | 
| 1855 | 
            +
                          {"id": 2502, "name": "Batou"  , "gender": "M"},
         | 
| 1856 | 
            +
                        ],
         | 
| 1857 | 
            +
                        "leader": "Aramaki",
         | 
| 1858 | 
            +
                      },
         | 
| 1859 | 
            +
                      {
         | 
| 1860 | 
            +
                        "team": "SOS Brigade",
         | 
| 1861 | 
            +
                        "members": [
         | 
| 1862 | 
            +
                          {"id": 1001, "name": "Haruhi", "gender": "F"},
         | 
| 1863 | 
            +
                          {"id": 1002, "name": "Mikuru", "gender": "F"},
         | 
| 1864 | 
            +
                          {"id": 1003, "name": "Yuki"  , "gender": "F"},
         | 
| 1865 | 
            +
                          {"id": 1004, "name": "Itsuki", "gender": "M"},
         | 
| 1866 | 
            +
                          {"id": 1005, "name": "Kyon"  , "gender": "M"},
         | 
| 1867 | 
            +
                        ],
         | 
| 1868 | 
            +
                      },
         | 
| 1869 | 
            +
                    ],
         | 
| 1870 | 
            +
                  }
         | 
| 1871 | 
            +
                  ## assertion
         | 
| 1872 | 
            +
                  ok {JSON(actual)} === {            # requires `JSON()` and `===`
         | 
| 1873 | 
            +
                    "teams": [
         | 
| 1874 | 
            +
                      {
         | 
| 1875 | 
            +
                        "team": String,
         | 
| 1876 | 
            +
                        "members": [
         | 
| 1877 | 
            +
                          {"id": 1000..9999, "name": String, "gender": Set.new(["M", "F"])}
         | 
| 1878 | 
            +
                        ].each,                     # Enumerator object (!= Array obj)
         | 
| 1879 | 
            +
                        "leader?": String,           # key 'xxx?' means optional value
         | 
| 1880 | 
            +
                      }
         | 
| 1881 | 
            +
                    ].each,                          # Enumerator object (!= Array obj)
         | 
| 1882 | 
            +
                  }
         | 
| 1883 | 
            +
                end
         | 
| 1884 | 
            +
             | 
| 1885 | 
            +
              end
         | 
| 1886 | 
            +
            end
         | 
| 1887 | 
            +
            ```
         | 
| 1888 | 
            +
             | 
| 1889 | 
            +
             | 
| 1890 | 
            +
            ### Complex Example
         | 
| 1891 | 
            +
             | 
| 1892 | 
            +
            * `OR(x, y, z)` matches to `x`, `y`, or `z`.
         | 
| 1893 | 
            +
            * `AND(x, y, z)` matches to `x`, `y`, and `z`.
         | 
| 1894 | 
            +
            * Key `"*"` matches to any key of hash object.
         | 
| 1895 | 
            +
            * `Any()` matches to anything.
         | 
| 1896 | 
            +
             | 
| 1897 | 
            +
            <!--
         | 
| 1898 | 
            +
            test/example43_test.rb:
         | 
| 1899 | 
            +
            -->
         | 
| 1900 | 
            +
            ```ruby
         | 
| 1901 | 
            +
            require 'oktest'
         | 
| 1902 | 
            +
            require 'set'
         | 
| 1903 | 
            +
             | 
| 1904 | 
            +
            Oktest.scope do
         | 
| 1905 | 
            +
              topic 'JSON Example' do
         | 
| 1906 | 
            +
             | 
| 1907 | 
            +
                spec "OR() example" do
         | 
| 1908 | 
            +
                  ok {JSON({"val": "123"})} === {"val": OR(String, Integer)}    # OR()
         | 
| 1909 | 
            +
                  ok {JSON({"val":  123 })} === {"val": OR(String, Integer)}    # OR()
         | 
| 1910 | 
            +
                end
         | 
| 1911 | 
            +
             | 
| 1912 | 
            +
                spec "AND() example" do
         | 
| 1913 | 
            +
                  ok {JSON({"val": "123"})} === {"val": AND(String, /^\d+$/)}   # AND()
         | 
| 1914 | 
            +
                  ok {JSON({"val":  123 })} === {"val": AND(Integer, 1..1000)}  # AND()
         | 
| 1915 | 
            +
                end
         | 
| 1916 | 
            +
             | 
| 1917 | 
            +
                spec "`*` and `ANY` example" do
         | 
| 1918 | 
            +
                  ok {JSON({"name": "Bob", "age": 20})} === {"*": Any()}    # '*' and Any()
         | 
| 1919 | 
            +
                end
         | 
| 1920 | 
            +
             | 
| 1921 | 
            +
                spec "complex exapmle" do
         | 
| 1922 | 
            +
                  actual = {
         | 
| 1923 | 
            +
                    "item":   "awesome item",
         | 
| 1924 | 
            +
                    "colors": ["red", "#cceeff", "green", "#fff"],
         | 
| 1925 | 
            +
                    "memo":   "this is awesome.",
         | 
| 1926 | 
            +
                    "url":    "https://example.com/awesome",
         | 
| 1927 | 
            +
                  }
         | 
| 1928 | 
            +
                  ## assertion
         | 
| 1929 | 
            +
                  color_names = ["red", "blue", "green", "white", "black"]
         | 
| 1930 | 
            +
                  color_pat   = /^\#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/
         | 
| 1931 | 
            +
                  ok {JSON(actual)} === {
         | 
| 1932 | 
            +
                    "colors": [
         | 
| 1933 | 
            +
                      AND(String, OR(Set.new(color_names), color_pat)),   # AND() and OR()
         | 
| 1934 | 
            +
                    ].each,
         | 
| 1935 | 
            +
                    "*": Any(),             # match to any key (`"*"`) and value (`ANY`)
         | 
| 1936 | 
            +
                  }
         | 
| 1937 | 
            +
                end
         | 
| 1938 | 
            +
             | 
| 1939 | 
            +
              end
         | 
| 1940 | 
            +
            end
         | 
| 1941 | 
            +
            ```
         | 
| 1942 | 
            +
             | 
| 1943 | 
            +
            (Note: `/^\d+$/` implies String value, and `1..100` implies Integer value.)
         | 
| 1944 | 
            +
             | 
| 1945 | 
            +
            ```ruby
         | 
| 1946 | 
            +
            ## No need to write:
         | 
| 1947 | 
            +
            ##   ok {JSON{...}} === {"val": AND(String, /^\d+$/)}
         | 
| 1948 | 
            +
            ##   ok {JSON{...}} === {"val": AND(Integer, 1..100)}
         | 
| 1949 | 
            +
            ok {JSON({"val": "A"})} === {"val": /^\d+$/}   # implies String value
         | 
| 1950 | 
            +
            ok {JSON({"val": 99 })} === {"val": 1..100}    # implies Integer value
         | 
| 1951 | 
            +
            ```
         | 
| 1952 | 
            +
             | 
| 1953 | 
            +
             | 
| 1954 | 
            +
            ### Helper Methods for JSON Matcher
         | 
| 1955 | 
            +
             | 
| 1956 | 
            +
            Oktest.rb provides some helper methods and objects:
         | 
| 1957 | 
            +
             | 
| 1958 | 
            +
            * `Enum(x, y, z)` is almost same as `Set.new([x, y, z])`.
         | 
| 1959 | 
            +
            * `Bool()` is same as `Enum(true, false)`.
         | 
| 1960 | 
            +
            * `Length(3)` matches to length 3, and `Length(1..3)` matches to length 1..3.
         | 
| 1961 | 
            +
             | 
| 1962 | 
            +
            <!--
         | 
| 1963 | 
            +
            test/example44_test.rb:
         | 
| 1964 | 
            +
            -->
         | 
| 1965 | 
            +
            ```ruby
         | 
| 1966 | 
            +
              actual = {"gender": "M", "deleted": false, "code": "ABCD1234"}
         | 
| 1967 | 
            +
              ok {JSON(actual)} == {
         | 
| 1968 | 
            +
                "gender":  Enum("M", "F"),        # same as Set.new(["M", "F"])
         | 
| 1969 | 
            +
                "deleted": Bool(),                # same as Enum(true, false)
         | 
| 1970 | 
            +
                "code":    Length(6..10),         # code length should be 6..10
         | 
| 1971 | 
            +
              }
         | 
| 1972 | 
            +
            ```
         | 
| 1973 | 
            +
             | 
| 1974 | 
            +
             | 
| 1591 1975 |  | 
| 1592 1976 | 
             
            ## Tips
         | 
| 1593 1977 |  | 
| @@ -1597,7 +1981,7 @@ end | |
| 1597 1981 | 
             
            If you want to use `ok {actual} == expected` style assertion in MiniTest,
         | 
| 1598 1982 | 
             
            install `minitest-ok` gem instead of `otest` gem.
         | 
| 1599 1983 |  | 
| 1600 | 
            -
            test/ | 
| 1984 | 
            +
            test/example51_test.rb:
         | 
| 1601 1985 |  | 
| 1602 1986 | 
             
            ```ruby
         | 
| 1603 1987 | 
             
            require 'minitest/spec'
         | 
| @@ -1620,7 +2004,7 @@ See [minitest-ok README](https://github.com/kwatch/minitest-ok) for details. | |
| 1620 2004 |  | 
| 1621 2005 | 
             
            `rack-test_app` gem will help you to test Rack application very well.
         | 
| 1622 2006 |  | 
| 1623 | 
            -
            test/ | 
| 2007 | 
            +
            test/example52_test.rb:
         | 
| 1624 2008 |  | 
| 1625 2009 | 
             
            ```ruby
         | 
| 1626 2010 | 
             
            require 'rack'
         | 
| @@ -1689,11 +2073,25 @@ end | |
| 1689 2073 | 
             
            ```
         | 
| 1690 2074 |  | 
| 1691 2075 |  | 
| 2076 | 
            +
            ### Environment Variale `$OKTEST_RB`
         | 
| 2077 | 
            +
             | 
| 2078 | 
            +
            You can set default command-line option to environment variale `$OKTEST_RB`.
         | 
| 2079 | 
            +
            For examle, you can specify default reporting style with `$OKTEST_RB`.
         | 
| 2080 | 
            +
             | 
| 2081 | 
            +
            ```terminal
         | 
| 2082 | 
            +
            ### change default reporting style to plain-style.
         | 
| 2083 | 
            +
            $ export OKTEST_RB="-s plain"                  # !!!!!
         | 
| 2084 | 
            +
             | 
| 2085 | 
            +
            ### run test script in plain-style reporting without '-s' option.
         | 
| 2086 | 
            +
            $ ruby test/foo_test.rb
         | 
| 2087 | 
            +
            ```
         | 
| 2088 | 
            +
             | 
| 2089 | 
            +
             | 
| 1692 2090 | 
             
            ### Traverser Class
         | 
| 1693 2091 |  | 
| 1694 2092 | 
             
            Oktest.rb provides `Traverser` class which implements Visitor pattern.
         | 
| 1695 2093 |  | 
| 1696 | 
            -
            test/ | 
| 2094 | 
            +
            test/example54_test.rb:
         | 
| 1697 2095 |  | 
| 1698 2096 | 
             
            ```ruby
         | 
| 1699 2097 | 
             
            require 'oktest'
         | 
| @@ -1750,8 +2148,8 @@ MyTraverser.new.start() | |
| 1750 2148 | 
             
            Result:
         | 
| 1751 2149 |  | 
| 1752 2150 | 
             
            ```terminal
         | 
| 1753 | 
            -
            $ ruby test/ | 
| 1754 | 
            -
            # scope: test/ | 
| 2151 | 
            +
            $ ruby test/example54_test.rb
         | 
| 2152 | 
            +
            # scope: test/example54_test.rb
         | 
| 1755 2153 | 
             
              + topic: Example Topic
         | 
| 1756 2154 | 
             
                - spec: sample #1
         | 
| 1757 2155 | 
             
                - spec: sample #2
         | 
| @@ -1762,18 +2160,36 @@ $ ruby test/example44_test.rb | |
| 1762 2160 | 
             
            ```
         | 
| 1763 2161 |  | 
| 1764 2162 |  | 
| 2163 | 
            +
            ### `--faster` Option
         | 
| 2164 | 
            +
             | 
| 2165 | 
            +
            ~~If you are working in very larget project and you want to run test scripts as fast as possible, try `--faster` option of `oktest` command.~~
         | 
| 2166 | 
            +
             | 
| 2167 | 
            +
            ```terminal
         | 
| 2168 | 
            +
            $ oktest -s quiet --faster test/        ## only for very large project
         | 
| 2169 | 
            +
            ```
         | 
| 2170 | 
            +
             | 
| 2171 | 
            +
            ~~Or set `Oktest::Config.ok_location = false` in your test script.~~
         | 
| 2172 | 
            +
             | 
| 2173 | 
            +
            ```ruby
         | 
| 2174 | 
            +
            require 'oktest'
         | 
| 2175 | 
            +
            Oktest::Config.ok_location = false      ## only for very large project
         | 
| 2176 | 
            +
            ```
         | 
| 2177 | 
            +
             | 
| 2178 | 
            +
            `--faster` option is still available but no longer recommended, because performance of `ok{}` is improved significantly since Oktest.rb 1.2.0.
         | 
| 2179 | 
            +
             | 
| 2180 | 
            +
             | 
| 1765 2181 | 
             
            ### Benchmarks
         | 
| 1766 2182 |  | 
| 1767 2183 | 
             
            Oktest.rb gem file contains benchmark script.
         | 
| 1768 2184 | 
             
            It shows that Oktest.rb runs more than three times faster than RSpec.
         | 
| 1769 2185 |  | 
| 1770 2186 | 
             
            ```terminal
         | 
| 1771 | 
            -
            $ gem install oktest        # ver 1. | 
| 2187 | 
            +
            $ gem install oktest        # ver 1.2.0
         | 
| 1772 2188 | 
             
            $ gem install rspec         # ver 3.10.0
         | 
| 1773 2189 | 
             
            $ gem install minitest      # ver 5.14.4
         | 
| 1774 2190 | 
             
            $ gem install test-unit     # ver 3.4.4
         | 
| 1775 2191 |  | 
| 1776 | 
            -
            $ cp -pr $GEM_HOME/gems/oktest-1. | 
| 2192 | 
            +
            $ cp -pr $GEM_HOME/gems/oktest-1.2.0/benchmark .
         | 
| 1777 2193 | 
             
            $ cd benchmark/
         | 
| 1778 2194 | 
             
            $ rake -T
         | 
| 1779 2195 | 
             
            $ ruby --version
         | 
| @@ -1782,67 +2198,60 @@ ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-darwin18] | |
| 1782 2198 | 
             
            $ rake benchmark:all
         | 
| 1783 2199 | 
             
            ```
         | 
| 1784 2200 |  | 
| 2201 | 
            +
            Summary of example result:
         | 
| 2202 | 
            +
             | 
| 2203 | 
            +
            ```
         | 
| 2204 | 
            +
            Oktest:              6.815 real     6.511 user     0.257 sys
         | 
| 2205 | 
            +
            Oktest (--faster):   6.401 real     6.123 user     0.240 sys
         | 
| 2206 | 
            +
            RSpec:              32.062 real    27.778 user     4.383 sys
         | 
| 2207 | 
            +
            MiniTest:            9.140 real     8.657 user     0.705 sys
         | 
| 2208 | 
            +
            Test::Unit:         19.580 real    19.020 user     0.885 sys
         | 
| 2209 | 
            +
            ```
         | 
| 2210 | 
            +
             | 
| 1785 2211 | 
             
            Example result:
         | 
| 1786 2212 |  | 
| 1787 2213 | 
             
            ```
         | 
| 1788 2214 | 
             
            ==================== oktest ====================
         | 
| 1789 2215 | 
             
            oktest -sq run_all.rb
         | 
| 1790 2216 |  | 
| 1791 | 
            -
            ## total:100000 (pass:100000, fail:0, error:0, skip:0, todo:0) in  | 
| 2217 | 
            +
            ## total:100000 (pass:100000, fail:0, error:0, skip:0, todo:0) in 2.36s
         | 
| 1792 2218 |  | 
| 1793 | 
            -
                     | 
| 2219 | 
            +
                    6.815 real        6.511 user        0.257 sys
         | 
| 1794 2220 |  | 
| 1795 2221 | 
             
            ==================== oktest:faster ====================
         | 
| 1796 2222 | 
             
            oktest -sq --faster run_all.rb
         | 
| 1797 2223 |  | 
| 1798 | 
            -
            ## total:100000 (pass:100000, fail:0, error:0, skip:0, todo:0) in  | 
| 2224 | 
            +
            ## total:100000 (pass:100000, fail:0, error:0, skip:0, todo:0) in 2.01s
         | 
| 1799 2225 |  | 
| 1800 | 
            -
                     | 
| 2226 | 
            +
                    6.401 real        6.123 user        0.240 sys
         | 
| 1801 2227 |  | 
| 1802 2228 | 
             
            ==================== rspec ====================
         | 
| 1803 2229 | 
             
            rspec run_all.rb | tail -4
         | 
| 1804 2230 |  | 
| 1805 | 
            -
            Finished in  | 
| 2231 | 
            +
            Finished in 15.27 seconds (files took 16.08 seconds to load)
         | 
| 1806 2232 | 
             
            100000 examples, 0 failures
         | 
| 1807 2233 |  | 
| 1808 2234 |  | 
| 1809 | 
            -
                     | 
| 2235 | 
            +
                    32.062 real        27.778 user        4.383 sys
         | 
| 1810 2236 |  | 
| 1811 2237 | 
             
            ==================== minitest ====================
         | 
| 1812 2238 | 
             
            ruby run_all.rb | tail -4
         | 
| 1813 2239 |  | 
| 1814 | 
            -
            Finished in 5. | 
| 2240 | 
            +
            Finished in 5.281425s, 18934.2838 runs/s, 37868.5677 assertions/s.
         | 
| 1815 2241 |  | 
| 1816 | 
            -
            100000 runs,  | 
| 2242 | 
            +
            100000 runs, 200000 assertions, 0 failures, 0 errors, 0 skips
         | 
| 1817 2243 |  | 
| 1818 | 
            -
                     | 
| 2244 | 
            +
                    9.140 real        8.657 user        0.705 sys
         | 
| 1819 2245 |  | 
| 1820 2246 | 
             
            ==================== testunit ====================
         | 
| 1821 2247 | 
             
            ruby run_all.rb | tail -5
         | 
| 1822 2248 | 
             
            -------------------------------------------------------------------------------
         | 
| 1823 | 
            -
            100000 tests,  | 
| 2249 | 
            +
            100000 tests, 200000 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
         | 
| 1824 2250 | 
             
            100% passed
         | 
| 1825 2251 | 
             
            -------------------------------------------------------------------------------
         | 
| 1826 | 
            -
             | 
| 1827 | 
            -
             | 
| 1828 | 
            -
                    17.838 real        17.201 user        0.879 sys
         | 
| 1829 | 
            -
            ```
         | 
| 2252 | 
            +
            7775.59 tests/s, 15551.18 assertions/s
         | 
| 1830 2253 |  | 
| 1831 | 
            -
             | 
| 1832 | 
            -
            ### `--faster` Option
         | 
| 1833 | 
            -
             | 
| 1834 | 
            -
            If you are working in very larget project and you want to run test scripts
         | 
| 1835 | 
            -
            as fast as possible, try `--faster` option of `oktest` command.
         | 
| 1836 | 
            -
             | 
| 1837 | 
            -
            ```terminal
         | 
| 1838 | 
            -
            $ oktest -s quiet --faster test/        ## only for very large project
         | 
| 1839 | 
            -
            ```
         | 
| 1840 | 
            -
             | 
| 1841 | 
            -
            Or set `Oktest::Config.ok_location = false` in your test script.
         | 
| 1842 | 
            -
             | 
| 1843 | 
            -
            ```ruby
         | 
| 1844 | 
            -
            require 'oktest'
         | 
| 1845 | 
            -
            Oktest::Config.ok_location = false      ## only for very large project
         | 
| 2254 | 
            +
                    19.580 real        19.020 user        0.885 sys
         | 
| 1846 2255 | 
             
            ```
         | 
| 1847 2256 |  | 
| 1848 2257 |  |