Should-DSL Matchers =================== You can find below some explanations on the available matchers of *should_dsl* package. Before all, you need to import it:: >>> from should_dsl import should, should_not ------------ **be** Checks object identity (*is*). :: >>> 1 |should| be(1) >>> a = "some message" >>> b = "some message" >>> id(a) == id(b) # the strings are equal but with different ids False >>> a |should| be(b) Traceback (most recent call last): ... ShouldNotSatisfied: 'some message' was expected to be 'some message' >>> c = "another message" >>> d = c >>> id(c) == id(d) True >>> c |should| be(d) **be_greater_than** **be_greater_than_or_equal_to** **be_less_than** **be_less_than_or_equal_to** Simply check the return of comparisons. :: >>> 1 |should_not| be_greater_than(1) >>> 2 |should| be_greater_than_or_equal_to(2) >>> 0.1 |should| be_less_than(0.11) >>> 3000 |should| be_less_than_or_equal_to(3001) **be_into** **contain** **include** Verify if an object is contained (*be_into*) or contains (*contain*) another. The *contain* and *include* matchers do exactly the same job. :: >>> 1 |should| be_into(range(2)) >>> ['a'] |should_not| be_into(['a']) >>> ['a'] |should| be_into([['a']]) >>> ['x', 'y', 'z'] |should| contain('z') >>> ['x', 'y', 'z'] |should| include('z') **be_empty** Verifies if an object is empty. Works for lists, strings, tuples, dictionaries, and any object that implements *__len__()*. :: >>> '' |should| be_empty >>> [] |should| be_empty >>> () |should| be_empty >>> {} |should| be_empty **be_kind_of** Verifies if an object is of a given type. :: >>> 1 |should| be_kind_of(int) >>> class Foo: pass >>> Foo() |should| be_kind_of(Foo) >>> class Bar(Foo): pass >>> Bar() |should| be_kind_of(Foo) **be_instance_of** Same as be_kind_of, but using *instance* word. **be_like** Checks matching against a regular expression. :: >>> 'Hello World' |should| be_like(r'Hello W.+') >>> '123 is a number' |should_not| be_like(r'^[12]+ is a number') *be_like* accepts flags from *re* module as its (optional) second parameter. :: >>> import re >>> 'Hello\nWorld' |should| be_like(r'hell.+', re.DOTALL|re.IGNORECASE) **be_thrown_by** **throw** Check the raising of exceptions. :: >>> ZeroDivisionError |should| be_thrown_by(lambda: 1/0) >>> (lambda: 1/0.000001) |should_not| throw(ZeroDivisionError) *throw* matcher also supports message checking. :: >>> def foo(): raise TypeError("Hey, it's cool!") >>> foo |should| throw(TypeError, message="Hey, it's cool!") >>> foo |should| throw(TypeError, message="This won't work...") Traceback (most recent call last): ... ShouldNotSatisfied: expected to throw 'TypeError' with the message "This won't work...", got 'TypeError' with "Hey, it's cool!" If the function or method has parameters, it must be called within a lambda or using a tuple. The following ways are both equivalent:: >>> def divide(x, y): return x / y >>> (lambda: divide(1, 0)) |should| throw(ZeroDivisionError) >>> (divide, 1, 0) |should| throw(ZeroDivisionError) The same works for *be_thrown_by* matcher. **change** Checks for changes on the result of a given function, method or lambda. :: >>> class Box(object): ... def __init__(self): ... self.items = [] ... def add_items(self, *items): ... for item in items: ... self.items.append(item) ... def item_count(self): ... return len(self.items) ... def clear(self): ... self.items = [] >>> box = Box() >>> box.add_items(5, 4, 3) >>> box.clear |should| change(box.item_count) >>> box.clear |should_not| change(box.item_count) If the function or method has parameters, it must be called within a lambda or using a tuple. The following ways are both equivalent:: >>> (lambda: box.add_items(1, 2, 3)) |should| change(box.item_count) >>> (box.add_items, 1, 2, 3) |should| change(box.item_count) *change* also works with an arbitrary change count:: >>> box.clear() >>> box.add_items(1, 2, 3) >>> box.clear |should| change(box.item_count).by(-3) >>> box.add_items(1, 2, 3) >>> box.clear |should| change(box.item_count).by(-2) Traceback (most recent call last): ... ShouldNotSatisfied: result should have changed by -2, but was changed by -3 *change* has support for maximum and minumum with *by_at_most* and *by_at_least*:: >>> (box.add_items, 1, 2, 3) |should| change(box.item_count).by_at_most(3) >>> (box.add_items, 1, 2, 3) |should| change(box.item_count).by_at_most(2) Traceback (most recent call last): ... ShouldNotSatisfied: result should have changed by at most 2, but was changed by 3 >>> (box.add_items, 1, 2, 3) |should| change(box.item_count).by_at_least(3) >>> (box.add_items, 1, 2, 3) |should| change(box.item_count).by_at_least(4) Traceback (most recent call last): ... ShouldNotSatisfied: result should have changed by at least 4, but was changed by 3 Finally, *change* supports specifying both the initial and final values or only the final one:: >>> box.clear() >>> (box.add_items, 1, 2, 3) |should| change(box.item_count).from_(0).to(3) >>> box.clear |should| change(box.item_count).to(0) >>> box.clear |should| change(box.item_count).to(0) Traceback (most recent call last): ... ShouldNotSatisfied: result should have been changed to 0, but is now 0 **close_to** Checks if a number is close to another, given a delta. :: >>> 1 |should| close_to(0.9, delta=0.1) >>> 0.8 |should| close_to(0.9, delta=0.1) >>> 1 |should_not| close_to(0.89, delta=0.1) >>> 4.9 |should| close_to(4, delta=0.9) **end_with** Verifies if a string ends with a given suffix. :: >>> "Brazil champion of 2010 FIFA world cup" |should| end_with('world cup') >>> "hello world" |should_not| end_with('worlds') **equal_to** Checks object equality (not identity). :: >>> 1 |should| equal_to(1) >>> class Foo: pass >>> Foo() |should_not| equal_to(Foo()) >>> class Foo(object): ... def __eq__(self, other): ... return True >>> Foo() |should| equal_to(Foo()) It can even show you a diff if you are comparing two big strings. :: >>> 'big' |should| equal_to('big\nstring', diff=True) Traceback (most recent call last): ... ShouldNotSatisfied: the strings are different, see the diff below: --- actual +++ expected @@ -1,1 +1,2 @@ -big+big +string This matcher can check string equality ignoring case too. A bonus: you can combine this feature with the diff parameter too. :: >>> 'abc' |should| equal_to('abC', case_sensitive=False) **equal_to_ignoring_case** Checks equality of strings ignoring case. :: >>> 'abc' |should| equal_to_ignoring_case('AbC') >>> 'XYZAb' |should| equal_to_ignoring_case('xyzaB') **have** Checks the element count of a given collection. Works with iterables, requiring a qualifier expression for readability purposes, which is in fact only a syntax sugar. ::) >>> ['b', 'c', 'd'] |should| have(3).elements >>> [1, [1, 2, 3], 'a', lambda: 1, 2**3] |should| have(5).heterogeneous_things >>> ['asesino', 'japanische kampfhoerspiele', 'facada'] |should| have(3).grindcore_bands >>> "left" |should| have(4).characters *have* also works with non-iterable objects, if the qualifier is an attribute name or method that contains the collection to be count. :: >>> class Foo: ... def __init__(self): ... self.inner_things = ['a', 'b', 'c'] ... def pieces(self): ... return range(10) >>> Foo() |should| have(3).inner_things >>> Foo() |should| have(10).pieces *have* allows counting collections within field objects. :: >>> class Field: ... def __init__(self, number_of_players): ... self.players = range(number_of_players) >>> class SoccerGame: ... def __init__(self): ... self.field = Field(22) >>> SoccerGame() |should| have(22).players_on_field **have_at_least** The same as *have*, but checking if the element count is greater than or equal to the given value. Works for collections with syntax sugar, object attributes, or methods. :: >>> range(20) |should| have_at_least(19).items >>> range(20) |should| have_at_least(20).items >>> range(20) |should_not| have_at_least(21).items **have_at_most** The same as *have*, but checking if the element count is less than or equal to the given value. Works for collections with syntax sugar, object attributes, or methods. :: >>> range(20) |should_not| have_at_most(19).items >>> range(20) |should| have_at_most(20).items >>> range(20) |should| have_at_most(21).items **include_all_of** **include_in_any_order** Check if an iterable includes all elements of another. Both matchers do the same job. :: >>> [4, 5, 6, 7] |should| include_all_of([5, 6]) >>> [4, 5, 6, 7] |should| include_in_any_order([5, 6]) >>> ['b', 'c'] |should| include_all_of(['b', 'c']) >>> ['b', 'c'] |should| include_in_any_order(['b', 'c']) >>> ['b', 'c'] |should_not| include_all_of(['b', 'c', 'a']) >>> ['b', 'c'] |should_not| include_in_any_order(['b', 'c', 'a']) **include_any_of** Checks if an iterable includes any element of another. :: >>> [1, 2, 3] |should| include_any_of([3, 4, 5]) >>> (1,) |should| include_any_of([4, 6, 3, 1, 9, 7]) **include_keys** Checks if a dictionary includes all given keys. :: >>> {'a': 1, 'b': 2, 'c': 3} |should| include_keys('a', 'b') >>> {'a': 1, 'b': 2, 'c': 3} |should_not| include_keys('d') **include_values** Checks if a dictionary includes all given values. :: >>> {'a': 1, 'b': 2, 'c': 3} |should| include_values(2, 3) >>> {'a': 1, 'b': 2, 'c': 3} |should_not| include_values(0, 4) **respond_to** Checks if an object has a given attribute or method. :: >>> 'some string' |should| respond_to('startswith') >>> class Foo: ... def __init__(self): ... self.foobar = 10 ... def bar(self): pass >>> Foo() |should| respond_to('foobar') >>> Foo() |should| respond_to('bar') **start_with** Verifies if a string starts with a given prefix. :: >>> "Brazil champion of 2010 FIFA world cup" |should| start_with('Brazil champion') >>> "hello world" |should_not| start_with('Hello') **have_same_attribute_values_as** Verifies if an object have the same attribute values as another one. :: >>> class Foo(object): ... def __init__(self, a, b): ... self.a = a ... self.b = b >>> a = Foo(1,2) >>> b = Foo(1,2) >>> a |should| have_same_attribute_values_as(b)