contracts 0.7 → 0.8
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/Gemfile +1 -0
- data/Gemfile.lock +16 -1
- data/README.md +12 -4
- data/TUTORIAL.md +67 -18
- data/benchmarks/bench.rb +20 -20
- data/benchmarks/invariants.rb +28 -18
- data/benchmarks/io.rb +62 -0
- data/benchmarks/wrap_test.rb +11 -13
- data/contracts.gemspec +1 -1
- data/lib/contracts.rb +167 -109
- data/lib/contracts/builtin_contracts.rb +132 -84
- data/lib/contracts/decorators.rb +41 -53
- data/lib/contracts/eigenclass.rb +3 -7
- data/lib/contracts/errors.rb +1 -1
- data/lib/contracts/formatters.rb +134 -0
- data/lib/contracts/invariants.rb +7 -8
- data/lib/contracts/method_reference.rb +33 -9
- data/lib/contracts/support.rb +9 -3
- data/lib/contracts/testable.rb +6 -6
- data/lib/contracts/version.rb +1 -1
- data/script/rubocop.rb +5 -0
- data/spec/builtin_contracts_spec.rb +57 -9
- data/spec/contracts_spec.rb +182 -53
- data/spec/fixtures/fixtures.rb +130 -9
- data/spec/invariants_spec.rb +0 -2
- data/spec/module_spec.rb +2 -2
- data/spec/ruby_version_specific/contracts_spec_1.9.rb +18 -0
- data/spec/ruby_version_specific/contracts_spec_2.0.rb +22 -0
- data/spec/ruby_version_specific/contracts_spec_2.1.rb +55 -0
- data/spec/spec_helper.rb +9 -2
- data/spec/support.rb +4 -0
- data/spec/support_spec.rb +21 -0
- metadata +11 -3
- data/lib/contracts/core_ext.rb +0 -15
data/lib/contracts/testable.rb
CHANGED
@@ -7,11 +7,11 @@ module Contracts
|
|
7
7
|
#
|
8
8
|
# [[1, 3], [1, 4], [2, 3], [2, 4]]
|
9
9
|
def self.product(arrays)
|
10
|
-
arrays.inject
|
10
|
+
arrays.inject do |acc, x|
|
11
11
|
acc.product(x)
|
12
|
-
|
12
|
+
end.flatten(arrays.size - 2)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# Given a contract, tells if you it's testable
|
16
16
|
def self.testable?(contract)
|
17
17
|
if contract.respond_to?(:testable?)
|
@@ -30,10 +30,10 @@ module Contracts
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
# TODO Should work on whatever class it was invoked on, no?
|
33
|
+
# TODO: Should work on whatever class it was invoked on, no?
|
34
34
|
def self.check_all
|
35
35
|
o = Object.new
|
36
|
-
Object.decorated_methods.each do |name,
|
36
|
+
Object.decorated_methods.each do |name, _contracts|
|
37
37
|
check(o.method(name))
|
38
38
|
end
|
39
39
|
end
|
@@ -64,6 +64,6 @@ module Contracts
|
|
64
64
|
end
|
65
65
|
puts "#{test_data.size} tests run."
|
66
66
|
end
|
67
|
-
end
|
67
|
+
end
|
68
68
|
end
|
69
69
|
end
|
data/lib/contracts/version.rb
CHANGED
data/script/rubocop.rb
ADDED
@@ -22,6 +22,10 @@ RSpec.describe "Contracts:" do
|
|
22
22
|
expect { @o.pos_test(1) }.to_not raise_error
|
23
23
|
end
|
24
24
|
|
25
|
+
it "should fail for 0" do
|
26
|
+
expect { @o.pos_test(0) }.to raise_error(ContractError)
|
27
|
+
end
|
28
|
+
|
25
29
|
it "should fail for negative numbers" do
|
26
30
|
expect { @o.pos_test(-1) }.to raise_error(ContractError)
|
27
31
|
end
|
@@ -32,11 +36,33 @@ RSpec.describe "Contracts:" do
|
|
32
36
|
expect { @o.neg_test(-1) }.to_not raise_error
|
33
37
|
end
|
34
38
|
|
39
|
+
it "should fail for 0" do
|
40
|
+
expect { @o.neg_test(0) }.to raise_error(ContractError)
|
41
|
+
end
|
42
|
+
|
35
43
|
it "should fail for positive numbers" do
|
36
44
|
expect { @o.neg_test(1) }.to raise_error(ContractError)
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
48
|
+
describe "Nat:" do
|
49
|
+
it "should pass for 0" do
|
50
|
+
expect { @o.nat_test(0) }.to_not raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should pass for positive whole numbers" do
|
54
|
+
expect { @o.nat_test(1) }.to_not raise_error
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should fail for positive non-whole numbers" do
|
58
|
+
expect { @o.nat_test(1.5) }.to raise_error(ContractError)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should fail for negative numbers" do
|
62
|
+
expect { @o.nat_test(-1) }.to raise_error(ContractError)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
40
66
|
describe "Any:" do
|
41
67
|
it "should pass for numbers" do
|
42
68
|
expect { @o.show(1) }.to_not raise_error
|
@@ -143,6 +169,28 @@ RSpec.describe "Contracts:" do
|
|
143
169
|
end
|
144
170
|
end
|
145
171
|
|
172
|
+
describe "Eq:" do
|
173
|
+
it "should pass for a class" do
|
174
|
+
expect { @o.eq_class_test(Foo) }
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should pass for a module" do
|
178
|
+
expect { @o.eq_module_test(Bar) }
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should pass for other values" do
|
182
|
+
expect { @o.eq_value_test(Baz) }
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should fail when not equal" do
|
186
|
+
expect { @o.eq_class_test(Bar) }.to raise_error(ContractError)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should fail when given instance of class" do
|
190
|
+
expect { @o.eq_class_test(Foo.new) }.to raise_error(ContractError)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
146
194
|
describe "Not:" do
|
147
195
|
it "should pass for an argument that isn't nil" do
|
148
196
|
expect { @o.not_nil(1) }.to_not raise_error
|
@@ -192,22 +240,22 @@ RSpec.describe "Contracts:" do
|
|
192
240
|
end
|
193
241
|
end
|
194
242
|
|
195
|
-
describe
|
196
|
-
context
|
243
|
+
describe "HashOf:" do
|
244
|
+
context "given a fulfilled contract" do
|
197
245
|
it { expect(@o.gives_max_value(:panda => 1, :bamboo => 2)).to eq(2) }
|
198
246
|
end
|
199
247
|
|
200
|
-
context
|
201
|
-
it { expect { @o.gives_max_value(:panda =>
|
248
|
+
context "given an unfulfilled contract" do
|
249
|
+
it { expect { @o.gives_max_value(:panda => "1", :bamboo => "2") }.to raise_error(ContractError) }
|
202
250
|
end
|
203
251
|
|
204
|
-
describe
|
205
|
-
context
|
206
|
-
it { expect(Contracts::HashOf[Symbol, String].to_s).to eq(
|
252
|
+
describe "#to_s" do
|
253
|
+
context "given Symbol => String" do
|
254
|
+
it { expect(Contracts::HashOf[Symbol, String].to_s).to eq("Hash<Symbol, String>") }
|
207
255
|
end
|
208
256
|
|
209
|
-
context
|
210
|
-
it { expect(Contracts::HashOf[String, Contracts::Num].to_s).to eq(
|
257
|
+
context "given String => Num" do
|
258
|
+
it { expect(Contracts::HashOf[String, Contracts::Num].to_s).to eq("Hash<String, Contracts::Num>") }
|
211
259
|
end
|
212
260
|
end
|
213
261
|
end
|
data/spec/contracts_spec.rb
CHANGED
@@ -5,9 +5,9 @@ RSpec.describe "Contracts:" do
|
|
5
5
|
|
6
6
|
describe "basic" do
|
7
7
|
it "should fail for insufficient arguments" do
|
8
|
-
expect
|
8
|
+
expect do
|
9
9
|
@o.hello
|
10
|
-
|
10
|
+
end.to raise_error
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should fail for insufficient contracts" do
|
@@ -23,8 +23,8 @@ RSpec.describe "Contracts:" do
|
|
23
23
|
|
24
24
|
it "should work as expected when there is no contract violation" do
|
25
25
|
expect(
|
26
|
-
subject.process_request(PatternMatchingExample::Success
|
27
|
-
).to eq(PatternMatchingExample::Success
|
26
|
+
subject.process_request(PatternMatchingExample::Success.new(string_with_hello))
|
27
|
+
).to eq(PatternMatchingExample::Success.new(expected_decorated_string))
|
28
28
|
|
29
29
|
expect(
|
30
30
|
subject.process_request(PatternMatchingExample::Failure.new)
|
@@ -33,28 +33,38 @@ RSpec.describe "Contracts:" do
|
|
33
33
|
|
34
34
|
it "should not fall through to next pattern when there is a deep contract violation" do
|
35
35
|
expect(PatternMatchingExample::Failure).not_to receive(:is_a?)
|
36
|
-
expect
|
37
|
-
subject.process_request(PatternMatchingExample::Success
|
38
|
-
|
36
|
+
expect do
|
37
|
+
subject.process_request(PatternMatchingExample::Success.new(string_without_hello))
|
38
|
+
end.to raise_error(ContractError)
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should fail when the pattern-matched method's contract fails" do
|
42
|
-
expect
|
42
|
+
expect do
|
43
43
|
subject.process_request("bad input")
|
44
|
-
|
44
|
+
end.to raise_error(ContractError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should work for differing arities" do
|
48
|
+
expect(
|
49
|
+
subject.do_stuff(1, "abc", 2)
|
50
|
+
).to eq("bar")
|
51
|
+
|
52
|
+
expect(
|
53
|
+
subject.do_stuff(3, "def")
|
54
|
+
).to eq("foo")
|
45
55
|
end
|
46
56
|
|
47
57
|
context "when failure_callback was overriden" do
|
48
58
|
before do
|
49
59
|
::Contract.override_failure_callback do |_data|
|
50
|
-
|
60
|
+
fail "contract violation"
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
54
64
|
it "calls a method when first pattern matches" do
|
55
65
|
expect(
|
56
|
-
subject.process_request(PatternMatchingExample::Success
|
57
|
-
).to eq(PatternMatchingExample::Success
|
66
|
+
subject.process_request(PatternMatchingExample::Success.new(string_with_hello))
|
67
|
+
).to eq(PatternMatchingExample::Success.new(expected_decorated_string))
|
58
68
|
end
|
59
69
|
|
60
70
|
it "falls through to 2nd pattern when first pattern does not match" do
|
@@ -64,9 +74,9 @@ RSpec.describe "Contracts:" do
|
|
64
74
|
end
|
65
75
|
|
66
76
|
it "uses overriden failure_callback when pattern matching fails" do
|
67
|
-
expect
|
77
|
+
expect do
|
68
78
|
subject.process_request("hello")
|
69
|
-
|
79
|
+
end.to raise_error(RuntimeError, /contract violation/)
|
70
80
|
end
|
71
81
|
end
|
72
82
|
end
|
@@ -77,13 +87,13 @@ RSpec.describe "Contracts:" do
|
|
77
87
|
end
|
78
88
|
|
79
89
|
it "should fail with proper error when there is contract violation" do
|
80
|
-
expect
|
90
|
+
expect do
|
81
91
|
SingletonClassExample.hoge(3)
|
82
|
-
|
92
|
+
end.to raise_error(ContractError, /Expected: String/)
|
83
93
|
end
|
84
94
|
|
85
95
|
context "when owner class does not include Contracts" do
|
86
|
-
let(:error)
|
96
|
+
let(:error) do
|
87
97
|
# NOTE Unable to support this user-friendly error for ruby
|
88
98
|
# 1.8.7 and jruby 1.8, 1.9 it has much less support for
|
89
99
|
# singleton inheritance hierarchy
|
@@ -92,10 +102,10 @@ RSpec.describe "Contracts:" do
|
|
92
102
|
else
|
93
103
|
[NoMethodError, /undefined method `Contract'/]
|
94
104
|
end
|
95
|
-
|
105
|
+
end
|
96
106
|
|
97
107
|
it "fails with descriptive error" do
|
98
|
-
expect
|
108
|
+
expect do
|
99
109
|
Class.new(GenericExample) do
|
100
110
|
class << self
|
101
111
|
Contract String => String
|
@@ -104,15 +114,15 @@ RSpec.describe "Contracts:" do
|
|
104
114
|
end
|
105
115
|
end
|
106
116
|
end
|
107
|
-
|
117
|
+
end.to raise_error(*error)
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
111
121
|
describe "builtin contracts usage" do
|
112
122
|
it "allows to use builtin contracts without namespacing and redundant Contracts inclusion" do
|
113
|
-
expect
|
123
|
+
expect do
|
114
124
|
SingletonClassExample.add("55", 5.6)
|
115
|
-
|
125
|
+
end.to raise_error(ContractError, /Expected: Num/)
|
116
126
|
end
|
117
127
|
end
|
118
128
|
end
|
@@ -236,20 +246,20 @@ RSpec.describe "Contracts:" do
|
|
236
246
|
it "should allow two classes to have the same method with different contracts" do
|
237
247
|
a = A.new
|
238
248
|
b = B.new
|
239
|
-
expect
|
249
|
+
expect do
|
240
250
|
a.triple(5)
|
241
251
|
b.triple("a string")
|
242
|
-
|
252
|
+
end.to_not raise_error
|
243
253
|
end
|
244
254
|
end
|
245
255
|
|
246
256
|
describe "instance and class methods" do
|
247
257
|
it "should allow a class to have an instance method and a class method with the same name" do
|
248
258
|
a = A.new
|
249
|
-
expect
|
259
|
+
expect do
|
250
260
|
a.instance_and_class_method(5)
|
251
261
|
A.instance_and_class_method("a string")
|
252
|
-
|
262
|
+
end.to_not raise_error
|
253
263
|
end
|
254
264
|
end
|
255
265
|
|
@@ -313,77 +323,103 @@ RSpec.describe "Contracts:" do
|
|
313
323
|
|
314
324
|
describe "Hashes" do
|
315
325
|
it "should pass for exact correct input" do
|
316
|
-
expect { @o.person(
|
326
|
+
expect { @o.person(:name => "calvin", :age => 10) }.to_not raise_error
|
317
327
|
end
|
318
328
|
|
319
329
|
it "should pass even if some keys don't have contracts" do
|
320
|
-
expect { @o.person(
|
330
|
+
expect { @o.person(:name => "calvin", :age => 10, :foo => "bar") }.to_not raise_error
|
321
331
|
end
|
322
332
|
|
323
333
|
it "should fail if a key with a contract on it isn't provided" do
|
324
|
-
expect { @o.person(
|
334
|
+
expect { @o.person(:name => "calvin") }.to raise_error(ContractError)
|
325
335
|
end
|
326
336
|
|
327
337
|
it "should fail for incorrect input" do
|
328
|
-
expect { @o.person(
|
338
|
+
expect { @o.person(:name => 50, :age => 10) }.to raise_error(ContractError)
|
329
339
|
end
|
330
340
|
end
|
331
341
|
|
332
342
|
describe "blocks" do
|
333
343
|
it "should pass for correct input" do
|
334
|
-
expect
|
335
|
-
|
336
|
-
|
344
|
+
expect do
|
345
|
+
@o.do_call do
|
346
|
+
2 + 2
|
347
|
+
end
|
348
|
+
end.to_not raise_error
|
337
349
|
end
|
338
350
|
|
339
351
|
it "should fail for incorrect input" do
|
340
|
-
expect
|
352
|
+
expect do
|
353
|
+
@o.do_call(nil)
|
354
|
+
end.to raise_error(ContractError)
|
341
355
|
end
|
342
356
|
|
343
357
|
it "should handle properly lack of block when there are other arguments" do
|
344
|
-
expect
|
358
|
+
expect do
|
359
|
+
@o.double_with_proc(4)
|
360
|
+
end.to raise_error(ContractError, /Actual: nil/)
|
345
361
|
end
|
346
362
|
end
|
347
363
|
|
348
364
|
describe "varargs" do
|
349
365
|
it "should pass for correct input" do
|
350
|
-
expect
|
366
|
+
expect do
|
367
|
+
@o.sum(1, 2, 3)
|
368
|
+
end.to_not raise_error
|
351
369
|
end
|
352
370
|
|
353
371
|
it "should fail for incorrect input" do
|
354
|
-
expect
|
372
|
+
expect do
|
373
|
+
@o.sum(1, 2, "bad")
|
374
|
+
end.to raise_error(ContractError)
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should work with arg before splat" do
|
378
|
+
expect do
|
379
|
+
@o.arg_then_splat(3, "hello", "world")
|
380
|
+
end.to_not raise_error
|
355
381
|
end
|
356
382
|
end
|
357
383
|
|
358
384
|
describe "varargs with block" do
|
359
385
|
it "should pass for correct input" do
|
360
|
-
expect
|
361
|
-
|
386
|
+
expect do
|
387
|
+
@o.with_partial_sums(1, 2, 3) do |partial_sum|
|
388
|
+
2 * partial_sum + 1
|
389
|
+
end
|
390
|
+
end.not_to raise_error
|
391
|
+
expect do
|
392
|
+
@o.with_partial_sums_contracted(1, 2, 3) do |partial_sum|
|
393
|
+
2 * partial_sum + 1
|
394
|
+
end
|
395
|
+
end.not_to raise_error
|
362
396
|
end
|
363
397
|
|
364
398
|
it "should fail for incorrect input" do
|
365
|
-
expect
|
366
|
-
@o.with_partial_sums(1, 2, "bad")
|
367
|
-
|
399
|
+
expect do
|
400
|
+
@o.with_partial_sums(1, 2, "bad") do |partial_sum|
|
401
|
+
2 * partial_sum + 1
|
402
|
+
end
|
403
|
+
end.to raise_error(ContractError, /Actual: "bad"/)
|
368
404
|
|
369
|
-
expect
|
405
|
+
expect do
|
370
406
|
@o.with_partial_sums(1, 2, 3)
|
371
|
-
|
407
|
+
end.to raise_error(ContractError, /Actual: nil/)
|
372
408
|
|
373
|
-
expect
|
409
|
+
expect do
|
374
410
|
@o.with_partial_sums(1, 2, 3, lambda { |x| x })
|
375
|
-
|
411
|
+
end.to raise_error(ContractError, /Actual: nil/)
|
376
412
|
end
|
377
413
|
|
378
414
|
context "when block has Func contract" do
|
379
415
|
it "should fail for incorrect input" do
|
380
|
-
expect
|
416
|
+
expect do
|
381
417
|
@o.with_partial_sums_contracted(1, 2, "bad") { |partial_sum| 2 * partial_sum + 1 }
|
382
|
-
|
418
|
+
end.to raise_error(ContractError, /Actual: "bad"/)
|
383
419
|
|
384
|
-
expect
|
420
|
+
expect do
|
385
421
|
@o.with_partial_sums_contracted(1, 2, 3)
|
386
|
-
|
422
|
+
end.to raise_error(ContractError, /Actual: nil/)
|
387
423
|
end
|
388
424
|
end
|
389
425
|
end
|
@@ -393,8 +429,20 @@ RSpec.describe "Contracts:" do
|
|
393
429
|
expect { @o.map([1, 2, 3], lambda { |x| x + 1 }) }.to_not raise_error
|
394
430
|
end
|
395
431
|
|
432
|
+
it "should pass for a function that passes the contract as in tutorial" do
|
433
|
+
expect { @o.tutorial_map([1, 2, 3], lambda { |x| x + 1 }) }.to_not raise_error
|
434
|
+
end
|
435
|
+
|
396
436
|
it "should fail for a function that doesn't pass the contract" do
|
397
|
-
expect { @o.map([1, 2, 3], lambda { |
|
437
|
+
expect { @o.map([1, 2, 3], lambda { |_| "bad return value" }) }.to raise_error(ContractError)
|
438
|
+
end
|
439
|
+
|
440
|
+
it "should pass for a function that passes the contract with weak other args" do
|
441
|
+
expect { @o.map_plain(["hello", "joe"], lambda { |x| x.size }) }.to_not raise_error
|
442
|
+
end
|
443
|
+
|
444
|
+
it "should fail for a function that doesn't pass the contract with weak other args" do
|
445
|
+
expect { @o.map_plain(["hello", "joe"], lambda { |_| nil }) }.to raise_error(ContractError)
|
398
446
|
end
|
399
447
|
end
|
400
448
|
|
@@ -443,6 +491,77 @@ RSpec.describe "Contracts:" do
|
|
443
491
|
end
|
444
492
|
end
|
445
493
|
|
494
|
+
describe "Contracts to_s formatting in expected" do
|
495
|
+
def not_s(match)
|
496
|
+
Regexp.new "[^\"\']#{match}[^\"\']"
|
497
|
+
end
|
498
|
+
|
499
|
+
def delim(match)
|
500
|
+
"(#{match})"
|
501
|
+
end
|
502
|
+
|
503
|
+
it "should not stringify native types" do
|
504
|
+
expect do
|
505
|
+
@o.constanty("bad", nil)
|
506
|
+
end.to raise_error(ContractError, not_s(123))
|
507
|
+
|
508
|
+
expect do
|
509
|
+
@o.constanty(123, "bad")
|
510
|
+
end.to raise_error(ContractError, not_s(nil))
|
511
|
+
end
|
512
|
+
|
513
|
+
it "should contain to_s representation within a Hash contract" do
|
514
|
+
expect do
|
515
|
+
@o.hash_complex_contracts(:rigged => "bad")
|
516
|
+
end.to raise_error(ContractError, not_s(delim "TrueClass or FalseClass"))
|
517
|
+
end
|
518
|
+
|
519
|
+
it "should contain to_s representation within a nested Hash contract" do
|
520
|
+
expect do
|
521
|
+
@o.nested_hash_complex_contracts(:rigged => true,
|
522
|
+
:contents => {
|
523
|
+
:kind => 0,
|
524
|
+
:total => 42 })
|
525
|
+
end.to raise_error(ContractError, not_s(delim "String or Symbol"))
|
526
|
+
end
|
527
|
+
|
528
|
+
it "should contain to_s representation within an Array contract" do
|
529
|
+
expect do
|
530
|
+
@o.array_complex_contracts(["bad"])
|
531
|
+
end.to raise_error(ContractError, not_s(delim "TrueClass or FalseClass"))
|
532
|
+
end
|
533
|
+
|
534
|
+
it "should contain to_s representation within a nested Array contract" do
|
535
|
+
expect do
|
536
|
+
@o.nested_array_complex_contracts([true, [0]])
|
537
|
+
end.to raise_error(ContractError, not_s(delim "String or Symbol"))
|
538
|
+
end
|
539
|
+
|
540
|
+
it "should not contain Contracts:: module prefix" do
|
541
|
+
expect do
|
542
|
+
@o.double("bad")
|
543
|
+
end.to raise_error(ContractError, /Expected: Num/)
|
544
|
+
end
|
545
|
+
|
546
|
+
it "should still show nils, not just blank space" do
|
547
|
+
expect do
|
548
|
+
@o.no_args("bad")
|
549
|
+
end.to raise_error(ContractError, /Expected: nil/)
|
550
|
+
end
|
551
|
+
|
552
|
+
it 'should show empty quotes as ""' do
|
553
|
+
expect do
|
554
|
+
@o.no_args("")
|
555
|
+
end.to raise_error(ContractError, /Actual: ""/)
|
556
|
+
end
|
557
|
+
|
558
|
+
it "should not use custom to_s if empty string" do
|
559
|
+
expect do
|
560
|
+
@o.using_empty_contract("bad")
|
561
|
+
end.to raise_error(ContractError, /Expected: EmptyCont/)
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
446
565
|
describe "functype" do
|
447
566
|
it "should correctly print out a instance method's type" do
|
448
567
|
expect(@o.functype(:double)).not_to eq("")
|
@@ -455,11 +574,21 @@ RSpec.describe "Contracts:" do
|
|
455
574
|
|
456
575
|
describe "private methods" do
|
457
576
|
it "should raise an error if you try to access a private method" do
|
458
|
-
expect { @o.a_private_method }.to raise_error
|
577
|
+
expect { @o.a_private_method }.to raise_error(NoMethodError, /private/)
|
459
578
|
end
|
460
579
|
|
461
580
|
it "should raise an error if you try to access a private method" do
|
462
|
-
expect { @o.a_really_private_method }.to raise_error
|
581
|
+
expect { @o.a_really_private_method }.to raise_error(NoMethodError, /private/)
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
describe "protected methods" do
|
586
|
+
it "should raise an error if you try to access a protected method" do
|
587
|
+
expect { @o.a_protected_method }.to raise_error(NoMethodError, /protected/)
|
588
|
+
end
|
589
|
+
|
590
|
+
it "should raise an error if you try to access a protected method" do
|
591
|
+
expect { @o.a_really_protected_method }.to raise_error(NoMethodError, /protected/)
|
463
592
|
end
|
464
593
|
end
|
465
594
|
|