diff --git a/spec/builtin_contracts_spec.rb b/spec/builtin_contracts_spec.rb index c3580cd..be718ad 100644 --- a/spec/builtin_contracts_spec.rb +++ b/spec/builtin_contracts_spec.rb @@ -3,296 +3,304 @@ @o = GenericExample.new end + def fails(&some) + expect { some.call }.to raise_error(ContractError) + end + + def passes(&some) + expect { some.call }.to_not raise_error + end + describe "DescendantOf:" do it "should pass for Array" do - expect { @o.enumerable_descendant_test(Array) }.to_not raise_error + passes { @o.enumerable_descendant_test(Array) } end it "should pass for a hash" do - expect { @o.enumerable_descendant_test(Hash) }.to_not raise_error + passes { @o.enumerable_descendant_test(Hash) } end it "should fail for a number class" do - expect { @o.enumerable_descendant_test(Integer) }.to raise_error(ContractError) + fails { @o.enumerable_descendant_test(Integer) } end it "should fail for a non-class" do - expect { @o.enumerable_descendant_test(1) }.to raise_error(ContractError) + fails { @o.enumerable_descendant_test(1) } end end describe "Num:" do it "should pass for Fixnums" do - expect { @o.double(2) }.to_not raise_error + passes { @o.double(2) } end it "should pass for Floats" do - expect { @o.double(2.2) }.to_not raise_error + passes { @o.double(2.2) } end it "should fail for nil and other data types" do - expect { @o.double(nil) }.to raise_error(ContractError) - expect { @o.double(:x) }.to raise_error(ContractError) - expect { @o.double("x") }.to raise_error(ContractError) - expect { @o.double(/x/) }.to raise_error(ContractError) + fails { @o.double(nil) } + fails { @o.double(:x) } + fails { @o.double("x") } + fails { @o.double(/x/) } end end describe "Pos:" do it "should pass for positive numbers" do - expect { @o.pos_test(1) }.to_not raise_error - expect { @o.pos_test(1.6) }.to_not raise_error + passes { @o.pos_test(1) } + passes { @o.pos_test(1.6) } end it "should fail for 0" do - expect { @o.pos_test(0) }.to raise_error(ContractError) + fails { @o.pos_test(0) } end it "should fail for negative numbers" do - expect { @o.pos_test(-1) }.to raise_error(ContractError) - expect { @o.pos_test(-1.6) }.to raise_error(ContractError) + fails { @o.pos_test(-1) } + fails { @o.pos_test(-1.6) } end it "should fail for nil and other data types" do - expect { @o.pos_test(nil) }.to raise_error(ContractError) - expect { @o.pos_test(:x) }.to raise_error(ContractError) - expect { @o.pos_test("x") }.to raise_error(ContractError) - expect { @o.pos_test(/x/) }.to raise_error(ContractError) + fails { @o.pos_test(nil) } + fails { @o.pos_test(:x) } + fails { @o.pos_test("x") } + fails { @o.pos_test(/x/) } end end describe "Neg:" do it "should pass for negative numbers" do - expect { @o.neg_test(-1) }.to_not raise_error - expect { @o.neg_test(-1.6) }.to_not raise_error + passes { @o.neg_test(-1) } + passes { @o.neg_test(-1.6) } end it "should fail for 0" do - expect { @o.neg_test(0) }.to raise_error(ContractError) + fails { @o.neg_test(0) } end it "should fail for positive numbers" do - expect { @o.neg_test(1) }.to raise_error(ContractError) - expect { @o.neg_test(1.6) }.to raise_error(ContractError) + fails { @o.neg_test(1) } + fails { @o.neg_test(1.6) } end it "should fail for nil and other data types" do - expect { @o.neg_test(nil) }.to raise_error(ContractError) - expect { @o.neg_test(:x) }.to raise_error(ContractError) - expect { @o.neg_test("x") }.to raise_error(ContractError) - expect { @o.neg_test(/x/) }.to raise_error(ContractError) + fails { @o.neg_test(nil) } + fails { @o.neg_test(:x) } + fails { @o.neg_test("x") } + fails { @o.neg_test(/x/) } end end describe "Nat:" do it "should pass for 0" do - expect { @o.nat_test(0) }.to_not raise_error + passes { @o.nat_test(0) } end it "should pass for positive whole numbers" do - expect { @o.nat_test(1) }.to_not raise_error + passes { @o.nat_test(1) } end it "should fail for positive non-whole numbers" do - expect { @o.nat_test(1.5) }.to raise_error(ContractError) + fails { @o.nat_test(1.5) } end it "should fail for negative numbers" do - expect { @o.nat_test(-1) }.to raise_error(ContractError) - expect { @o.nat_test(-1.6) }.to raise_error(ContractError) + fails { @o.nat_test(-1) } + fails { @o.nat_test(-1.6) } end it "should fail for nil and other data types" do - expect { @o.nat_test(nil) }.to raise_error(ContractError) - expect { @o.nat_test(:x) }.to raise_error(ContractError) - expect { @o.nat_test("x") }.to raise_error(ContractError) - expect { @o.nat_test(/x/) }.to raise_error(ContractError) + fails { @o.nat_test(nil) } + fails { @o.nat_test(:x) } + fails { @o.nat_test("x") } + fails { @o.nat_test(/x/) } end end describe "Any:" do it "should pass for numbers" do - expect { @o.show(1) }.to_not raise_error + passes { @o.show(1) } end it "should pass for strings" do - expect { @o.show("bad") }.to_not raise_error + passes { @o.show("bad") } end it "should pass for procs" do - expect { @o.show(lambda {}) }.to_not raise_error + passes { @o.show(lambda {}) } end it "should pass for nil" do - expect { @o.show(nil) }.to_not raise_error + passes { @o.show(nil) } end end describe "None:" do it "should fail for numbers" do - expect { @o.fail_all(1) }.to raise_error(ContractError) + fails { @o.fail_all(1) } end it "should fail for strings" do - expect { @o.fail_all("bad") }.to raise_error(ContractError) + fails { @o.fail_all("bad") } end it "should fail for procs" do - expect { @o.fail_all(lambda {}) }.to raise_error(ContractError) + fails { @o.fail_all(lambda {}) } end it "should fail for nil" do - expect { @o.fail_all(nil) }.to raise_error(ContractError) + fails { @o.fail_all(nil) } end end describe "Or:" do it "should pass for nums" do - expect { @o.num_or_string(1) }.to_not raise_error + passes { @o.num_or_string(1) } end it "should pass for strings" do - expect { @o.num_or_string("bad") }.to_not raise_error + passes { @o.num_or_string("bad") } end it "should fail for nil" do - expect { @o.num_or_string(nil) }.to raise_error(ContractError) + fails { @o.num_or_string(nil) } end end describe "Xor:" do it "should pass for an object with a method :good" do - expect { @o.xor_test(A.new) }.to_not raise_error + passes { @o.xor_test(A.new) } end it "should pass for an object with a method :bad" do - expect { @o.xor_test(B.new) }.to_not raise_error + passes { @o.xor_test(B.new) } end it "should fail for an object with neither method" do - expect { @o.xor_test(1) }.to raise_error(ContractError) + fails { @o.xor_test(1) } end it "should fail for an object with both methods :good and :bad" do - expect { @o.xor_test(F.new) }.to raise_error(ContractError) + fails { @o.xor_test(F.new) } end end describe "And:" do it "should pass for an object of class A that has a method :good" do - expect { @o.and_test(A.new) }.to_not raise_error + passes { @o.and_test(A.new) } end it "should fail for an object that has a method :good but isn't of class A" do - expect { @o.and_test(F.new) }.to raise_error(ContractError) + fails { @o.and_test(F.new) } end end describe "Enum:" do it "should pass for an object that is included" do - expect { @o.enum_test(:a) }.to_not raise_error + passes { @o.enum_test(:a) } end it "should fail for an object that is not included" do - expect { @o.enum_test(:z) }.to raise_error(ContractError) + fails { @o.enum_test(:z) } end end describe "RespondTo:" do it "should pass for an object that responds to :good" do - expect { @o.responds_test(A.new) }.to_not raise_error + passes { @o.responds_test(A.new) } end it "should fail for an object that doesn't respond to :good" do - expect { @o.responds_test(B.new) }.to raise_error(ContractError) + fails { @o.responds_test(B.new) } end end describe "Send:" do it "should pass for an object that returns true for method :good" do - expect { @o.send_test(A.new) }.to_not raise_error + passes { @o.send_test(A.new) } end it "should fail for an object that returns false for method :good" do - expect { @o.send_test(F.new) }.to raise_error(ContractError) + fails { @o.send_test(F.new) } end end describe "Exactly:" do it "should pass for an object that is exactly a Parent" do - expect { @o.exactly_test(Parent.new) }.to_not raise_error + passes { @o.exactly_test(Parent.new) } end it "should fail for an object that inherits from Parent" do - expect { @o.exactly_test(Child.new) }.to raise_error(ContractError) + fails { @o.exactly_test(Child.new) } end it "should fail for an object that is not related to Parent at all" do - expect { @o.exactly_test(A.new) }.to raise_error(ContractError) + fails { @o.exactly_test(A.new) } end end describe "Eq:" do it "should pass for a class" do - expect { @o.eq_class_test(Foo) } + passes { @o.eq_class_test(Foo) } end it "should pass for a module" do - expect { @o.eq_module_test(Bar) } + passes { @o.eq_module_test(Bar) } end it "should pass for other values" do - expect { @o.eq_value_test(Baz) } + passes { @o.eq_value_test(Baz) } end it "should fail when not equal" do - expect { @o.eq_class_test(Bar) }.to raise_error(ContractError) + fails { @o.eq_class_test(Bar) } end it "should fail when given instance of class" do - expect { @o.eq_class_test(Foo.new) }.to raise_error(ContractError) + fails { @o.eq_class_test(Foo.new) } end end describe "Not:" do it "should pass for an argument that isn't nil" do - expect { @o.not_nil(1) }.to_not raise_error + passes { @o.not_nil(1) } end it "should fail for nil" do - expect { @o.not_nil(nil) }.to raise_error(ContractError) + fails { @o.not_nil(nil) } end end describe "ArrayOf:" do it "should pass for an array of nums" do - expect { @o.product([1, 2, 3]) }.to_not raise_error + passes { @o.product([1, 2, 3]) } end it "should fail for an array with one non-num" do - expect { @o.product([1, 2, 3, "bad"]) }.to raise_error(ContractError) + fails { @o.product([1, 2, 3, "bad"]) } end it "should fail for a non-array" do - expect { @o.product(1) }.to raise_error(ContractError) + fails { @o.product(1) } end end describe "RangeOf:" do require "date" it "should pass for a range of nums" do - expect { @o.first_in_range_num(3..10) }.to_not raise_error + passes { @o.first_in_range_num(3..10) } end it "should pass for a range of dates" do d1 = Date.today d2 = d1 + 18 - expect { @o.first_in_range_date(d1..d2) }.to_not raise_error + passes { @o.first_in_range_date(d1..d2) } end it "should fail for a non-range" do - expect { @o.first_in_range_num("foo") }.to raise_error(ContractError) - expect { @o.first_in_range_num(:foo) }.to raise_error(ContractError) - expect { @o.first_in_range_num(5) }.to raise_error(ContractError) - expect { @o.first_in_range_num(nil) }.to raise_error(ContractError) + fails { @o.first_in_range_num("foo") } + fails { @o.first_in_range_num(:foo) } + fails { @o.first_in_range_num(5) } + fails { @o.first_in_range_num(nil) } end it "should fail for a range with incorrect data type" do - expect { @o.first_in_range_num("a".."z") }.to raise_error(ContractError) + fails { @o.first_in_range_num("a".."z") } end it "should fail for a badly-defined range" do @@ -302,8 +310,8 @@ # This test guards against ranges with inconsistent data types. begin d1 = Date.today - expect { @o.first_in_range_date(d1..10).to raise_error(ContractError) } - expect { @o.first_in_range_num(d1..10).to raise_error(ContractError) } + fails { @o.first_in_range_date(d1..10) } + fails { @o.first_in_range_num(d1..10) } rescue ArgumentError # If Ruby doesn't like the range, we ignore the test. :nop @@ -313,26 +321,26 @@ describe "SetOf:" do it "should pass for a set of nums" do - expect { @o.product_from_set(Set.new([1, 2, 3])) }.to_not raise_error + passes { @o.product_from_set(Set.new([1, 2, 3])) } end it "should fail for an array with one non-num" do - expect { @o.product_from_set(Set.new([1, 2, 3, "bad"])) }.to raise_error(ContractError) + fails { @o.product_from_set(Set.new([1, 2, 3, "bad"])) } end it "should fail for a non-array" do - expect { @o.product_from_set(1) }.to raise_error(ContractError) + fails { @o.product_from_set(1) } end end describe "Bool:" do it "should pass for an argument that is a boolean" do - expect { @o.bool_test(true) }.to_not raise_error - expect { @o.bool_test(false) }.to_not raise_error + passes { @o.bool_test(true) } + passes { @o.bool_test(false) } end it "should fail for nil" do - expect { @o.bool_test(nil) }.to raise_error(ContractError) + fails { @o.bool_test(nil) } end end @@ -346,31 +354,31 @@ end it "should fail for strings" do - expect { @o.maybe_double("foo") }.to raise_error(ContractError) + fails { @o.maybe_double("foo") } end end describe "KeywordArgs:" do it "should pass for exact correct input" do - expect { @o.person_keywordargs(:name => "calvin", :age => 10) }.to_not raise_error + passes { @o.person_keywordargs(:name => "calvin", :age => 10) } end it "should fail if some keys don't have contracts" do - expect { @o.person_keywordargs(:name => "calvin", :age => 10, :foo => "bar") }.to raise_error(ContractError) + fails { @o.person_keywordargs(:name => "calvin", :age => 10, :foo => "bar") } end it "should fail if a key with a contract on it isn't provided" do - expect { @o.person_keywordargs(:name => "calvin") }.to raise_error(ContractError) + fails { @o.person_keywordargs(:name => "calvin") } end it "should fail for incorrect input" do - expect { @o.person_keywordargs(:name => 50, :age => 10) }.to raise_error(ContractError) - expect { @o.hash_keywordargs(:hash => nil) }.to raise_error(ContractError) - expect { @o.hash_keywordargs(:hash => 1) }.to raise_error(ContractError) + fails { @o.person_keywordargs(:name => 50, :age => 10) } + fails { @o.hash_keywordargs(:hash => nil) } + fails { @o.hash_keywordargs(:hash => 1) } end it "should pass if a method is overloaded with non-KeywordArgs" do - expect { @o.person_keywordargs("name", 10) }.to_not raise_error + passes { @o.person_keywordargs("name", 10) } end end @@ -402,10 +410,10 @@ def something(hash) end context "given an unfulfilled contract" do - it { expect { @o.gives_max_value(:panda => "1", :bamboo => "2") }.to raise_error(ContractError) } - it { expect { @o.gives_max_value(nil) }.to raise_error(ContractError) } - it { expect { @o.gives_max_value(1) }.to raise_error(ContractError) } - it { expect { @o.pretty_gives_max_value(:panda => "1", :bamboo => "2") }.to raise_error(ContractError) } + it { fails { @o.gives_max_value(:panda => "1", :bamboo => "2") } } + it { fails { @o.gives_max_value(nil) } } + it { fails { @o.gives_max_value(1) } } + it { fails { @o.pretty_gives_max_value(:panda => "1", :bamboo => "2") } } end describe "#to_s" do @@ -422,39 +430,31 @@ def something(hash) describe "StrictHash:" do context "when given an exact correct input" do it "does not raise an error" do - expect do - @o.strict_person(:name => "calvin", :age => 10) - end.to_not raise_error + passes { @o.strict_person(:name => "calvin", :age => 10) } end end context "when given an input with correct keys but wrong types" do it "raises an error" do - expect do - @o.strict_person(:name => "calvin", :age => "10") - end.to raise_error(ContractError) + fails { @o.strict_person(:name => "calvin", :age => "10") } end end context "when given an input with missing keys" do it "raises an error" do - expect do - @o.strict_person(:name => "calvin") - end.to raise_error(ContractError) + fails { @o.strict_person(:name => "calvin") } end end context "when given an input with extra keys" do it "raises an error" do - expect do - @o.strict_person(:name => "calvin", :age => "10", :soft => true) - end.to raise_error(ContractError) + fails { @o.strict_person(:name => "calvin", :age => "10", :soft => true) } end end context "when given not a hash" do it "raises an error" do - expect { @o.strict_person(1337) }.to raise_error(ContractError) + fails { @o.strict_person(1337) } end end end