oktest 1.0.2 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|