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