oktest 1.0.0 → 1.1.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 +4 -4
- data/README.md +287 -51
- data/Rakefile.rb +1 -1
- data/lib/oktest.rb +393 -19
- data/oktest.gemspec +2 -2
- data/test/assertion_test.rb +70 -5
- data/test/filter_test.rb +2 -2
- data/test/fixture_test.rb +1 -1
- data/test/generator_test.rb +1 -1
- data/test/helper_test.rb +1 -1
- data/test/initialize.rb +8 -1
- data/test/mainapp_test.rb +42 -5
- data/test/matcher_test.rb +424 -0
- data/test/misc_test.rb +1 -1
- data/test/node_test.rb +34 -1
- data/test/reporter_test.rb +34 -6
- data/test/runner_test.rb +90 -9
- data/test/util_test.rb +1 -1
- data/test/visitor_test.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5232c4c9a9bf78763791cf182129900a376d1dd619fbf4a21f441ea10c0a7f27
|
4
|
+
data.tar.gz: 1d35a5ec4678e1a80624c058a32647cc6013c6a3dc4f87f3590bea2a226ea412
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 385ddc6a48f39657c38ee43ade9c89677aa686f8e7f55ec90eb9aef7d9dbec795cea55014e48070a22a18b63daea081863a4c6c0afc3c1d24c33316a70fcd149
|
7
|
+
data.tar.gz: ea3d7947b5195db3cdfd7a435adbdf0d96edfcfc0a653b67d7a241d4dec3e479c986fe8fc8294427e3c05343681b2308474131a35e5e62b75d1214660e62599e
|
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
|
@@ -54,7 +55,7 @@ Oktest.rb requires Ruby 2.3 or later.
|
|
54
55
|
* <a href="#install">Install</a>
|
55
56
|
* <a href="#basic-example">Basic Example</a>
|
56
57
|
* <a href="#assertion-failure-and-error">Assertion Failure, and Error</a>
|
57
|
-
* <a href="#skip-and-todo">Skip
|
58
|
+
* <a href="#skip-and-todo">Skip and Todo</a>
|
58
59
|
* <a href="#reporting-style">Reporting Style</a>
|
59
60
|
* <a href="#run-all-test-scripts-under-directory">Run All Test Scripts Under Directory</a>
|
60
61
|
* <a href="#tag-and-filtering">Tag and Filtering</a>
|
@@ -82,6 +83,11 @@ Oktest.rb requires Ruby 2.3 or later.
|
|
82
83
|
* <a href="#dummy_attrs"><code>dummy_attrs()</code></a>
|
83
84
|
* <a href="#dummy_ivars"><code>dummy_ivars()</code></a>
|
84
85
|
* <a href="#recorder"><code>recorder()</code></a>
|
86
|
+
* <a href="#json-matcher">JSON Matcher</a>
|
87
|
+
* <a href="#simple-example">Simple Example</a>
|
88
|
+
* <a href="#nested-example">Nested Example</a>
|
89
|
+
* <a href="#complex-example">Complex Example</a>
|
90
|
+
* <a href="#helper-methods-for-json-matcher">Helper Methods for JSON Matcher</a>
|
85
91
|
* <a href="#tips">Tips</a>
|
86
92
|
* <a href="#ok--in-minitest"><code>ok {}</code> in MiniTest</a>
|
87
93
|
* <a href="#testing-rack-application">Testing Rack Application</a>
|
@@ -165,6 +171,7 @@ Result:
|
|
165
171
|
|
166
172
|
```terminal
|
167
173
|
$ oktest test/example01_test.rb # or: ruby test/example01_test.rb
|
174
|
+
## test/example01_test.rb
|
168
175
|
* Hello
|
169
176
|
* #hello()
|
170
177
|
- [pass] returns greeting message.
|
@@ -172,6 +179,10 @@ $ oktest test/example01_test.rb # or: ruby test/example01_test.rb
|
|
172
179
|
## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
|
173
180
|
```
|
174
181
|
|
182
|
+
For accessibility reason, Oktest.rb prints passed test cases in blue color
|
183
|
+
instead of green color.
|
184
|
+
See https://accessibility.psu.edu/color/colorcoding/#RB for details.
|
185
|
+
|
175
186
|
|
176
187
|
### Assertion Failure, and Error
|
177
188
|
|
@@ -202,19 +213,20 @@ Result:
|
|
202
213
|
|
203
214
|
```terminal
|
204
215
|
$ oktest test/example02_test.rb # or: ruby test/example02_test.rb
|
216
|
+
## test/example02_test.rb
|
205
217
|
* other examples
|
206
218
|
- [Fail] example of assertion failure
|
207
219
|
- [ERROR] example of something error
|
208
220
|
----------------------------------------------------------------------
|
209
221
|
[Fail] other examples > example of assertion failure
|
210
|
-
|
222
|
+
test/example02_test.rb:9:in `block (3 levels) in <main>'
|
211
223
|
ok {1+1} == 0 # FAIL
|
212
224
|
$<actual> == $<expected>: failed.
|
213
225
|
$<actual>: 2
|
214
226
|
$<expected>: 0
|
215
227
|
----------------------------------------------------------------------
|
216
228
|
[ERROR] other examples > example of something error
|
217
|
-
|
229
|
+
test/example02_test.rb:13:in `block (3 levels) in <main>'
|
218
230
|
x = foobar # NameError
|
219
231
|
NameError: undefined local variable or method `foobar' for #<#<Class:...>:...>
|
220
232
|
----------------------------------------------------------------------
|
@@ -222,7 +234,7 @@ NameError: undefined local variable or method `foobar' for #<#<Class:...>:...>
|
|
222
234
|
```
|
223
235
|
|
224
236
|
|
225
|
-
### Skip
|
237
|
+
### Skip and Todo
|
226
238
|
|
227
239
|
test/example03_test.rb:
|
228
240
|
|
@@ -256,6 +268,7 @@ Result:
|
|
256
268
|
|
257
269
|
```terminal
|
258
270
|
$ oktest test/example03_test.rb # or: ruby test/example03_test.rb
|
271
|
+
## oktest test/example03_test.rb
|
259
272
|
* other examples
|
260
273
|
- [Skip] example of skip (reason: requires Ruby3)
|
261
274
|
- [TODO] example of todo
|
@@ -276,6 +289,7 @@ Verbose mode (default):
|
|
276
289
|
|
277
290
|
```terminal
|
278
291
|
$ oktest test/example01_test.rb -s verbose # or -sv
|
292
|
+
## test/example01_test.rb
|
279
293
|
* Hello
|
280
294
|
* #hello()
|
281
295
|
- [pass] returns greeting message.
|
@@ -287,6 +301,16 @@ Simple mode:
|
|
287
301
|
|
288
302
|
```terminal
|
289
303
|
$ oktest test/example01_test.rb -s simple # or -ss
|
304
|
+
## test/example01_test.rb
|
305
|
+
* Hello:
|
306
|
+
* #hello(): ..
|
307
|
+
## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
|
308
|
+
```
|
309
|
+
|
310
|
+
Compact mode:
|
311
|
+
|
312
|
+
```terminal
|
313
|
+
$ oktest test/example01_test.rb -s compact # or -sc
|
290
314
|
test/example01_test.rb: ..
|
291
315
|
## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
|
292
316
|
```
|
@@ -294,7 +318,7 @@ test/example01_test.rb: ..
|
|
294
318
|
Plain mode:
|
295
319
|
|
296
320
|
```terminal
|
297
|
-
$ oktest test/example01_test.rb -s
|
321
|
+
$ oktest test/example01_test.rb -s plain # or -sp
|
298
322
|
..
|
299
323
|
## total:2 (pass:2, fail:0, error:0, skip:0, todo:0) in 0.000s
|
300
324
|
```
|
@@ -311,21 +335,23 @@ Quiet mode reports progress only of failed or error test cases (and doesn't
|
|
311
335
|
report progress of passed ones), so it's output is very compact. This is
|
312
336
|
very useful for large project which contains large number of test cases.
|
313
337
|
|
338
|
+
(Note: `ruby test/example01_test.rb -s <STYLE>` is also available.)
|
339
|
+
|
314
340
|
|
315
341
|
### Run All Test Scripts Under Directory
|
316
342
|
|
317
343
|
How to run test scripts under `test` directory:
|
318
344
|
|
319
345
|
```terminal
|
320
|
-
$ ls test
|
346
|
+
$ ls test/
|
321
347
|
example01_test.rb example02_test.rb example03_test.rb
|
322
348
|
|
323
|
-
$ oktest -s
|
324
|
-
|
325
|
-
|
349
|
+
$ oktest -s compact test # or: ruby -r oktest -e 'Oktest.main' -- test -s compact
|
350
|
+
test/example01_test.rb: ..
|
351
|
+
test/example02_test.rb: fE
|
326
352
|
----------------------------------------------------------------------
|
327
353
|
[Fail] other examples > example of assertion failure
|
328
|
-
|
354
|
+
test/example02_test.rb:9:in `block (3 levels) in <top (required)>'
|
329
355
|
ok {1+1} == 0 # FAIL
|
330
356
|
-e:1:in `<main>'
|
331
357
|
$<actual> == $<expected>: failed.
|
@@ -333,12 +359,12 @@ $<actual> == $<expected>: failed.
|
|
333
359
|
$<expected>: 0
|
334
360
|
----------------------------------------------------------------------
|
335
361
|
[ERROR] other examples > example of something error
|
336
|
-
|
362
|
+
test/example02_test.rb:13:in `block (3 levels) in <top (required)>'
|
337
363
|
x = foobar # NameError
|
338
364
|
-e:1:in `<main>'
|
339
365
|
NameError: undefined local variable or method `foobar' for #<#<Class:...>:...>
|
340
366
|
----------------------------------------------------------------------
|
341
|
-
|
367
|
+
test/example03_test.rb: st
|
342
368
|
## total:6 (pass:2, fail:1, error:1, skip:1, todo:1) in 0.000s
|
343
369
|
```
|
344
370
|
|
@@ -348,7 +374,8 @@ Test script filename should be `test_xxx.rb` or `xxx_test.rb`
|
|
348
374
|
|
349
375
|
### Tag and Filtering
|
350
376
|
|
351
|
-
`topic()
|
377
|
+
`scope()`, `topic()`, and `spec()` accepts tag name, for example 'obsolete'
|
378
|
+
or 'experimental'.
|
352
379
|
|
353
380
|
test/example04_test.rb:
|
354
381
|
|
@@ -388,16 +415,16 @@ Oktest.scope do
|
|
388
415
|
end
|
389
416
|
```
|
390
417
|
|
391
|
-
It is possible to filter topics and specs by tag name
|
418
|
+
It is possible to filter topics and specs by tag name or pattern.
|
419
|
+
Pattern (!= regular expression) supports `*`, `?`, `[]` and `{}`.
|
392
420
|
|
393
421
|
```terminal
|
394
|
-
$ oktest -F tag=exp
|
395
|
-
$ oktest -F tag='*exp*'
|
396
|
-
$ oktest -F tag='{exp,old}'
|
422
|
+
$ oktest -F tag=exp test/ # filter by tag name
|
423
|
+
$ oktest -F tag='*exp*' test/ # filter by tag name pattern
|
424
|
+
$ oktest -F tag='{exp,old}' test/ # filter by multiple tag names
|
397
425
|
```
|
398
426
|
|
399
427
|
It is also possible to filter topics or specs by name.
|
400
|
-
Pattern (!= regular expression) supports `*`, `?`, `[]`, and `{}`.
|
401
428
|
|
402
429
|
```terminal
|
403
430
|
$ oktest -F topic='*Integer*' test/ # filter topics by pattern
|
@@ -407,8 +434,8 @@ $ oktest -F spec='*#[1-3]' test/ # filter specs by pattern
|
|
407
434
|
If you need negative filter, use `!=` instead of `=`.
|
408
435
|
|
409
436
|
```terminal
|
410
|
-
$ oktest -F spec!='*#5'
|
411
|
-
$ oktest -F tag!='{exp,old}'
|
437
|
+
$ oktest -F spec!='*#5' test/ # exclude spec 'example #5'
|
438
|
+
$ oktest -F tag!='{exp,old}' test/ # exclude tag='exp' or tag='old'
|
412
439
|
```
|
413
440
|
|
414
441
|
|
@@ -452,6 +479,7 @@ Result:
|
|
452
479
|
|
453
480
|
```terminal
|
454
481
|
$ ruby test/example05_test.rb
|
482
|
+
## test/example05_test.rb
|
455
483
|
* Integer
|
456
484
|
* #abs()
|
457
485
|
- When value is negative...
|
@@ -466,7 +494,7 @@ $ ruby test/example05_test.rb
|
|
466
494
|
|
467
495
|
### Optional: Unary Operators
|
468
496
|
|
469
|
-
`topic()` accepts unary `+`
|
497
|
+
`topic()` accepts unary plus (`+`) and `spec()` accepts unary minus (`-`).
|
470
498
|
This makes test scripts more readable.
|
471
499
|
|
472
500
|
<!--
|
@@ -500,7 +528,7 @@ end
|
|
500
528
|
|
501
529
|
### Generate Test Code Skeleton
|
502
530
|
|
503
|
-
`oktest
|
531
|
+
`oktest --generate` (or `oktest -G`) generates test code skeleton from ruby file.
|
504
532
|
Comment line starting with `#;` is regarded as spec description.
|
505
533
|
|
506
534
|
hello.rb:
|
@@ -523,7 +551,7 @@ end
|
|
523
551
|
Generate test code skeleton:
|
524
552
|
|
525
553
|
```terminal
|
526
|
-
$ oktest
|
554
|
+
$ oktest --generate hello.rb > test/hello_test.rb
|
527
555
|
```
|
528
556
|
|
529
557
|
test/hello_test.rb:
|
@@ -608,7 +636,7 @@ Oktest.scope do
|
|
608
636
|
end
|
609
637
|
|
610
638
|
spec "example" do
|
611
|
-
s = hello() # call
|
639
|
+
s = hello() # call it in spec block
|
612
640
|
ok {s} == "Hello!"
|
613
641
|
end
|
614
642
|
|
@@ -701,7 +729,7 @@ ok {a}.item(key, e) # alias of `ok {a}.keyval(key, e)`
|
|
701
729
|
ok {a}.length(e) # fail unless a.length == e
|
702
730
|
```
|
703
731
|
|
704
|
-
It is possible to
|
732
|
+
It is possible to chain method call of `.attr()` and `.keyval()`.
|
705
733
|
|
706
734
|
<!--
|
707
735
|
test/example11b_test.rb:
|
@@ -873,7 +901,7 @@ end
|
|
873
901
|
```
|
874
902
|
|
875
903
|
To catch subclass of error class, invoke `.raise!` instead of `.raise?`.
|
876
|
-
For example: `ok {pr}.raise!(NameError, /foobar
|
904
|
+
For example: `ok {pr}.raise!(NameError, /foobar/)`.
|
877
905
|
|
878
906
|
<!--
|
879
907
|
test/example14f_test.rb:
|
@@ -1017,8 +1045,8 @@ Oktest.scope do
|
|
1017
1045
|
after { puts "===== Inner: after =====" } # !!!!!
|
1018
1046
|
|
1019
1047
|
spec "example" do
|
1020
|
-
|
1021
|
-
|
1048
|
+
ok {1+1} == 2
|
1049
|
+
end
|
1022
1050
|
|
1023
1051
|
end
|
1024
1052
|
|
@@ -1075,7 +1103,7 @@ Oktest.scope do
|
|
1075
1103
|
end
|
1076
1104
|
```
|
1077
1105
|
|
1078
|
-
* `at_end()` can be called multiple times.
|
1106
|
+
* `at_end()` can be called multiple times in a spec.
|
1079
1107
|
* Registered blocks are invoked in reverse order at end of test case.
|
1080
1108
|
* Registered blocks of `at_end()` are invoked prior to block of `after()`.
|
1081
1109
|
* If something error raised in `at_end()`, test script execution will be
|
@@ -1085,7 +1113,7 @@ end
|
|
1085
1113
|
### Named Fixtures
|
1086
1114
|
|
1087
1115
|
`fixture() { ... }` in topic or scope block defines fixture builder,
|
1088
|
-
and `fixture()` in
|
1116
|
+
and `fixture()` in spec block returns fixture data.
|
1089
1117
|
|
1090
1118
|
test/example23_test.rb:
|
1091
1119
|
|
@@ -1144,7 +1172,7 @@ Oktest.scope do
|
|
1144
1172
|
end
|
1145
1173
|
```
|
1146
1174
|
|
1147
|
-
*
|
1175
|
+
* Fixture builders can be defined in `topic()` block as well as `Oktest.scope()` block.
|
1148
1176
|
* If fixture requires clean-up operation, call `at_end()` in `fixture()` block.
|
1149
1177
|
|
1150
1178
|
```ruby
|
@@ -1267,7 +1295,7 @@ Oktest.scope do
|
|
1267
1295
|
end
|
1268
1296
|
```
|
1269
1297
|
|
1270
|
-
*
|
1298
|
+
* The first argument of `capture_sio()` represents data from `$stdin`.
|
1271
1299
|
If it is not necessary, you can omit it like `caputre_sio() do ... end`.
|
1272
1300
|
* If you need `$stdin.tty? == true` and `$stdout.tty? == true`,
|
1273
1301
|
call `capture_sio(tty: true) do ... end`.
|
@@ -1275,7 +1303,7 @@ end
|
|
1275
1303
|
|
1276
1304
|
### `dummy_file()`
|
1277
1305
|
|
1278
|
-
`dummy_file()` creates dummy file temporarily.
|
1306
|
+
`dummy_file()` creates a dummy file temporarily.
|
1279
1307
|
|
1280
1308
|
test/example32_test.rb:
|
1281
1309
|
|
@@ -1310,12 +1338,12 @@ Oktest.scope do
|
|
1310
1338
|
end
|
1311
1339
|
```
|
1312
1340
|
|
1313
|
-
* If first argument of `dummy_file()` is nil, then it generates temporary file name automatically.
|
1341
|
+
* If the first argument of `dummy_file()` is nil, then it generates temporary file name automatically.
|
1314
1342
|
|
1315
1343
|
|
1316
1344
|
### `dummy_dir()`
|
1317
1345
|
|
1318
|
-
`dummy_dir()` creates dummy directory temporarily.
|
1346
|
+
`dummy_dir()` creates a dummy directory temporarily.
|
1319
1347
|
|
1320
1348
|
test/example33_test.rb:
|
1321
1349
|
|
@@ -1352,7 +1380,7 @@ Oktest.scope do
|
|
1352
1380
|
end
|
1353
1381
|
```
|
1354
1382
|
|
1355
|
-
* If first argument of `dummy_dir()` is nil, then it generates temorary directory name automatically.
|
1383
|
+
* If the first argument of `dummy_dir()` is nil, then it generates temorary directory name automatically.
|
1356
1384
|
|
1357
1385
|
|
1358
1386
|
### `dummy_values()`
|
@@ -1519,7 +1547,7 @@ end
|
|
1519
1547
|
|
1520
1548
|
### `recorder()`
|
1521
1549
|
|
1522
|
-
`recorder()` returns Benry::Recorder object.
|
1550
|
+
`recorder()` returns `Benry::Recorder` object.
|
1523
1551
|
See [Benry::Recorder README](https://github.com/kwatch/benry-ruby/blob/ruby/benry-recorder/README.md)
|
1524
1552
|
for detals.
|
1525
1553
|
|
@@ -1584,6 +1612,216 @@ end
|
|
1584
1612
|
|
1585
1613
|
|
1586
1614
|
|
1615
|
+
## JSON Matcher
|
1616
|
+
|
1617
|
+
Oktest.rb provides easy way to assert JSON data.
|
1618
|
+
This is very convenient feature, but don't abuse it.
|
1619
|
+
|
1620
|
+
|
1621
|
+
### Simple Example
|
1622
|
+
|
1623
|
+
<!--
|
1624
|
+
test/example41_test.rb:
|
1625
|
+
-->
|
1626
|
+
```ruby
|
1627
|
+
require 'oktest'
|
1628
|
+
require 'set' # !!!!!
|
1629
|
+
|
1630
|
+
Oktest.scope do
|
1631
|
+
topic 'JSON Example' do
|
1632
|
+
|
1633
|
+
spec "simple example" do
|
1634
|
+
actual = {
|
1635
|
+
"name": "Alice",
|
1636
|
+
"id": 1001,
|
1637
|
+
"age": 18,
|
1638
|
+
"email": "alice@example.com",
|
1639
|
+
"gender": "F",
|
1640
|
+
"deleted": false,
|
1641
|
+
"tags": ["aaa", "bbb", "ccc"],
|
1642
|
+
#"twitter": "@alice",
|
1643
|
+
}
|
1644
|
+
## assertion
|
1645
|
+
ok {JSON(actual)} === { # requires `JSON()` and `===`
|
1646
|
+
"name": "Alice", # scalar value
|
1647
|
+
"id": 1000..9999, # range object
|
1648
|
+
"age": Integer, # class object
|
1649
|
+
"email": /^\w+@example\.com$/, # regexp
|
1650
|
+
"gender": Set.new(["M", "F"]), # Set object ("M" or "F")
|
1651
|
+
"deleted": Set.new([true, false]), # boolean (true or false)
|
1652
|
+
"tags": [/^\w+$/].each, # Enumerator object (!= Array obj)
|
1653
|
+
"twitter?": /^@\w+$/, # key 'xxx?' means optional value
|
1654
|
+
}
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
end
|
1658
|
+
end
|
1659
|
+
```
|
1660
|
+
|
1661
|
+
(Note: Ruby 2.4 or older doesn't have `Set#===()`, so above code will occur error
|
1662
|
+
in Ruby 2.4 or older. Please add the folllowing hack in your test script.)
|
1663
|
+
|
1664
|
+
```ruby
|
1665
|
+
require 'set'
|
1666
|
+
unless Set.instance_methods(false).include?(:===) # for Ruby 2.4 or older
|
1667
|
+
class Set; alias === include?; end
|
1668
|
+
end
|
1669
|
+
```
|
1670
|
+
|
1671
|
+
Notice that `Enumerator` has different meaning from `Array` in JSON matcher.
|
1672
|
+
|
1673
|
+
```ruby
|
1674
|
+
actual = {"tags": ["foo", "bar", "baz"]}
|
1675
|
+
|
1676
|
+
## Array
|
1677
|
+
ok {JSON(actual)} == {"tags": ["foo", "bar", "baz"]}
|
1678
|
+
|
1679
|
+
## Enumerator
|
1680
|
+
ok {JSON(actual)} == {"tags": [/^\w+$/].each}
|
1681
|
+
```
|
1682
|
+
|
1683
|
+
|
1684
|
+
### Nested Example
|
1685
|
+
|
1686
|
+
<!--
|
1687
|
+
test/example42_test.rb:
|
1688
|
+
-->
|
1689
|
+
```ruby
|
1690
|
+
require 'oktest'
|
1691
|
+
require 'set' # !!!!!
|
1692
|
+
|
1693
|
+
Oktest.scope do
|
1694
|
+
topic 'JSON Example' do
|
1695
|
+
|
1696
|
+
spec "nested example" do
|
1697
|
+
actual = {
|
1698
|
+
"teams": [
|
1699
|
+
{
|
1700
|
+
"team": "Section 9",
|
1701
|
+
"members": [
|
1702
|
+
{"id": 2500, "name": "Aramaki", "gender": "M"},
|
1703
|
+
{"id": 2501, "name": "Motoko" , "gender": "F"},
|
1704
|
+
{"id": 2502, "name": "Batou" , "gender": "M"},
|
1705
|
+
],
|
1706
|
+
"leader": "Aramaki",
|
1707
|
+
},
|
1708
|
+
{
|
1709
|
+
"team": "SOS Brigade",
|
1710
|
+
"members": [
|
1711
|
+
{"id": 1001, "name": "Haruhi", "gender": "F"},
|
1712
|
+
{"id": 1002, "name": "Mikuru", "gender": "F"},
|
1713
|
+
{"id": 1003, "name": "Yuki" , "gender": "F"},
|
1714
|
+
{"id": 1004, "name": "Itsuki", "gender": "M"},
|
1715
|
+
{"id": 1005, "name": "Kyon" , "gender": "M"},
|
1716
|
+
],
|
1717
|
+
},
|
1718
|
+
],
|
1719
|
+
}
|
1720
|
+
## assertion
|
1721
|
+
ok {JSON(actual)} === { # requires `JSON()` and `===`
|
1722
|
+
"teams": [
|
1723
|
+
{
|
1724
|
+
"team": String,
|
1725
|
+
"members": [
|
1726
|
+
{"id": 1000..9999, "name": String, "gender": Set.new(["M", "F"])}
|
1727
|
+
].each, # Enumerator object (!= Array obj)
|
1728
|
+
"leader?": String, # key 'xxx?' means optional value
|
1729
|
+
}
|
1730
|
+
].each, # Enumerator object (!= Array obj)
|
1731
|
+
}
|
1732
|
+
end
|
1733
|
+
|
1734
|
+
end
|
1735
|
+
end
|
1736
|
+
```
|
1737
|
+
|
1738
|
+
|
1739
|
+
### Complex Example
|
1740
|
+
|
1741
|
+
* `OR(x, y, z)` matches to `x`, `y`, or `z`.
|
1742
|
+
* `AND(x, y, z)` matches to `x`, `y`, and `z`.
|
1743
|
+
* Key `"*"` matches to any key of hash object.
|
1744
|
+
* `Any()` matches to anything.
|
1745
|
+
|
1746
|
+
<!--
|
1747
|
+
test/example43_test.rb:
|
1748
|
+
-->
|
1749
|
+
```ruby
|
1750
|
+
require 'oktest'
|
1751
|
+
require 'set'
|
1752
|
+
|
1753
|
+
Oktest.scope do
|
1754
|
+
topic 'JSON Example' do
|
1755
|
+
|
1756
|
+
spec "OR() example" do
|
1757
|
+
ok {JSON({"val": "123"})} === {"val": OR(String, Integer)} # OR()
|
1758
|
+
ok {JSON({"val": 123 })} === {"val": OR(String, Integer)} # OR()
|
1759
|
+
end
|
1760
|
+
|
1761
|
+
spec "AND() example" do
|
1762
|
+
ok {JSON({"val": "123"})} === {"val": AND(String, /^\d+$/)} # AND()
|
1763
|
+
ok {JSON({"val": 123 })} === {"val": AND(Integer, 1..1000)} # AND()
|
1764
|
+
end
|
1765
|
+
|
1766
|
+
spec "`*` and `ANY` example" do
|
1767
|
+
ok {JSON({"name": "Bob", "age": 20})} === {"*": Any()} # '*' and Any()
|
1768
|
+
end
|
1769
|
+
|
1770
|
+
spec "complex exapmle" do
|
1771
|
+
actual = {
|
1772
|
+
"item": "awesome item",
|
1773
|
+
"colors": ["red", "#cceeff", "green", "#fff"],
|
1774
|
+
"memo": "this is awesome.",
|
1775
|
+
"url": "https://example.com/awesome",
|
1776
|
+
}
|
1777
|
+
## assertion
|
1778
|
+
color_names = ["red", "blue", "green", "white", "black"]
|
1779
|
+
color_pat = /^\#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/
|
1780
|
+
ok {JSON(actual)} === {
|
1781
|
+
"colors": [
|
1782
|
+
AND(String, OR(Set.new(color_names), color_pat)), # AND() and OR()
|
1783
|
+
].each,
|
1784
|
+
"*": Any(), # match to any key (`"*"`) and value (`ANY`)
|
1785
|
+
}
|
1786
|
+
end
|
1787
|
+
|
1788
|
+
end
|
1789
|
+
end
|
1790
|
+
```
|
1791
|
+
|
1792
|
+
(Note: `/^\d+$/` implies String value, and `1..100` implies Integer value.)
|
1793
|
+
|
1794
|
+
```ruby
|
1795
|
+
## No need to write:
|
1796
|
+
## ok {JSON{...}} === {"val": AND(String, /^\d+$/)}
|
1797
|
+
## ok {JSON{...}} === {"val": AND(Integer, 1..100)}
|
1798
|
+
ok {JSON({"val": "A"})} === {"val": /^\d+$/} # implies String value
|
1799
|
+
ok {JSON({"val": 99 })} === {"val": 1..100} # implies Integer value
|
1800
|
+
```
|
1801
|
+
|
1802
|
+
|
1803
|
+
### Helper Methods for JSON Matcher
|
1804
|
+
|
1805
|
+
Oktest.rb provides some helper methods and objects:
|
1806
|
+
|
1807
|
+
* `Enum(x, y, z)` is almost same as `Set.new([x, y, z])`.
|
1808
|
+
* `Bool()` is same as `Enum(true, false)`.
|
1809
|
+
* `Length(3)` matches to length 3, and `Length(1..3)` matches to length 1..3.
|
1810
|
+
|
1811
|
+
<!--
|
1812
|
+
test/example44_test.rb:
|
1813
|
+
-->
|
1814
|
+
```ruby
|
1815
|
+
actual = {"gender": "M", "deleted": false, "code": "ABCD1234"}
|
1816
|
+
ok {JSON(actual)} == {
|
1817
|
+
"gender": Enum("M", "F"), # same as Set.new(["M", "F"])
|
1818
|
+
"deleted": Bool(), # same as Enum(true, false)
|
1819
|
+
"code": Length(6..10), # code length should be 6..10
|
1820
|
+
}
|
1821
|
+
```
|
1822
|
+
|
1823
|
+
|
1824
|
+
|
1587
1825
|
## Tips
|
1588
1826
|
|
1589
1827
|
|
@@ -1592,7 +1830,7 @@ end
|
|
1592
1830
|
If you want to use `ok {actual} == expected` style assertion in MiniTest,
|
1593
1831
|
install `minitest-ok` gem instead of `otest` gem.
|
1594
1832
|
|
1595
|
-
test/
|
1833
|
+
test/example51_test.rb:
|
1596
1834
|
|
1597
1835
|
```ruby
|
1598
1836
|
require 'minitest/spec'
|
@@ -1615,7 +1853,7 @@ See [minitest-ok README](https://github.com/kwatch/minitest-ok) for details.
|
|
1615
1853
|
|
1616
1854
|
`rack-test_app` gem will help you to test Rack application very well.
|
1617
1855
|
|
1618
|
-
test/
|
1856
|
+
test/example52_test.rb:
|
1619
1857
|
|
1620
1858
|
```ruby
|
1621
1859
|
require 'rack'
|
@@ -1648,7 +1886,7 @@ Oktest.scope do
|
|
1648
1886
|
end
|
1649
1887
|
```
|
1650
1888
|
|
1651
|
-
Defining helper
|
1889
|
+
Defining helper methods per topic may help you.
|
1652
1890
|
|
1653
1891
|
```ruby
|
1654
1892
|
$http = http # !!!!
|
@@ -1688,7 +1926,7 @@ end
|
|
1688
1926
|
|
1689
1927
|
Oktest.rb provides `Traverser` class which implements Visitor pattern.
|
1690
1928
|
|
1691
|
-
test/
|
1929
|
+
test/example54_test.rb:
|
1692
1930
|
|
1693
1931
|
```ruby
|
1694
1932
|
require 'oktest'
|
@@ -1745,8 +1983,8 @@ MyTraverser.new.start()
|
|
1745
1983
|
Result:
|
1746
1984
|
|
1747
1985
|
```terminal
|
1748
|
-
$ ruby test/
|
1749
|
-
# scope: test/
|
1986
|
+
$ ruby test/example54_test.rb
|
1987
|
+
# scope: test/example54_test.rb
|
1750
1988
|
+ topic: Example Topic
|
1751
1989
|
- spec: sample #1
|
1752
1990
|
- spec: sample #2
|
@@ -1826,10 +2064,8 @@ ruby run_all.rb | tail -5
|
|
1826
2064
|
|
1827
2065
|
### `--faster` Option
|
1828
2066
|
|
1829
|
-
|
1830
|
-
|
1831
|
-
very larget project and you want to run test scripts as fast as possible,
|
1832
|
-
try `--faster` option of `oktest` command.
|
2067
|
+
If you are working in very larget project and you want to run test scripts
|
2068
|
+
as fast as possible, try `--faster` option of `oktest` command.
|
1833
2069
|
|
1834
2070
|
```terminal
|
1835
2071
|
$ oktest -s quiet --faster test/ ## only for very large project
|