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