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.
data/oktest.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  ###
4
- ### $Release: 1.0.0 $
4
+ ### $Release: 1.1.1 $
5
5
  ### $License: MIT License $
6
6
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
7
7
  ###
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.name = "oktest"
14
14
  s.author = "kwatch"
15
15
  s.email = "kwatch@gmail.com"
16
- s.version = "$Release: 1.0.0 $".split()[1]
16
+ s.version = "$Release: 1.1.1 $".split()[1]
17
17
  s.license = "MIT"
18
18
  s.platform = Gem::Platform::RUBY
19
19
  s.homepage = "https://github.com/kwatch/oktest/tree/ruby"
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  ###
4
- ### $Release: 1.0.0 $
4
+ ### $Release: 1.1.1 $
5
5
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
6
  ### $License: MIT License $
7
7
  ###
@@ -170,6 +170,15 @@ END
170
170
  " $<expected>: \"str\""
171
171
  FAIL!(errmsg) { ok {String}.NOT === 'str' }
172
172
  end
173
+ it "[!mjh4d] raises error when combination of 'not_ok()' and matcher object." do
174
+ errmsg = "negative `===` is not available with matcher object."
175
+ assert_exc(Oktest::OktestError, errmsg) do
176
+ not_ok {Oktest::JsonMatcher.new({})} === {}
177
+ end
178
+ assert_exc(Oktest::OktestError, errmsg) do
179
+ ok {Oktest::JsonMatcher.new({})}.NOT === {}
180
+ end
181
+ end
173
182
  end
174
183
 
175
184
  describe '>' do
@@ -423,11 +432,11 @@ describe '#method_missing()' do
423
432
  assert NoMethodError < NameError, "NoMethodError extends NameError"
424
433
  ERROR!(NoMethodError, /foobar/) { ok {pr}.raise?(NameError) }
425
434
  end
426
- it "[!hwg0z] compares error class with '.is_a?' if 'subclass: true' specified." do
435
+ it "[!hwg0z] compares error class with '.is_a?' if '_subclass: true' specified." do
427
436
  pr = proc { "SOS".foobar }
428
437
  PASS! { ok {pr}.raise?(NoMethodError, nil) }
429
438
  assert NoMethodError < NameError, "NoMethodError extends NameError"
430
- PASS! { ok {pr}.raise?(NameError, nil, subclass: true) }
439
+ PASS! { ok {pr}.raise?(NameError, nil, _subclass: true) }
431
440
  end
432
441
  it "[!4n3ed] reraises if exception is not matched to specified error class." do
433
442
  pr = proc { "SOS".sos }
@@ -483,11 +492,11 @@ describe '#method_missing()' do
483
492
  assert NoMethodError < NameError, "NoMethodError extends NameError"
484
493
  ERROR!(NoMethodError) { ok {pr}.NOT.raise?(NameError) }
485
494
  end
486
- it "[!34nd8] compares error class with '.is_a?' if 'subclass: true' specified." do
495
+ it "[!34nd8] compares error class with '.is_a?' if '_subclass: true' specified." do
487
496
  pr = proc { "SOS".foobar }
488
497
  FAIL!(/foobar/) { ok {pr}.NOT.raise?(NoMethodError, nil) }
489
498
  assert NoMethodError < NameError, "NoMethodError extends NameError"
490
- FAIL!(/foobar/) { ok {pr}.NOT.raise?(NameError, nil, subclass: true) }
499
+ FAIL!(/foobar/) { ok {pr}.NOT.raise?(NameError, nil, _subclass: true) }
491
500
  end
492
501
  it "[!shxne] reraises exception if different from specified error class." do
493
502
  pr = proc { 1/0 }
@@ -814,4 +823,60 @@ describe '#method_missing()' do
814
823
  end
815
824
  end
816
825
 
826
+ describe '#JSON()' do
827
+ it "[!n0k03] creates JsonMatcher object." do
828
+ o = JSON({})
829
+ assert_eq o.class, Oktest::JsonMatcher
830
+ end
831
+ end
832
+
833
+ describe '#Enum()' do
834
+ it "[!fbfr0] creates Enum object which is a subclass of Set." do
835
+ o = Enum("a", "b", "c")
836
+ assert_eq o.class, Oktest::JsonMatcher::Enum
837
+ assert o.class < Set
838
+ assert_eq (o === "a"), true
839
+ assert_eq (o === "b"), true
840
+ assert_eq (o === "c"), true
841
+ assert_eq (o === "d"), false
842
+ end
843
+ end
844
+
845
+ describe '#Bool()' do
846
+ it "[!vub5j] creates a set of true and false." do
847
+ assert_eq Bool().class, Oktest::JsonMatcher::Enum
848
+ assert Bool() === true
849
+ assert Bool() === false
850
+ assert_eq (Bool() === 1), false
851
+ assert_eq (Bool() === 0), false
852
+ end
853
+ end
854
+
855
+ describe '#OR()' do
856
+ it "[!9e8im] creates `OR` object." do
857
+ o = OR(1, 2, 3)
858
+ assert_eq o.class, Oktest::JsonMatcher::OR
859
+ end
860
+ end
861
+
862
+ describe '#AND()' do
863
+ it "[!38jln] creates `AND` object." do
864
+ o = AND(4, 5, 6)
865
+ assert_eq o.class, Oktest::JsonMatcher::AND
866
+ end
867
+ end
868
+
869
+ describe '#Length()' do
870
+ it "[!qqas3] creates Length object." do
871
+ o = Length(3)
872
+ assert_eq o.class, Oktest::JsonMatcher::Length
873
+ end
874
+ end
875
+
876
+ describe '#Any()' do
877
+ it "[!dlo1o] creates an 'Any' object." do
878
+ assert_eq Any().class, Oktest::JsonMatcher::Any
879
+ end
880
+ end
881
+
817
882
  end
data/test/filter_test.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  ###
4
- ### $Release: 1.0.0 $
4
+ ### $Release: 1.1.1 $
5
5
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
6
  ### $License: MIT License $
7
7
  ###
@@ -188,7 +188,7 @@ class Filter_TC < TC
188
188
  Oktest::Runner.new(reporter).start()
189
189
  end
190
190
  assert_eq serr, ""
191
- return sout.sub(/^## total:.*\n/, '')
191
+ return sout.sub(/^## total:.*\n/, '').sub(/^## test\/filter_test\.rb\n/, '')
192
192
  end
193
193
 
194
194
  def uncolor(s)
data/test/fixture_test.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  ###
4
- ### $Release: 1.0.0 $
4
+ ### $Release: 1.1.1 $
5
5
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
6
  ### $License: MIT License $
7
7
  ###
@@ -1,5 +1,5 @@
1
1
  ###
2
- ### $Release: 1.0.0 $
2
+ ### $Release: 1.1.1 $
3
3
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
4
4
  ### $License: MIT License $
5
5
  ###
data/test/helper_test.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  ###
2
- ### $Release: 1.0.0 $
2
+ ### $Release: 1.1.1 $
3
3
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
4
4
  ### $License: MIT License $
5
5
  ###
data/test/initialize.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  ###
4
- ### $Release: 1.0.0 $
4
+ ### $Release: 1.1.1 $
5
5
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
6
  ### $License: MIT License $
7
7
  ###
@@ -12,3 +12,10 @@ end
12
12
 
13
13
  require_relative './tc'
14
14
  require 'oktest'
15
+
16
+
17
+ # for Ruby 2.4 or older
18
+ require 'set'
19
+ unless Set.instance_methods(false).include?(:===)
20
+ class Set; alias === include?; end
21
+ end
data/test/mainapp_test.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  ###
2
- ### $Release: 1.0.0 $
2
+ ### $Release: 1.1.1 $
3
3
  ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
4
4
  ### $License: MIT License $
5
5
  ###
@@ -201,7 +201,7 @@ END
201
201
  Usage: #{File.basename($0)} [<options>] [<file-or-directory>...]
202
202
  -h, --help : show help
203
203
  --version : print version
204
- -s <STYLE> : report style (verbose/simple/plain/quiet, or v/s/p/q)
204
+ -s <REPORT-STYLE> : verbose/simple/compact/plain/quiet, or v/s/c/p/q
205
205
  -F <PATTERN> : filter topic or spec with pattern (see below)
206
206
  --color[={on|off}] : enable/disable output coloring forcedly
207
207
  -C, --create : print test code skeleton
@@ -241,7 +241,7 @@ END
241
241
  end
242
242
 
243
243
  it "[!qqizl] '--version' option prints version number." do
244
- expected = '$Release: 1.0.0 $'.split()[1] + "\n"
244
+ expected = '$Release: 1.1.1 $'.split()[1] + "\n"
245
245
  #
246
246
  ret, sout, serr = run("--version")
247
247
  assert_eq ret, 0
@@ -251,6 +251,7 @@ END
251
251
 
252
252
  it "[!0qd92] '-s verbose' or '-sv' option prints test results in verbose mode." do
253
253
  expected = <<END
254
+ ## _tmp_test.rb
254
255
  * <b>Parent</b>
255
256
  * <b>Child1</b>
256
257
  - [<B>pass</B>] 1+1 should be 2
@@ -272,9 +273,12 @@ END
272
273
  assert_eq serr, ""
273
274
  end
274
275
 
275
- it "[!ef5v7] '-s simple' or '-ss' option prints test results in simple mode." do
276
+ it "[!zfdr5] '-s simple' or '-ss' option prints test results in simple mode." do
276
277
  expected = <<END
277
- #{@testfile}: <B>.</B><B>.</B><R>f</R><R>E</R><Y>s</Y><Y>t</Y><B>.</B><B>.</B>
278
+ ## _tmp_test.rb
279
+ * <b>Parent</b>: <B>.</B><B>.</B>
280
+ * <b>Child1</b>: <B>.</B><B>.</B>
281
+ * <b>Child2</b>: <R>f</R><R>E</R>
278
282
  ----------------------------------------------------------------------
279
283
  END
280
284
  #
@@ -289,6 +293,23 @@ END
289
293
  assert_eq serr, ""
290
294
  end
291
295
 
296
+ it "[!ef5v7] '-s compact' or '-sc' option prints test results in compact mode." do
297
+ expected = <<END
298
+ #{@testfile}: <B>.</B><B>.</B><R>f</R><R>E</R><Y>s</Y><Y>t</Y><B>.</B><B>.</B>
299
+ ----------------------------------------------------------------------
300
+ END
301
+ #
302
+ ret, sout, serr = run("-sc", @testfile)
303
+ assert_eq ret, 2
304
+ assert edit_actual(sout).start_with?(edit_expected(expected)), "invalid testcase output"
305
+ assert_eq serr, ""
306
+ #
307
+ ret, sout, serr = run("-s", "compact", @testfile)
308
+ assert_eq ret, 2
309
+ assert edit_actual(sout).start_with?(edit_expected(expected)), "invalid testcase output"
310
+ assert_eq serr, ""
311
+ end
312
+
292
313
  it "[!244te] '-s plain' or '-sp' option prints test results in plain mode." do
293
314
  expected = <<END
294
315
  <B>.</B><B>.</B><R>f</R><R>E</R><Y>s</Y><Y>t</Y><B>.</B><B>.</B>
@@ -325,6 +346,7 @@ END
325
346
 
326
347
  it "[!yz7g5] '-F topic=...' option filters topics." do
327
348
  expected = <<END
349
+ ## _tmp_test.rb
328
350
  * <b>Parent</b>
329
351
  * <b>Child1</b>
330
352
  - [<B>pass</B>] 1+1 should be 2
@@ -340,6 +362,7 @@ END
340
362
 
341
363
  it "[!ww2mp] '-F spec=...' option filters specs." do
342
364
  expected = <<END
365
+ ## _tmp_test.rb
343
366
  * <b>Parent</b>
344
367
  * <b>Child1</b>
345
368
  - [<B>pass</B>] 1-1 should be 0
@@ -354,6 +377,7 @@ END
354
377
 
355
378
  it "[!8uvib] '-F tag=...' option filters by tag name." do
356
379
  expected = <<'END'
380
+ ## _tmp_test.rb
357
381
  * <b>Parent</b>
358
382
  * <b>Child1</b>
359
383
  - [<B>pass</B>] 1-1 should be 0
@@ -373,6 +397,7 @@ END
373
397
 
374
398
  it "[!m0iwm] '-F sid=...' option filters by spec id." do
375
399
  expected = <<'END'
400
+ ## _tmp_test.rb
376
401
  * <b>Parent</b>
377
402
  - <b>When x is negative</b>
378
403
  - [<B>pass</B>] [!6hs1j] x*x is positive.
@@ -387,6 +412,7 @@ END
387
412
 
388
413
  it "[!noi8i] '-F' option supports negative filter." do
389
414
  expected = <<'END'
415
+ ## _tmp_test.rb
390
416
  * <b>Parent</b>
391
417
  * <b>Child1</b>
392
418
  - [<B>pass</B>] 1+1 should be 2
@@ -408,6 +434,17 @@ END
408
434
  end
409
435
  end
410
436
 
437
+ it "[!j01y7] if filerting by '-F' matched nothing, then prints zero result." do
438
+ expected = <<'END'
439
+ ## total:0 (pass:0, fail:0, error:0, skip:0, todo:0) in 0.000s
440
+ END
441
+ #
442
+ ret, sout, serr = run("-F", "tag=blablabla", @testfile)
443
+ assert_eq ret, 0
444
+ assert_eq edit_actual(sout), edit_expected(expected)
445
+ assert_eq serr, ""
446
+ end
447
+
411
448
  it "[!6ro7j] '--color=on' option enables output coloring forcedly." do
412
449
  [true, false].each do |bool|
413
450
  [true, false].each do |tty|
@@ -0,0 +1,424 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+ ### $Release: 1.1.1 $
5
+ ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
+ ### $License: MIT License $
7
+ ###
8
+
9
+ require_relative './initialize'
10
+ require 'set'
11
+
12
+
13
+ class Matcher_TC < TC
14
+
15
+ describe '#===' do
16
+ it "[!spybn] raises NotImplementedError." do
17
+ errmsg = "Oktest::Matcher#===(): not implemented yet."
18
+ assert_exc(NotImplementedError, errmsg) do
19
+ Oktest::Matcher.new(nil) === nil
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '#==' do
25
+ it "[!ymt1b] raises OktestError." do
26
+ errmsg = "JSON(): use `===` instead of `==`."
27
+ assert_exc(Oktest::OktestError, errmsg) do
28
+ Oktest::Matcher.new(nil) == nil
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#fail()' do
34
+ it "[!8qpsd] raises assertion error." do
35
+ errmsg = "<<errmsg>>"
36
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
37
+ Oktest::Matcher.new(nil).fail("<<errmsg>>")
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+
45
+ class JsonMatcher_TC < TC
46
+
47
+ def JSON(x)
48
+ return Oktest::JsonMatcher.new(x)
49
+ end
50
+
51
+ def OR(*args)
52
+ return Oktest::JsonMatcher::OR.new(*args)
53
+ end
54
+
55
+ def AND(*args)
56
+ return Oktest::JsonMatcher::AND.new(*args)
57
+ end
58
+
59
+ def ANY()
60
+ return Oktest::JsonMatcher::Any.new
61
+ end
62
+
63
+ describe '#===' do
64
+ it "[!4uf1o] raises assertion error when JSON not matched." do
65
+ assert_exc(Oktest::FAIL_EXCEPTION) do
66
+ JSON({"status": "ok"}) === {"status": "OK"}
67
+ end
68
+ end
69
+ it "[!0g0u4] returns true when JSON matched." do
70
+ result = JSON({"status": "ok"}) === {"status": "ok"}
71
+ assert_eq result, true
72
+ end
73
+ it "[!1ukbv] scalar value matches to integer, string, bool, and so son." do
74
+ actual = {"name": "Alice", "age": 20, "deleted": false}
75
+ result = JSON(actual) === {"name": "Alice", "age": 20, "deleted": false}
76
+ assert_eq result, true
77
+ #
78
+ errmsg = ("$<JSON>[\"name\"]: $<expected> === $<actual> : failed.\n"\
79
+ " $<actual>: \"Alice\"\n"\
80
+ " $<expected>: \"alice\"\n")
81
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
82
+ JSON(actual) === {"name": "alice", "age": 20, "deleted": false}
83
+ end
84
+ end
85
+ it "[!8o55d] class object matches to instance object." do
86
+ actual = {"name": "Alice", "age": 20, "deleted": false}
87
+ result = JSON(actual) === {"name": String, "age": Integer, "deleted": FalseClass}
88
+ assert_eq result, true
89
+ #
90
+ errmsg = ("$<JSON>[\"deleted\"]: $<expected> === $<actual> : failed.\n"\
91
+ " $<actual>: false\n"\
92
+ " $<expected>: TrueClass\n")
93
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
94
+ JSON(actual) === {"name": String, "age": Integer, "deleted": TrueClass}
95
+ end
96
+ end
97
+ it "[!s625d] regexp object matches to string value." do
98
+ actual = {"email": "alice@example.com"}
99
+ result = JSON(actual) === {"email": /^\w[-.\w]+@example\.(com|net|org)$/}
100
+ assert_eq result, true
101
+ #
102
+ errmsg = ("$<JSON>[\"email\"]: $<expected> === $<actual> : failed.\n"\
103
+ " $<actual>: \"alice@example.com\"\n"\
104
+ " $<expected>: /^\\w[-.\\w]+@example\\.org$/\n")
105
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
106
+ JSON(actual) === {"email": /^\w[-.\w]+@example\.org$/}
107
+ end
108
+ end
109
+ it "[!aqkk0] range object matches to scalar value." do
110
+ actual = {"int": 5, "float": 3.14, "str": "abc"}
111
+ result = JSON(actual) === {"int": 1..10, "float": 3.1..3.2, "str": "aaa".."zzz"}
112
+ assert_eq result, true
113
+ #
114
+ errmsg = ("$<JSON>[\"int\"]: $<expected> === $<actual> : failed.\n"\
115
+ " $<actual>: 5\n"\
116
+ " $<expected>: 1...5\n")
117
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
118
+ JSON(actual) === {"int": 1...5, "float": 3.1..3.2, "str": "aaa".."zzz"}
119
+ end
120
+ end
121
+ it "[!4ymj2] fails when actual value is not matched to item class of range object." do
122
+ actual = {"val": 1.5}
123
+ errmsg = ("$<JSON>[\"val\"]: expected #{1.class.name} value, but got Float value.\n"\
124
+ " $<actual>: 1.5\n"\
125
+ " $<expected>: 1..10\n")
126
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
127
+ JSON(actual) === {"val": 1..10}
128
+ end
129
+ end
130
+ it "[!a7bfs] Set object matches to enum value." do
131
+ actual = {"gender": "female"}
132
+ result = JSON(actual) === {"gender": Set.new(["male", "female"])}
133
+ assert_eq result, true
134
+ #
135
+ errmsg = ("$<JSON>[\"gender\"]: $<expected> === $<actual> : failed.\n"\
136
+ " $<actual>: \"female\"\n"\
137
+ " $<expected>: #<Set: {\"M\", \"F\"}>\n")
138
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
139
+ JSON(actual) === {"gender": Set.new(["M", "F"])}
140
+ end
141
+ end
142
+ it "[!sh5cg] Enumerator object matches to repeat of rule." do
143
+ actual = {"tags": ["foo", "bar", "baz"]}
144
+ result = JSON(actual) === {"tags": [String].each}
145
+ assert_eq result, true
146
+ #
147
+ errmsg = ("$<JSON>[\"tags\"][0]: $<expected> === $<actual> : failed.\n"\
148
+ " $<actual>: \"foo\"\n"\
149
+ " $<expected>: Integer\n")
150
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
151
+ JSON(actual) === {"tags": [Integer].each}
152
+ end
153
+ end
154
+ it "[!ljrmc] fails when expected is an Enumerator object and actual is not an array." do
155
+ actual = {"tags": "foo"}
156
+ errmsg = ("$<JSON>[\"tags\"]: Array value expected but got String value.\n"\
157
+ " $<actual>: \"foo\"\n"\
158
+ " $<expected>: [String].each\n")
159
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
160
+ JSON(actual) === {"tags": [String].each}
161
+ end
162
+ end
163
+ it "[!lh6d6] compares array items recursively." do
164
+ actual = {"items": [{"name": "Alice", "id": 101}, {"name": "Bob"}]}
165
+ result = JSON(actual) === {
166
+ "items": [{"name": String, "id?": 100..999}].each
167
+ }
168
+ assert_eq result, true
169
+ #
170
+ errmsg = ("$<JSON>[\"items\"][0][\"id\"]: $<expected> === $<actual> : failed.\n"\
171
+ " $<actual>: 101\n"\
172
+ " $<expected>: 1000..9999\n")
173
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
174
+ JSON(actual) === {
175
+ "items": [{"name": String, "id?": 1000..9999}].each
176
+ }
177
+ end
178
+ end
179
+ it "[!bz74w] fails when array lengths are different." do
180
+ actual = {"arr": ["A", "B", "C"]}
181
+ errmsg = ("$<JSON>[\"arr\"]: $<actual>.length == $<expected>.length : failed.\n"\
182
+ " $<actual>.length: 3\n"\
183
+ " $<expected>.length: 4\n"\
184
+ " $<actual>: [\"A\", \"B\", \"C\"]\n"\
185
+ " $<expected>: [\"A\", \"B\", \"C\", \"D\"]\n")
186
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
187
+ JSON(actual) === {"arr": ["A", "B", "C", "D"]}
188
+ end
189
+ end
190
+ it "[!fmxyg] compares hash objects recursively." do
191
+ actual = {
192
+ "owner": {"name": "Alice", "age": 20},
193
+ "item": {"id": 10001, "name": "Something", "price": 500},
194
+ }
195
+ result = JSON(actual) === {
196
+ "owner": {"name": String, "age": 0..100},
197
+ "item": {"id": 1..99999, "name": String, "price?": Numeric},
198
+ }
199
+ assert_eq result, true
200
+ #
201
+ errmsg = ("$<JSON>[\"item\"][\"price\"]: $<expected> === $<actual> : failed.\n"\
202
+ " $<actual>: 500\n"\
203
+ " $<expected>: Float\n")
204
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
205
+ JSON(actual) === {
206
+ "owner": {"name": String, "age": 0..100},
207
+ "item": {"id": 1..99999, "name": String, "price?": Float},
208
+ }
209
+ end
210
+ end
211
+ it "[!rkv0z] compares two hashes with converting keys into string." do
212
+ actual1 = {k1: "A", k2: "B"}
213
+ result = JSON(actual1) === {"k1"=>"A", "k2"=>"B"}
214
+ assert_eq result, true
215
+ #
216
+ actual2 = {"k1"=>"A", "k2"=>"B"}
217
+ result = JSON(actual2) === {k1: "A", k2: "B"}
218
+ assert_eq result, true
219
+ end
220
+ it "[!jbyv6] key 'aaa?' represents optional key." do
221
+ actual1 = {"name": "alice", "birth": "2000-01-01"}
222
+ result = JSON(actual1) === {"name": "alice", "birth?": "2000-01-01"}
223
+ assert_eq result, true
224
+ #
225
+ actual2 = {"name": "alice"}
226
+ result = JSON(actual2) === {"name": "alice", "birth?": "2000-01-01"}
227
+ assert_eq result, true
228
+ #
229
+ actual3 = {"name": "alice", "birth": nil}
230
+ result = JSON(actual3) === {"name": "alice", "birth?": "2000-01-01"}
231
+ assert_eq result, true
232
+ #
233
+ actual4 = {"name": "alice", "birth?": "2000-01-01"} # TODO
234
+ result = JSON(actual4) === {"name": "alice", "birth?": "2000-01-01"}
235
+ assert_eq result, true
236
+ end
237
+ it "[!mpbvu] fails when unexpected key exists in actual hash." do
238
+ actual = {"id": 101, "name": "Alice"}
239
+ errmsg = ("$<JSON>: key \"gender\" expected but not found.\n"\
240
+ " $<actual>.keys: \"id\", \"name\"\n"\
241
+ " $<expected>.keys: \"gender\", \"id\", \"name\"\n")
242
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
243
+ JSON(actual) === {"id": Integer, "name": String, "gender": String}
244
+ end
245
+ end
246
+ it "[!4oasq] fails when expected key not exist in actual hash." do
247
+ actual = {"id": 101, "name": "Alice"}
248
+ errmsg = ("$<JSON>[\"id\"]: unexpected key.\n"\
249
+ " $<actual>: 101\n")
250
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
251
+ JSON(actual) === {"name": String}
252
+ end
253
+ end
254
+ it "[!eqr3b] `OR()` matches to any of arguments." do
255
+ result = JSON({"val": 123}) === {"val": OR(String, Integer)}
256
+ assert_eq result, true
257
+ result = JSON({"val": "123"}) === {"val": OR(String, Integer)}
258
+ assert_eq result, true
259
+ #
260
+ errmsg = ("$<JSON>[\"val\"]: $<expected> === $<actual> : failed.\n"\
261
+ " $<actual>: 3.14\n"\
262
+ " $<expected>: OR(String, Integer)\n")
263
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
264
+ JSON({"val": 3.14}) === {"val": OR(String, Integer)}
265
+ end
266
+ end
267
+ it "[!4hk96] `AND()` matches to all of arguments." do
268
+ result = JSON({"val": "alice"}) === {"val": AND(String, /^[a-z]+$/)}
269
+ assert_eq result, true
270
+ #
271
+ errmsg = ("$<JSON>[\"val\"]: $<expected> === $<actual> : failed.\n"\
272
+ " $<actual>: \"Alice\"\n"\
273
+ " $<expected>: AND(/^[a-z]+$/)\n")
274
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
275
+ JSON({"val": "Alice"}) === {"val": AND(String, /^[a-z]+$/)}
276
+ end
277
+ end
278
+ it "[!5ybfg] `OR()` can contain `AND()`." do
279
+ expected = {"val": OR(AND(String, /^\d+$/), AND(Integer, 100..999))}
280
+ result = JSON({"val": "123"}) === expected
281
+ assert_eq result, true
282
+ result = JSON({"val": 123}) === expected
283
+ assert_eq result, true
284
+ #
285
+ errmsg = ("$<JSON>[\"val\"]: $<expected> === $<actual> : failed.\n"\
286
+ " $<actual>: \"abc\"\n"\
287
+ " $<expected>: OR(AND(String, /^\\d+$/), AND(Integer, 100..999))\n")
288
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
289
+ JSON({"val": "abc"}) === expected
290
+ end
291
+ errmsg = ("$<JSON>[\"val\"]: $<expected> === $<actual> : failed.\n"\
292
+ " $<actual>: 99\n"\
293
+ " $<expected>: OR(AND(String, /^\\d+$/), AND(Integer, 100..999))\n")
294
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
295
+ JSON({"val": 99}) === expected
296
+ end
297
+ end
298
+ it "[!scx22] `AND()` can contain `OR()`." do
299
+ expected = {"val": AND(OR(String, Integer), OR(/^\d{3}$/, 100..999))}
300
+ result = JSON({"val": "123"}) === expected
301
+ assert_eq result, true
302
+ result = JSON({"val": 123}) === expected
303
+ assert_eq result, true
304
+ #
305
+ errmsg = ("$<JSON>[\"val\"]: $<expected> === $<actual> : failed.\n"\
306
+ " $<actual>: \"1\"\n"\
307
+ " $<expected>: AND(OR(/^\\d{3}$/, 100..999))\n")
308
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
309
+ JSON({"val": "1"}) === expected
310
+ end
311
+ errmsg = ("$<JSON>[\"val\"]: $<expected> === $<actual> : failed.\n"\
312
+ " $<actual>: 0\n"\
313
+ " $<expected>: AND(OR(/^\\d{3}$/, 100..999))\n")
314
+ assert_exc(Oktest::FAIL_EXCEPTION, errmsg) do
315
+ JSON({"val": 0}) === expected
316
+ end
317
+ end
318
+ it "[!uc4ag] key '*' matches to any key name." do
319
+ actual = {"name": "Alice", "age": 20}
320
+ result = JSON(actual) === {"name": String, "*": Integer}
321
+ assert_eq result, true
322
+ result = JSON(actual) === {"name": String, "*": ANY()}
323
+ assert_eq result, true
324
+ end
325
+ end
326
+
327
+ describe '#_compare?()' do
328
+ it "[!nkvqo] returns true when nothing raised." do
329
+ result = JSON(nil).instance_eval { _compare?([], "abc", /^\w+$/) }
330
+ assert_eq result, true
331
+ end
332
+ it "[!57m2j] returns false when assertion error raised." do
333
+ result = JSON(nil).instance_eval { _compare?([], "abc", /^\d+$/) }
334
+ assert_eq result, false
335
+ end
336
+ end
337
+
338
+ end
339
+
340
+
341
+ class OR_TC < TC
342
+
343
+ describe '#inspect()' do
344
+ it "[!2mu33] returns 'OR(...)' string." do
345
+ o = Oktest::JsonMatcher::OR.new('A', 'B', 'C')
346
+ assert_eq o.inspect(), 'OR("A", "B", "C")'
347
+ end
348
+ end
349
+
350
+ end
351
+
352
+
353
+ class AND_TC < TC
354
+
355
+ describe '#inspect()' do
356
+ it "[!w43ag] returns 'AND(...)' string." do
357
+ o = Oktest::JsonMatcher::AND.new('A', 'B', 'C')
358
+ assert_eq o.inspect(), 'AND("A", "B", "C")'
359
+ end
360
+ end
361
+
362
+ end
363
+
364
+
365
+ class Enum_TC < TC
366
+
367
+ describe '#inspect()' do
368
+ it "[!fam11] returns 'Enum(...)' string." do
369
+ o = Oktest::JsonMatcher::Enum.new(['A', 'B', 'C'])
370
+ assert_eq o.inspect(), 'Enum("A", "B", "C")'
371
+ end
372
+ end
373
+
374
+ end
375
+
376
+
377
+ class Length_TC < TC
378
+
379
+ describe '#===' do
380
+ it "[!03ozi] compares length of actual value with expected value." do
381
+ o1 = Oktest::JsonMatcher::Length.new(3)
382
+ assert_eq (o1 === "abc"), true
383
+ assert_eq (o1 === "abcd"), false
384
+ assert_eq (o1 === [1,2,3]), true
385
+ assert_eq (o1 === [1, 2]), false
386
+ o2 = Oktest::JsonMatcher::Length.new(1..3)
387
+ assert_eq (o2 === "a"), true
388
+ assert_eq (o2 === "abc"), true
389
+ assert_eq (o2 === ""), false
390
+ assert_eq (o2 === "abcd"), false
391
+ end
392
+ end
393
+
394
+ describe '#inspect()' do
395
+ it "[!nwv3e] returns 'Length(n)' string." do
396
+ o = Oktest::JsonMatcher::Length.new(1..3)
397
+ assert_eq o.inspect, "Length(1..3)"
398
+ end
399
+ end
400
+
401
+ end
402
+
403
+
404
+ class Any_TC < TC
405
+
406
+ describe '#===' do
407
+ it "[!mzion] returns true in any case." do
408
+ o = Oktest::JsonMatcher::Any.new()
409
+ assert_eq (o === nil) , true
410
+ assert_eq (o === true) , true
411
+ assert_eq (o === false), true
412
+ assert_eq (o === 123) , true
413
+ assert_eq (o === "abc"), true
414
+ end
415
+ end
416
+
417
+ describe '#inspect()' do
418
+ it "[!6f0yv] returns 'Any()' string." do
419
+ o = Oktest::JsonMatcher::Any.new()
420
+ assert_eq o.inspect, "Any()"
421
+ end
422
+ end
423
+
424
+ end