def notcontain_behaviour(): ''' NotContain comparator should negate the behaviour of Contain ''' spec = Spec(NotContain(1)) spec.description().should_be('not contain 1') spec.compares_to([1, 2]).should_be(False) spec.compares_to([1]).should_be(False) spec.compares_to([2]).should_be(True)
def can_override_comparators(self): ''' should be able to specify any comparator for arg verification ''' mock_spec = MockSpec(comparators={Exception: Nothing}) mock_call = mock_spec.your_mother(TypeError('hamster')) mock_call_result = mock_call.result_of('your_mother') spec = Spec(mock_call_result) spec.__call__(TypeError('hamster')).should_raise(UnmetSpecification)
def should_notify_mock_spec(self): ''' start_collaborating should pass message on to mock_spec ''' mock_spec = MockSpec() mock_call = mock_spec.foo().once() Spec(mock_call).start_collaborating().should_be(mock_spec) Spec(mock_spec).bar().should_raise(UnmetSpecification) Spec(mock_spec).foo().should_not_raise(UnmetSpecification)
def can_override_comparators(self): ''' should be able to specify any comparator for arg verification ''' mock_spec = MockSpec(comparators={Exception:Nothing}) mock_call = mock_spec.your_mother(TypeError('hamster')) mock_call_result = mock_call.result_of('your_mother') spec = Spec(mock_call_result) spec.__call__(TypeError('hamster')).should_raise(UnmetSpecification)
def greaterthanorequal_behaviour(): ''' GreaterThanOrEqual should compare using >= ''' spec = Spec(GreaterThanOrEqual(2)) spec.description().should_be("=> 2") spec.compares_to(2).should_be(True) spec.compares_to(1).should_be(False) spec.compares_to('a').should_be(False)
def spec_getattr_behaviour(): ''' getattr from spec should return wrapper for unknown attributes ''' spec = Spec(lambda: getattr(Spec('grail'), 'should')) spec.__call__().should_not_be(Type(WrapFunction)) # Spec.should() exists spec = Spec(lambda: getattr(Spec('life'), 'death')) spec.__call__().should_be(Type(WrapFunction)) # Spec.death() not exists
def verify_should_invoke_callable(self): ''' verify should invoke callable and compare result ''' a_list = [] with_callable = lambda: a_list.append(True) spec = Spec(Constraint()) spec.verify(with_callable).should_raise(UnmetSpecification) spec.then(a_list.__len__).should_be(1)
def nothing_behaviour(): ''' Nothing comparator should never find compared objects equivalent. ''' spec = Spec(Nothing()) spec.description().should_be("nothing") spec.compares_to(1).should_be(False) spec.compares_to('1').should_be(False) spec.compares_to([1]).should_be(False) spec.compares_to('xyz').should_be(False)
def mock_call_successive_times(): ''' once(), twice() and times() should return the mock call ''' mock_call = MockSpec().foo() Spec(mock_call).once().should_be(mock_call) mock_call = MockSpec().foo() Spec(mock_call).twice().should_be(mock_call) mock_call = MockSpec().foo() Spec(mock_call).times(3).should_be(mock_call)
def override_comparators_dont_replace_all(self): ''' comparator overrides only affect comparator used for that type ''' mock_spec = MockSpec(comparators={float:EqualsEquals}) mock_call = mock_spec.your_mother(TypeError('hamster')) mock_call_result = mock_call.result_of('your_mother') spec = Spec(mock_call_result) spec.__call__(TypeError('hamster')) spec.should_not_raise(UnmetSpecification)
def anything_behaviour(): ''' Anything comparator should find all compared objects equivalent. ''' spec = Spec(Anything()) spec.description().should_be("anything") spec.compares_to(1).should_be(True) spec.compares_to('1').should_be(True) spec.compares_to([1]).should_be(True) spec.compares_to('xyz').should_be(True)
def lessthanorequal_behaviour(): ''' LessThanOrEqual should compare using <= ''' spec = Spec(LessThanOrEqual(2)) spec.description().should_be("<= 2") spec.compares_to(1).should_be(True) spec.compares_to(2).should_be(True) spec.compares_to(3).should_be(False) spec.compares_to('a').should_be(False)
def should_delegate_eq(self): ''' base Comparator should delegate __eq__ to compare_to. ''' #TODO: nicer way of forcing spec to use underlying __eq__ base_comparator_equals = Comparator(1).__eq__ spec = Spec(base_comparator_equals) spec.__call__(1).should_be(False) spec.__call__(2).should_be(False) spec.__call__(int).should_be(False)
def given_typechecking_behaviour(): ''' Spec for check that given=... is correct type ''' def spec_for_dict_given_empty_list(): ''' callable method to defer instance creation until within Spec ''' return Spec(type({}), given=lambda: []) spec = Spec(spec_for_dict_given_empty_list) type_error = TypeError("[] is not instance of <class 'dict'>") spec.__call__().should_raise(type_error)
def notnonevalue_behaviour(): ''' NotNoneValue comparator should compare objects with not-None ''' spec = Spec(NotNoneValue()) spec.description().should_be('not None') spec.compares_to(None).should_be(False) spec.compares_to(1).should_be(True) spec.compares_to(2).should_be(True) spec.compares_to([]).should_be(True) spec.compares_to('').should_be(True)
def should_trap_incorrect_return(self): ''' Specified and_result="bar" but was "baz": UnmetSpecification. Note: and_result refers to the value returned from the callable invoked in verify(), not the return value from the mock. See the Hungarian gentleman in the examples for a clearer picture... ''' mock_spec = MockSpec() spec = Spec(CollaborateWith(mock_spec.foo().will_return('baz'), and_result='bar')) spec.verify(lambda: mock_spec.foo()).should_raise(UnmetSpecification)
def should_trap_incorrect_args(self): ''' Specified foo(2) & bar(), and foo(1) called: UnmetSpecification''' mock_spec = MockSpec() collaborations = (mock_spec.foo(2), mock_spec.bar()) descriptions = [collaboration.description() for collaboration in collaborations] spec = Spec(CollaborateWith(*collaborations)) spec.describe_constraint().should_be(','.join(descriptions)) spec.verify(lambda: mock_spec.foo(1)).should_raise(UnmetSpecification)
def desc_should_use_comparator(self): ''' describe_constraint should delegate to comparator.description ''' comparator = MockSpec() spec = Spec(Constraint(comparator)) comparator_description = comparator.description() comparator_description.will_return('subtitled') spec.describe_constraint() spec.should_collaborate_with(comparator_description, and_result='should be subtitled')
def given_when_then_behaviour(): ''' given empty list when item appended then list length should be one ''' spec = Spec([]) spec.when(spec.append(object())).then(spec.it()).should_be(Length(1)) def empty_list(): ''' descriptive name for fn returning an empty list ''' return [] spec = Spec(type([]), given=empty_list) spec.when(spec.append('monty')).then(spec.it()).should_be(Length(1))
def should_trap_incorrect_return(self): ''' Specified and_result="bar" but was "baz": UnmetSpecification. Note: and_result refers to the value returned from the callable invoked in verify(), not the return value from the mock. See the Hungarian gentleman in the examples for a clearer picture... ''' mock_spec = MockSpec() spec = Spec( CollaborateWith(mock_spec.foo().will_return('baz'), and_result='bar')) spec.verify(lambda: mock_spec.foo()).should_raise(UnmetSpecification)
def atomic_raise_behaviour(): ''' should_raise() and should_not_raise() are the only "atomic" parts that require test assertions. All other functionality can be bootstrap-specified using these methods. ''' spec1 = Spec(dont_raise_index_error) try: spec1.dont_raise_index_error().should_raise(IndexError) assert False except UnmetSpecification: # UnmetSpecification because no IndexError is raised pass spec2 = Spec(raise_index_error) try: spec2.raise_index_error().should_not_raise(IndexError) assert False except UnmetSpecification: # UnmetSpecification because an IndexError is raised pass spec2 = Spec(raise_index_error) try: spec2.raise_index_error().should_raise(ValueError) assert False except IndexError: # Not UnmetSpecification because IndexError is raised, not ValueError pass
def external_then_behaviour(): ''' Spec for then()... actions that call outside the spec itself. Note that the action on the spec is invoked in client code with parens(): spec.then( * spec.__len__() * ).should_be(1) but the action outside the spec is NOT: spec.then( * 'they called him brian'.__len__ * ).should_be(21) ''' spec = Spec([]) spec.when(spec.append('brian')) spec.then(spec.__len__()).should_be(1) spec.then('they called him brian'.__len__).should_be(21)
def verify_exceptions_with_comparator(self): ''' ExceptionValue should be used to verify Exception args ''' mock_call = MockSpec().your_mother(TypeError('hamster')) mock_call_result = mock_call.result_of('your_mother') spec = Spec(mock_call_result) spec.__call__(TypeError('hamster')) spec.should_not_raise(UnmetSpecification) mock_call = MockSpec().your_father(smelt_of=TypeError('elderberries')) mock_call_result = mock_call.result_of('your_father') spec = Spec(mock_call_result) spec.__call__(smelt_of=TypeError('elderberries')) spec.should_not_raise(UnmetSpecification)
def should_add_to_collation(self): ''' verifiable should add fn to ALL_VERIFIABLE and return it ''' all_verifiable = silent_listener() spec = Spec(verifiable) spec.verifiable(number_one, all_verifiable).should_be(number_one) num_verifiable_before = all_verifiable.total() spec.when(spec.verifiable(string_abc, all_verifiable)) spec.then(all_verifiable.total).should_be(num_verifiable_before + 1)
def should_check_message(self): ''' Raise should verify exception type & message vs specified ''' spec = Spec(Raise(IndexError('with message'))) spec.verify(raise_index_error).should_not_raise(UnmetSpecification) spec = Spec(Raise(IndexError('with different message'))) spec.verify(raise_index_error).should_raise(UnmetSpecification)
def should_verify_each_item(self): ''' verify() should execute each included item ''' a_list = [] lambda_list_append1 = lambda: a_list.append(0) lambda_list_append2 = lambda: a_list.extend((1, 2)) spec = Spec(AllVerifiable, given=silent_listener) spec.when(spec.include(lambda_list_append1), spec.include(lambda_list_append2), spec.verify()) spec.then(a_list.__len__).should_be(3)
def should_verify_name(self): ''' result_of should verify the name specification ''' mock_call = MockSpec(name='p').foo() spec = Spec(mock_call) msg = 'should be collaborating with p.foo(), not p.bar()' spec.result_of('bar').should_raise(UnmetSpecification(msg)) mock_call = MockSpec().foo() spec = Spec(mock_call) spec.result_of('foo').should_not_raise(UnmetSpecification)
def override_comparators_dont_replace_all(self): ''' comparator overrides only affect comparator used for that type ''' mock_spec = MockSpec(comparators={float: EqualsEquals}) mock_call = mock_spec.your_mother(TypeError('hamster')) mock_call_result = mock_call.result_of('your_mother') spec = Spec(mock_call_result) spec.__call__(TypeError('hamster')) spec.should_not_raise(UnmetSpecification)
def should_trap_incorrect_args(self): ''' Specified foo(2) & bar(), and foo(1) called: UnmetSpecification''' mock_spec = MockSpec() collaborations = (mock_spec.foo(2), mock_spec.bar()) descriptions = [ collaboration.description() for collaboration in collaborations ] spec = Spec(CollaborateWith(*collaborations)) spec.describe_constraint().should_be(','.join(descriptions)) spec.verify(lambda: mock_spec.foo(1)).should_raise(UnmetSpecification)
def should_be_value_behaviour(): ''' Basic specification of the Spec.should...() methods''' spec = Spec(number_one) spec.number_one().should_be(1) spec.number_one().should_not_be(2) spec.number_one().should_not_be('a') spec = Spec(string_abc) spec.string_abc().should_be('abc') spec.string_abc().should_not_be('a') spec.string_abc().should_not_be(2)
def floatvalue_behaviour(): ''' FloatValue comparator should compare objects with tolerance for FPA ''' spec = Spec(FloatValue(1.1)) spec.tolerance().should_be(0.01) spec.compares_to(1.1).should_be(True) spec.description().should_be('within 0.01 of 1.1') spec.compares_to(1.11).should_be(True) spec.compares_to(1.12).should_be(False) spec.compares_to(1.2).should_be(False) spec.compares_to(1.09).should_be(True) spec.compares_to(1.08).should_be(False) spec.compares_to(1.0).should_be(False) spec = Spec(FloatValue(1.1, 0.05)) spec.tolerance().should_be(0.05) spec.description().should_be('within 0.05 of 1.1') spec.compares_to(1.1).should_be(True) spec.compares_to(1.11).should_be(True) spec.compares_to(1.12).should_be(True) spec.compares_to(1.2).should_be(False) spec.compares_to(1.09).should_be(True) spec.compares_to(1.08).should_be(True) spec.compares_to(1.0).should_be(False) spec = Spec(FloatValue(1.11)) spec.tolerance().should_be(0.001) spec.description().should_be('within 0.001 of 1.11') spec = Spec(FloatValue(1.99)) spec.tolerance().should_be(0.001) spec = Spec(FloatValue(2)) spec.tolerance().should_be(0.1)
def exceptionvalue_behaviour(): ''' ExceptionValue comparator should compare type and messsage ''' spec = Spec(ExceptionValue(IndexError('with message'))) spec.description().should_be('%r' % IndexError('with message')) spec.compares_to(IndexError('with message')).should_be(True) spec.compares_to(IndexError('different message')).should_be(False) spec.compares_to(ValueError('with message')).should_be(False) spec = Spec(ExceptionValue(IndexError)) spec.description().should_be('IndexError') spec.compares_to(IndexError('with message')).should_be(True) spec.compares_to(IndexError('different message')).should_be(True) spec.compares_to(ValueError('with message')).should_be(False)
def type_behaviour(): ''' Type comparator should compare type() ''' spec = Spec(Type(list)) spec.compares_to([]).should_be(True) spec.compares_to({}).should_be(False) spec.description().should_be("type <class 'list'>") spec = Spec(Type([])) spec.compares_to([]).should_be(True) spec.compares_to({}).should_be(False) spec.description().should_be("type <class 'list'>")
def reprequals_behaviour(): ''' ReprEquals comparator should compare objects with repr() ''' spec = Spec(ReprEquals(1)) spec.description().should_be('repr() value 1') spec.compares_to(1).should_be(True) spec.compares_to('1').should_be(False) spec.compares_to([1]).should_be(False) spec = Spec(ReprEquals('1')) spec.description().should_be("repr() value '1'") spec.compares_to('1').should_be(True) spec.compares_to(1).should_be(False) spec.compares_to([1]).should_be(False)
def not_behaviour(): ''' Not should raise exception iff underlying check succeeds ''' spec = Spec(Not(Constraint(EqualsEquals(2)))) spec.verify(number_one).should_not_raise(UnmetSpecification) spec = Spec(Not(Constraint(EqualsEquals(1)))) msg = 'should not be == 1' spec.describe_constraint().should_be(msg) spec.verify(number_one).should_raise(UnmetSpecification(msg)) spec = Spec(Not(Not(Constraint(EqualsEquals(2))))) msg = 'should be == 2' spec.describe_constraint().should_be(msg) spec.verify(number_one).should_raise(UnmetSpecification(msg))
def should_check_type(self): ''' Raise should check that exception is raised ''' spec = Spec(Raise(IndexError)) spec.verify(raise_index_error).should_not_raise(UnmetSpecification) spec.verify(dont_raise_index_error).should_raise(UnmetSpecification)
def should_use_comparator_desc(self): ''' base Comparator description should be type name plus prototype ''' Spec(Comparator('x')).description().should_be("comparator 'x'") Spec(Comparator(1)).description().should_be("comparator 1")
def should_have_meaningful_msg(self): ''' Raise should produce meaningful UnmetSpecification messages''' spec = Spec(Raise(IndexError)) msg = "should raise IndexError" spec.describe_constraint().should_be(msg) spec.verify(dont_raise_index_error) spec.should_raise(UnmetSpecification(msg)) spec = Spec(Raise(IndexError('with some message'))) msg = "should raise IndexError('with some message',)" spec.describe_constraint().should_be(msg) unmet_msg = msg + ", not IndexError('with message',)" unmet_specification = UnmetSpecification(unmet_msg) spec.verify(raise_index_error).should_raise(unmet_specification)
def orcomparator_behaviour(): ''' OrComparator should chain "either-or" comparisons together ''' spec = Spec(OrComparator(LessThan(2), EqualsEquals(2))) spec.description().should_be("< 2 or == 2") spec.compares_to(1).should_be(True) spec.compares_to(2).should_be(True) spec.compares_to(3).should_be(False) spec.compares_to('a').should_be(False) spec = Spec(OrComparator(GreaterThan(2), EqualsEquals(2))) spec.description().should_be("> 2 or == 2") spec.compares_to(2).should_be(True) spec.compares_to(1).should_be(False) spec.compares_to('a').should_be(False)
def notcomparator_behaviour(): ''' NotComparator should negate other comparisons ''' spec = Spec(NotComparator(EqualsEquals(1))) spec.description().should_be('not == 1') spec.compares_to(1).should_be(False) spec.compares_to('1').should_be(True) spec.compares_to([1]).should_be(True) spec = Spec(NotComparator(EqualsEquals('1'))) spec.description().should_be("not == '1'") spec.compares_to('1').should_be(False) spec.compares_to(1).should_be(True) spec.compares_to([1]).should_be(True)
def verify_should_use_comparator(self): ''' verify should delegate to comparator.compares_to ''' comparator = MockSpec() spec = Spec(Constraint(comparator)) comparator_compares_to = comparator.compares_to(1).will_return(True) spec.verify(lambda: 1).should_collaborate_with(comparator_compares_to)
def strequals_behaviour(): ''' StrEquals comparator should compare objects with str() ''' spec = Spec(StrEquals(1)) spec.description().should_be("str() value '1'") spec.compares_to(1).should_be(True) spec.compares_to('1').should_be(True) spec.compares_to([1]).should_be(False) spec = Spec(StrEquals('1')) spec.description().should_be("str() value '1'") spec.compares_to(1).should_be(True) spec.compares_to('1').should_be(True) spec.compares_to([1]).should_be(False)
def should_contain_behaviour(): ''' should_ and should_not_ contain methods delegate to Contain ''' spec = Spec(['brave', 'brave', 'sir robin']) spec.it().should_contain('brave') spec.it().should_not_contain('bravely ran away')
def should_use_nothing_comparator(self): ''' Constraint should use Nothing comparator by default''' spec = Spec(Constraint()) spec.describe_constraint().should_be('should be nothing') spec.verify_value(1).should_be(False) spec.verify_value(2).should_be(False) spec.verify_value(None).should_be(False) spec.verify_value(['majestic', 'moose']).should_be(False) spec.verify_value({'gumby': 'brain surgeon'}).should_be(False)