PyHamcrest-1.8.0/0000755000076500000240000000000012230156532014107 5ustar offby1staff00000000000000PyHamcrest-1.8.0/CHANGES.txt0000644000076500000240000001300412230143133015707 0ustar offby1staff00000000000000=== Version 1.8 == * Supported versions - Support for Python 2.5 and Jython 2.5 has been dropped. They may still work, but no promises. * Bug Fixes - [#39] is_empty was missing from the global namespace * New Features - Support for numpy numeric values in iscloseto (Alexander Beedie) - A matcher targeting exceptions and call results (Per Fagrell) === Version 1.7 == 2 Sep 2013 (Version 1.7.2) * Supported versions - As of this version, support for Python 3.1 has been dropped due to no available CI platform. - Added support for Python 3.3 * Bug fixes: - string_contains_in_order is now used in the test as it would be in an application, and is properly exported. (Romilly Cocking) - Fix mismatch description of containing_inanyorder (David Keijser) - added import of stringmatches to text/__init__.py (Eric Scheidemantle) - added matches_regexp to __all__ list to library/__init__.py (Eric Scheidemantle) 5 Jan 2010 (Version 1.7.1) * Bug fixes: - included a fix by jaimegildesagredo for issue #28 (has_properties was not importable) - included a fix by keys for contains_inanyorder 29 Dec 2012 (All changes by Chris Rose unless otherwise noted.) * New matchers: - matches_regexp matches a regular expression in a string. - has_properties matches an object with more than one property. - is_empty matches any object with length 0. * Improvements: - Can now do matching against old-style classes. - Sequence matchers handle generators, as well as actual sequences and pseudo-sequences. - README enhancements by ming13 === Version 1.6 == 27 Sep 2011 (All changes by Chris Rose unless otherwise noted.) * Packaging: - Python 3.2 support. * New matchers: - has_property('property_name', value_matcher) matches if object has a property with a given name whose value satisfies a given matcher. * Improvements: - hasEntries supports two new calling conventions: has_entries({'key' : value_matcher, 'key_2' : other_value_matcher}) has_entries(key=value_matcher, key_2=other_value_matcher) - Describe Unicode strings by their __repr__. Thanks to: Sebastian Arming - Rewrote documentation. (Jon Reid) == Version 1.5 == 29 Apr 2011 * Packaging: - Python 3.1 support. Thanks to: Chris Rose - Easier installation with bootstrapping. Thanks to: Chris Rose * Mock integration: - "match_equality" wraps a matcher to define equality in terms of satisfying the matcher. This allows Hamcrest matchers to be used in libraries that are not Hamcrest-aware, such as Michael Foord's mock library. Thanks to: Chris Rose * New matcher: - "string_contains_in_order" matches string containing given list of substrings, in order. Thanks to: Romilly Cocking * Improved matchers: - For consistency, changed "any_of" and "all_of" to implicitly wrap non-matcher values in EqualTo. Thanks to: Chris Rose - Changed "sameInstance" mismatch description to omit address when describing None. == Version 1.4 == 13 Feb 2011 * New matchers: - "has_entries" matches dictionary containing key-value pairs satisfying a given list of alternating keys and value matchers. * "assert_that" can be invoked with a single boolean argument; the reason message is now optional. This is a convenience replacement for assertTrue. Thanks to: Jeong-Min Lee * Improved descriptions: - Reverted 1.3 change: Describe None as "" after all, since it is an object. - "is_" no longer says "is ..." in its description, but just lets the inner description pass through. - Consistently use articles to begin descriptions, such as "a sequence containing" instead of "sequence containing". == Version 1.3 == 04 Feb 2011 * PyHamcrest is now compatible with Python 3! To install PyHamcrest on Python 3: - Install the "distribute" package, http://pypi.python.org/pypi/distribute - Run "python3 setup.py install" Unit tests are not converted by the install procedure. Run "2to3 -nw ." separately to convert them. You may discover import statements in the __init__.py files (and one in core/base_description.py) that need dot prefixes. Thanks to: Jeong-Min Lee * Improved descriptions and mismatch descriptions of several matchers, including: - Fixed "contains" and "contains_inanyorder" to describe mismatch if item is not a sequence. - Fixed "described_as" to use nested matcher to generate mismatch description. - "same_instance" is more readable, and includes object memory addresses. - If object has a length, "has_length" mismatch describes actual length. - Describe None as "None" instead of "". - Don't wrap angle brackets around a description that already has them. - Improved readability of several matchers. == Version 1.2.1 == 04 Jan 2011 * Fixed "assert_that" to describe the diagnosis of the mismatch, not just the mismatched value. PyHamcrest will now give even more useful information. * Expanded BaseDescription.append_description_of to handle all types of values, not just self-describing values. * Deprecated: - Description.append_value no longer needed; call append_description_of instead. - BaseDescription.append_value_list no longer needed; call append_list instead. - SelfDescribingValue no longer needed. 1.2.1 fixes to 1.2: - Corrected manifest so install works. Thanks to: Jeong-Min Lee == Version 1.1 == 28 Dec 2010 * New matchers: - "contains" matches sequence containing matching items in order. - "contains_inanyorder" matches sequence containing matching items in any order. * Added Sphinx documentation support. == Version 1.0 == 04 Dec 2010 * First official release * Text matchers now support Unicode strings 15 Jan 2008 * Initial submission PyHamcrest-1.8.0/examples/0000755000076500000240000000000012230156532015725 5ustar offby1staff00000000000000PyHamcrest-1.8.0/examples/CustomDateMatcher.py0000644000076500000240000000312211760072653021661 0ustar offby1staff00000000000000import sys sys.path.append('..') from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest import * import unittest import datetime class IsGivenDayOfWeek(BaseMatcher): """Matches dates that fall on a given day of the week.""" def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): """Test whether item matches.""" if not hasmethod(item, 'weekday'): return False return item.weekday() == self.day def describe_to(self, description): """Describe the matcher.""" day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] description.append_text('calendar date falling on ') \ .append_text(day_as_string[self.day]) def on_a_saturday(): """Factory function to generate Saturday matcher.""" return IsGivenDayOfWeek(5) class SampleTest(unittest.TestCase): def testDateIsOnASaturday(self): """Example of successful match.""" d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) def testFailsWithMismatchedDate(self): """Example of what happens with date that doesn't match.""" d = datetime.date(2008, 04, 06) assert_that(d, is_(on_a_saturday())) def testFailsWithNonDate(self): """Example of what happens with object that isn't a date.""" d = 'oops' assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() PyHamcrest-1.8.0/examples/ExampleWithAssertThat.py0000644000076500000240000000105011760072653022535 0ustar offby1staff00000000000000import sys sys.path.append('..') from hamcrest import * import unittest class ExampleWithAssertThat(unittest.TestCase): def testUsingAssertThat(self): assert_that('xx', is_('xx')) assert_that('yy', is_not('xx')) assert_that('i like cheese', contains_string('cheese')) def testCanAlsoSupplyDescriptiveReason(self): assert_that('xx', is_('xx'), 'description') def testCanAlsoAssertPlainBooleans(self): assert_that(True, 'This had better not fail') if __name__ == '__main__': unittest.main() PyHamcrest-1.8.0/LICENSE.txt0000644000076500000240000000267411760072653015753 0ustar offby1staff00000000000000BSD License Copyright 2011 hamcrest.org All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Hamcrest nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PyHamcrest-1.8.0/MANIFEST.in0000644000076500000240000000013211760072653015651 0ustar offby1staff00000000000000include CHANGES.txt include LICENSE.txt include README.md recursive-include examples *.py PyHamcrest-1.8.0/PKG-INFO0000644000076500000240000003172512230156532015214 0ustar offby1staff00000000000000Metadata-Version: 1.1 Name: PyHamcrest Version: 1.8.0 Summary: Hamcrest framework for matcher objects Home-page: https://github.com/hamcrest/PyHamcrest Author: Chris Rose Author-email: offline@offby1.net License: New BSD Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.8.0.tar.gz Description: PyHamcrest ========== .. image:: https://pypip.in/v/PyHamcrest/badge.png :alt: Release Status :target: https://crate.io/packages/PyHamcrest .. image:: https://pypip.in/d/PyHamcrest/badge.png :alt: Downloads :target: https://crate.io/packages/PyHamcrest .. image:: https://travis-ci.org/hamcrest/PyHamcrest.png?branch=master :alt: Build Status :target: https://travis-ci.org/hamcrest/PyHamcrest Introduction ============ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. Installation ============ Hamcrest can be installed using the usual Python packaging tools. It depends on distribute, but as long as you have a network connection when you install, the installation process will take care of that for you. My first PyHamcrest test ======================== We'll start by writing a very simple PyUnit test, but instead of using PyUnit's ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and the standard set of matchers: .. code:: python from hamcrest import * import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit('Ginger') myBiscuit = Biscuit('Ginger') assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == '__main__': unittest.main() The ``assert_that`` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier for the tested value in the assertion: .. code:: python assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips') assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts') As a convenience, assert_that can also be used to verify a boolean condition: .. code:: python assert_that(theBiscuit.isCooked(), 'cooked') This is equivalent to the ``assert_`` method of unittest.TestCase, but because it's a standalone function, it offers greater flexibility in test writing. Predefined matchers =================== PyHamcrest comes with a library of useful matchers: * Object * ``equal_to`` - match equal object * ``has_length`` - match ``len()`` * ``has_property`` - match value of property with given name * ``has_properties`` - match an object that has all of the given properties. * ``has_string`` - match ``str()`` * ``instance_of`` - match object type * ``none``, ``not_none`` - match ``None``, or not ``None`` * ``same_instance`` - match same object * Number * ``close_to`` - match number close to a given value * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``, ``less_than_or_equal_to`` - match numeric ordering * Text * ``contains_string`` - match part of a string * ``ends_with`` - match the end of a string * ``equal_to_ignoring_case`` - match the complete string but ignore case * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace * ``matches_regexp`` - match a regular expression in a string * ``starts_with`` - match the beginning of a string * ``string_contains_in_order`` - match parts of a string, in relative order * Logical * ``all_of`` - ``and`` together all matchers * ``any_of`` - ``or`` together all matchers * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value * ``is_not`` - negate the matcher * Sequence * ``contains`` - exactly match the entire sequence * ``contains_inanyorder`` - match the entire sequence, but in any order * ``has_item`` - match if given item appears in the sequence * ``has_items`` - match if all given items appear in the sequence, in any order * ``is_in`` - match if item appears in the given sequence * ``only_contains`` - match if sequence's items appear in given list * Dictionary * ``has_entries`` - match dictionary with list of key-value pairs * ``has_entry`` - match dictionary containing a key-value pair * ``has_key`` - match dictionary with a key * ``has_value`` - match dictionary with a value * Decorator * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour * ``raises`` - Ensure that a deferred callable raises as expected * ``described_as`` - give the matcher a custom failure description * ``is_`` - decorator to improve readability - see `Syntactic sugar` below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. Syntactic sugar =============== PyHamcrest strives to make your tests as readable as possible. For example, the ``is_`` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent: .. code:: python assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with ``equal_to``. But if the argument is a type, it is wrapped with ``instance_of``, so the following are also equivalent: .. code:: python assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is ``same_instance``.* Writing custom matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write: .. code:: python def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation: .. code:: python from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod class IsGivenDayOfWeek(BaseMatcher): def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): if not hasmethod(item, 'weekday'): return False return item.weekday() == self.day def describe_to(self, description): day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] description.append_text('calendar date falling on ') \ .append_text(day_as_string[self.day]) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the ``_matches`` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the ``describe_to`` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks: .. code:: python assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``: .. code:: python from hamcrest import * import unittest from isgivendayofweek import on_a_saturday class DateTest(unittest.TestCase): def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. More resources ============== * Documentation_ * Package_ * Sources_ * Hamcrest_ .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.7.1/ .. _Package: http://pypi.python.org/pypi/PyHamcrest .. _Sources: https://github.com/hamcrest/PyHamcrest .. _Hamcrest: http://hamcrest.org Keywords: hamcrest matchers pyunit unit test testing unittest unittesting Platform: All Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Testing Provides: hamcrest PyHamcrest-1.8.0/README.rst0000644000076500000240000002333412213122554015601 0ustar offby1staff00000000000000PyHamcrest ========== .. image:: https://pypip.in/v/PyHamcrest/badge.png :alt: Release Status :target: https://crate.io/packages/PyHamcrest .. image:: https://pypip.in/d/PyHamcrest/badge.png :alt: Downloads :target: https://crate.io/packages/PyHamcrest .. image:: https://travis-ci.org/hamcrest/PyHamcrest.png?branch=master :alt: Build Status :target: https://travis-ci.org/hamcrest/PyHamcrest Introduction ============ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. Installation ============ Hamcrest can be installed using the usual Python packaging tools. It depends on distribute, but as long as you have a network connection when you install, the installation process will take care of that for you. My first PyHamcrest test ======================== We'll start by writing a very simple PyUnit test, but instead of using PyUnit's ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and the standard set of matchers: .. code:: python from hamcrest import * import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit('Ginger') myBiscuit = Biscuit('Ginger') assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == '__main__': unittest.main() The ``assert_that`` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier for the tested value in the assertion: .. code:: python assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips') assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts') As a convenience, assert_that can also be used to verify a boolean condition: .. code:: python assert_that(theBiscuit.isCooked(), 'cooked') This is equivalent to the ``assert_`` method of unittest.TestCase, but because it's a standalone function, it offers greater flexibility in test writing. Predefined matchers =================== PyHamcrest comes with a library of useful matchers: * Object * ``equal_to`` - match equal object * ``has_length`` - match ``len()`` * ``has_property`` - match value of property with given name * ``has_properties`` - match an object that has all of the given properties. * ``has_string`` - match ``str()`` * ``instance_of`` - match object type * ``none``, ``not_none`` - match ``None``, or not ``None`` * ``same_instance`` - match same object * Number * ``close_to`` - match number close to a given value * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``, ``less_than_or_equal_to`` - match numeric ordering * Text * ``contains_string`` - match part of a string * ``ends_with`` - match the end of a string * ``equal_to_ignoring_case`` - match the complete string but ignore case * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace * ``matches_regexp`` - match a regular expression in a string * ``starts_with`` - match the beginning of a string * ``string_contains_in_order`` - match parts of a string, in relative order * Logical * ``all_of`` - ``and`` together all matchers * ``any_of`` - ``or`` together all matchers * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value * ``is_not`` - negate the matcher * Sequence * ``contains`` - exactly match the entire sequence * ``contains_inanyorder`` - match the entire sequence, but in any order * ``has_item`` - match if given item appears in the sequence * ``has_items`` - match if all given items appear in the sequence, in any order * ``is_in`` - match if item appears in the given sequence * ``only_contains`` - match if sequence's items appear in given list * Dictionary * ``has_entries`` - match dictionary with list of key-value pairs * ``has_entry`` - match dictionary containing a key-value pair * ``has_key`` - match dictionary with a key * ``has_value`` - match dictionary with a value * Decorator * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour * ``raises`` - Ensure that a deferred callable raises as expected * ``described_as`` - give the matcher a custom failure description * ``is_`` - decorator to improve readability - see `Syntactic sugar` below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. Syntactic sugar =============== PyHamcrest strives to make your tests as readable as possible. For example, the ``is_`` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent: .. code:: python assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with ``equal_to``. But if the argument is a type, it is wrapped with ``instance_of``, so the following are also equivalent: .. code:: python assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is ``same_instance``.* Writing custom matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write: .. code:: python def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation: .. code:: python from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod class IsGivenDayOfWeek(BaseMatcher): def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): if not hasmethod(item, 'weekday'): return False return item.weekday() == self.day def describe_to(self, description): day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] description.append_text('calendar date falling on ') \ .append_text(day_as_string[self.day]) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the ``_matches`` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the ``describe_to`` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks: .. code:: python assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``: .. code:: python from hamcrest import * import unittest from isgivendayofweek import on_a_saturday class DateTest(unittest.TestCase): def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. More resources ============== * Documentation_ * Package_ * Sources_ * Hamcrest_ .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.7.1/ .. _Package: http://pypi.python.org/pypi/PyHamcrest .. _Sources: https://github.com/hamcrest/PyHamcrest .. _Hamcrest: http://hamcrest.org PyHamcrest-1.8.0/setup.cfg0000644000076500000240000000007312230156532015730 0ustar offby1staff00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 PyHamcrest-1.8.0/setup.py0000755000076500000240000000425512230156003015623 0ustar offby1staff00000000000000import sys import os import re try: from setuptools import setup, find_packages except ImportError: from distribute_setup import use_setuptools use_setuptools() from setuptools import setup, find_packages def local(fname): return os.path.join(os.path.dirname(__file__), fname) def read(fname): return open(local(fname)).read() # On Python 3, we can't "from hamcrest import __version__" (get ImportError), # so we extract the variable assignment and execute it ourselves. fh = open(local('src/hamcrest/__init__.py')) try: for line in fh: if re.match('__version__.*', line): exec(line) finally: if fh: fh.close() extra_attributes = {} if sys.version_info >= (3,): extra_attributes['use_2to3'] = True params = dict( name='PyHamcrest', version=__version__, #flake8:noqa author='Chris Rose', author_email='offline@offby1.net', description='Hamcrest framework for matcher objects', license='New BSD', platforms=['All'], keywords='hamcrest matchers pyunit unit test testing unittest unittesting', url='https://github.com/hamcrest/PyHamcrest', download_url='http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-%s.tar.gz' % __version__, packages=find_packages('src'), package_dir = {'': 'src'}, provides=['hamcrest'], long_description=read('README.rst'), install_requires=['setuptools'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Topic :: Software Development', 'Topic :: Software Development :: Quality Assurance', 'Topic :: Software Development :: Testing', ], **extra_attributes ) all_params = dict(params.items(), **extra_attributes) setup(**all_params) PyHamcrest-1.8.0/src/0000755000076500000240000000000012230156532014676 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/0000755000076500000240000000000012230156532016504 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/__init__.py0000644000076500000240000000025512230156343020617 0ustar offby1staff00000000000000from core import * from library import * __version__ = "1.8.0" __author__ = "Chris Rose" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/core/0000755000076500000240000000000012230156532017434 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/core/__init__.py0000644000076500000240000000024311760072653021554 0ustar offby1staff00000000000000from assert_that import assert_that from core import * __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/core/assert_that.py0000644000076500000240000000447612213122554022340 0ustar offby1staff00000000000000from matcher import Matcher from string_description import StringDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" # unittest integration; hide these frames from tracebacks __unittest = True # py.test integration; hide these frames from tracebacks __tracebackhide__ = True def assert_that(arg1, arg2=None, arg3=''): """Asserts that actual value satisfies matcher. (Can also assert plain boolean condition.) :param actual: The object to evaluate as the actual value. :param matcher: The matcher to satisfy as the expected condition. :param reason: Optional explanation to include in failure description. ``assert_that`` passes the actual value to the matcher for evaluation. If the matcher is not satisfied, an exception is thrown describing the mismatch. ``assert_that`` is designed to integrate well with PyUnit and other unit testing frameworks. The exception raised for an unmet assertion is an :py:exc:`AssertionError`, which PyUnit reports as a test failure. With a different set of parameters, ``assert_that`` can also verify a boolean condition: .. function:: assert_that(assertion[, reason]) :param assertion: Boolean condition to verify. :param reason: Optional explanation to include in failure description. This is equivalent to the :py:meth:`~unittest.TestCase.assertTrue` method of :py:class:`unittest.TestCase`, but offers greater flexibility in test writing by being a standalone function. """ if isinstance(arg2, Matcher): _assert_match(actual=arg1, matcher=arg2, reason=arg3) else: _assert_bool(assertion=arg1, reason=arg2) def _assert_match(actual, matcher, reason): if not matcher.matches(actual): description = StringDescription() description.append_text(reason) \ .append_text('\nExpected: ') \ .append_description_of(matcher) \ .append_text('\n but: ') matcher.describe_mismatch(actual, description) description.append_text('\n') raise AssertionError(str(description)) def _assert_bool(assertion, reason=None): if not assertion: if not reason: reason = 'Assertion failed' raise AssertionError(reason) PyHamcrest-1.8.0/src/hamcrest/core/base_description.py0000644000076500000240000000505612121131200023311 0ustar offby1staff00000000000000from description import Description from selfdescribingvalue import SelfDescribingValue from helpers.hasmethod import hasmethod import warnings __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class BaseDescription(Description): """Base class for all :py:class:`~hamcrest.core.description.Description` implementations. """ def append_text(self, text): self.append(text) return self def append_description_of(self, value): if hasmethod(value, 'describe_to'): value.describe_to(self) elif isinstance(value, str): self.append_string_in_python_syntax(value) elif isinstance(value, unicode): self.append(repr(value)) else: description = str(value) if description[:1] == '<' and description[-1:] == '>': self.append(description) else: self.append('<') self.append(description) self.append('>') return self def append_value(self, value): warnings.warn('Call append_description_of instead of append_value', DeprecationWarning) if isinstance(value, str): self.append_string_in_python_syntax(value) else: self.append('<') self.append(str(value)) self.append('>') return self def append_value_list(self, start, separator, end, list): warnings.warn('Call append_list instead of append_value_list', DeprecationWarning) return self.append_list(start, separator, end, map(SelfDescribingValue, list)) def append_list(self, start, separator, end, list): separate = False self.append(start) for item in list: if separate: self.append(separator) self.append_description_of(item) separate = True self.append(end) return self def append(self, string): """Append the string to the description.""" raise NotImplementedError('append') def append_string_in_python_syntax(self, string): self.append("'") for ch in string: self.append(character_in_python_syntax(ch)) self.append("'") def character_in_python_syntax(ch): if ch == "'": return "\'" elif ch == '\n': return '\\n' elif ch == '\r': return '\\r' elif ch == '\t': return '\\t' else: return ch PyHamcrest-1.8.0/src/hamcrest/core/base_matcher.py0000644000076500000240000000214611760072653022436 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from matcher import Matcher from string_description import tostring class BaseMatcher(Matcher): """Base class for all :py:class:`~hamcrest.core.matcher.Matcher` implementations. Most implementations can just implement :py:obj:`_matches`, leaving the handling of any mismatch description to the ``matches`` method. But if it makes more sense to generate the mismatch description during the matching, override :py:meth:`~hamcrest.core.matcher.Matcher.matches` instead. """ def __str__(self): return tostring(self) def _matches(self, item): raise NotImplementedError('_matches') def matches(self, item, mismatch_description=None): match_result = self._matches(item) if not match_result and mismatch_description: self.describe_mismatch(item, mismatch_description) return match_result def describe_mismatch(self, item, mismatch_description): mismatch_description.append_text('was ').append_description_of(item) PyHamcrest-1.8.0/src/hamcrest/core/compat.py0000644000076500000240000000120212213122554021262 0ustar offby1staff00000000000000__author__ = "Per Fagrell" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" __all__ = ['is_callable'] import sys # callable was not part of py3k until 3.2, so we create this # generic is_callable to use callable if possible, otherwise # we use generic homebrew. if sys.version_info[0] == 3 and sys.version_info[1] < 2: def is_callable(function): """Return whether the object is callable (i.e., some kind of function).""" if function is None: return False return any("__call__" in klass.__dict__ for klass in type(function).__mro__) else: is_callable = callable PyHamcrest-1.8.0/src/hamcrest/core/core/0000755000076500000240000000000012230156532020364 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/core/core/__init__.py0000644000076500000240000000100412213122554022466 0ustar offby1staff00000000000000"""Fundamental matchers of objects and values, and composite matchers.""" from allof import all_of from anyof import any_of from described_as import described_as from is_ import is_ from isanything import anything from isequal import equal_to from isinstanceof import instance_of from isnone import none, not_none from isnot import is_not from issame import same_instance from raises import calling, raises __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/core/core/allof.py0000644000076500000240000000271711760072653022052 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AllOf(BaseMatcher): def __init__(self, *matchers): self.matchers = matchers def matches(self, item, mismatch_description=None): for matcher in self.matchers: if not matcher.matches(item): if mismatch_description: mismatch_description.append_description_of(matcher) \ .append_text(' ') matcher.describe_mismatch(item, mismatch_description) return False return True def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_to(self, description): description.append_list('(', ' and ', ')', self.matchers) def all_of(*items): """Matches if all of the given matchers evaluate to ``True``. :param matcher1,...: A comma-separated list of matchers. The matchers are evaluated from left to right using short-circuit evaluation, so evaluation stops as soon as a matcher returns ``False``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return AllOf(*[wrap_matcher(item) for item in items]) PyHamcrest-1.8.0/src/hamcrest/core/core/anyof.py0000644000076500000240000000211111760072653022055 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AnyOf(BaseMatcher): def __init__(self, *matchers): self.matchers = matchers def _matches(self, item): for matcher in self.matchers: if matcher.matches(item): return True return False def describe_to(self, description): description.append_list('(', ' or ', ')', self.matchers) def any_of(*items): """Matches if any of the given matchers evaluate to ``True``. :param matcher1,...: A comma-separated list of matchers. The matchers are evaluated from left to right using short-circuit evaluation, so evaluation stops as soon as a matcher returns ``True``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return AnyOf(*[wrap_matcher(item) for item in items]) PyHamcrest-1.8.0/src/hamcrest/core/core/described_as.py0000644000076500000240000000312712101144121023334 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher import re __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ARG_PATTERN = re.compile('%([0-9]+)') class DescribedAs(BaseMatcher): def __init__(self, description_template, matcher, *values): self.template = description_template self.matcher = matcher self.values = values def matches(self, item, mismatch_description=None): return self.matcher.matches(item, mismatch_description) def describe_mismatch(self, item, mismatch_description): self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description): text_start = 0 for match in re.finditer(ARG_PATTERN, self.template): description.append_text(self.template[text_start:match.start()]) arg_index = int(match.group()[1:]) description.append_description_of(self.values[arg_index]) text_start = match.end() if text_start < len(self.template): description.append_text(self.template[text_start:]) def described_as(description, matcher, *values): """Adds custom failure description to a given matcher. :param description: Overrides the matcher's description. :param matcher: The matcher to satisfy. :param value1,...: Optional comma-separated list of substitution values. The description may contain substitution placeholders %0, %1, etc. These will be replaced by any values that follow the matcher. """ return DescribedAs(description, matcher, *values) PyHamcrest-1.8.0/src/hamcrest/core/core/is_.py0000644000076500000240000000471312101144121021501 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type from isinstanceof import instance_of class Is(BaseMatcher): def __init__(self, matcher): self.matcher = matcher def matches(self, item, mismatch_description=None): return self.matcher.matches(item, mismatch_description) def describe_mismatch(self, item, mismatch_description): return self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description): description.append_description_of(self.matcher) def wrap_value_or_type(x): if is_matchable_type(x): return instance_of(x) else: return wrap_matcher(x) def is_(x): """Decorates another matcher, or provides shortcuts to the frequently used ``is(equal_to(x))`` and ``is(instance_of(x))``. :param x: The matcher to satisfy, or a type for :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matching, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher compares the evaluated object to the given matcher. .. note:: PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is :py:func:`~hamcrest.core.core.issame.same_instance`. If the ``x`` argument is a matcher, its behavior is retained, but the test may be more expressive. For example:: assert_that(value, less_than(5)) assert_that(value, is_(less_than(5))) If the ``x`` argument is a type, it is wrapped in an :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matcher. This makes the following statements equivalent:: assert_that(cheese, instance_of(Cheddar)) assert_that(cheese, is_(instance_of(Cheddar))) assert_that(cheese, is_(Cheddar)) Otherwise, if the ``x`` argument is not a matcher, it is wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. This makes the following statements equivalent:: assert_that(cheese, equal_to(smelly)) assert_that(cheese, is_(equal_to(smelly))) assert_that(cheese, is_(smelly)) Choose the style that makes your expression most readable. This will vary depending on context. """ return Is(wrap_value_or_type(x)) PyHamcrest-1.8.0/src/hamcrest/core/core/isanything.py0000644000076500000240000000143611760072653023127 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsAnything(BaseMatcher): def __init__(self, description): self.description = description if not description: self.description = 'ANYTHING' def _matches(self, item): return True def describe_to(self, description): description.append_text(self.description) def anything(description=None): """Matches anything. :param description: Optional string used to describe this matcher. This matcher always evaluates to ``True``. Specify this in composite matchers when the value of a particular element is unimportant. """ return IsAnything(description) PyHamcrest-1.8.0/src/hamcrest/core/core/isequal.py0000644000076500000240000000157511760072653022421 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.matcher import Matcher class IsEqual(BaseMatcher): def __init__(self, equals): self.object = equals def _matches(self, item): return item == self.object def describe_to(self, description): nested_matcher = isinstance(self.object, Matcher) if nested_matcher: description.append_text('<') description.append_description_of(self.object) if nested_matcher: description.append_text('>') def equal_to(obj): """Matches if object is equal to a given object. :param obj: The object to compare against as the expected value. This matcher compares the evaluated object to ``obj`` for equality.""" return IsEqual(obj) PyHamcrest-1.8.0/src/hamcrest/core/core/isinstanceof.py0000644000076500000240000000212612121131200023404 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import is_matchable_type __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" import types class IsInstanceOf(BaseMatcher): def __init__(self, expected_type): if not is_matchable_type(expected_type): raise TypeError('IsInstanceOf requires type') self.expected_type = expected_type def _matches(self, item): return isinstance(item, self.expected_type) def describe_to(self, description): description.append_text('an instance of ') \ .append_text(self.expected_type.__name__) def instance_of(atype): """Matches if object is an instance of, or inherits from, a given type. :param atype: The type to compare against as the expected type. This matcher checks whether the evaluated object is an instance of ``atype`` or an instance of any class that inherits from ``atype``. Example:: instance_of(str) """ return IsInstanceOf(atype) PyHamcrest-1.8.0/src/hamcrest/core/core/isnone.py0000644000076500000240000000100511760072653022235 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from isnot import is_not class IsNone(BaseMatcher): def _matches(self, item): return item is None def describe_to(self, description): description.append_text('None') def none(): """Matches if object is ``None``.""" return IsNone() def not_none(): """Matches if object is not ``None``.""" return is_not(none()) PyHamcrest-1.8.0/src/hamcrest/core/core/isnot.py0000644000076500000240000000242712101144121022063 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher, Matcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type from isequal import equal_to from isinstanceof import instance_of class IsNot(BaseMatcher): def __init__(self, matcher): self.matcher = matcher def _matches(self, item): return not self.matcher.matches(item) def describe_to(self, description): description.append_text('not ').append_description_of(self.matcher) def wrap_value_or_type(x): if is_matchable_type(x): return instance_of(x) else: return wrap_matcher(x) def is_not(match): """Inverts the given matcher to its logical negation. :param match: The matcher to negate. This matcher compares the evaluated object to the negation of the given matcher. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality, and thus matches for inequality. Examples:: assert_that(cheese, is_not(equal_to(smelly))) assert_that(cheese, is_not(smelly)) """ return IsNot(wrap_value_or_type(match)) PyHamcrest-1.8.0/src/hamcrest/core/core/issame.py0000644000076500000240000000235511760072653022234 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher class IsSame(BaseMatcher): def __init__(self, object): self.object = object def _matches(self, item): return item is self.object def describe_to(self, description): description.append_text('same instance as ') \ .append_text(hex(id(self.object))) \ .append_text(' ') \ .append_description_of(self.object) def describe_mismatch(self, item, mismatch_description): mismatch_description.append_text('was ') if item is not None: mismatch_description.append_text(hex(id(item))) \ .append_text(' ') mismatch_description.append_description_of(item) def same_instance(obj): """Matches if evaluated object is the same instance as a given object. :param obj: The object to compare against as the expected value. This matcher invokes the ``is`` identity operator to determine if the evaluated object is the the same object as ``obj``. """ return IsSame(obj) PyHamcrest-1.8.0/src/hamcrest/core/core/raises.py0000644000076500000240000000711712213122554022230 0ustar offby1staff00000000000000from weakref import ref import re import sys from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher from hamcrest.core.compat import is_callable __author__ = "Per Fagrell" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" class Raises(BaseMatcher): def __init__(self, expected, pattern=None): self.pattern = pattern self.expected = expected self.actual = None self.function = None def _matches(self, function): if not is_callable(function): return False self.function = ref(function) return self._call_function(function) def _call_function(self, function): self.actual = None try: function() except Exception: self.actual = sys.exc_info()[1] if isinstance(self.actual, self.expected): if self.pattern is not None: return re.search(self.pattern, str(self.actual)) is not None return True return False def describe_to(self, description): description.append_text('Expected a callable raising %s' % self.expected) def describe_mismatch(self, item, description): if not is_callable(item): description.append_text('%s is not callable' % item) return function = None if self.function is None else self.function() if function is None or function is not item: self.function = ref(item) if not self._call_function(item): return if self.actual is None: description.append_text('No exception raised.') elif isinstance(self.actual, self.expected) and self.pattern is not None: description.append_text('Correct assertion type raised, but the expected pattern ("%s") not found.' % self.pattern) description.append_text('\n message was: "%s"' % str(self.actual)) else: description.append_text('%s was raised instead' % type(self.actual)) def raises(exception, pattern=None): """Matches if the called function raised the expected exception. :param exception: The class of the expected exception :param pattern: Optional regular expression to match exception message. Expects the actual to be wrapped by using :py:func:`~hamcrest.core.core.raises.calling`, or a callable taking no arguments. Optional argument pattern should be a string containing a regular expression. If provided, the string representation of the actual exception - e.g. `str(actual)` - must match pattern. Examples:: assert_that(calling(int).with_args('q'), raises(TypeError)) assert_that(calling(parse, broken_input), raises(ValueError)) """ return Raises(exception, pattern) class DeferredCallable(object): def __init__(self, func): self.func = func self.args = tuple() self.kwargs = {} def __call__(self): self.func(*self.args, **self.kwargs) def with_args(self, *args, **kwargs): self.args = args self.kwargs = kwargs return self def calling(func): """Wrapper for function call that delays the actual execution so that :py:func:`~hamcrest.core.core.raises.raises` matcher can catch any thrown exception. :param func: The function or method to be called The arguments can be provided with a call to the `with_args` function on the returned object:: calling(my_method).with_args(arguments, and_='keywords') """ return DeferredCallable(func) PyHamcrest-1.8.0/src/hamcrest/core/description.py0000644000076500000240000000330111760072653022336 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class Description(object): """A description of a :py:class:`~hamcrest.core.matcher.Matcher`. A :py:class:`~hamcrest.core.matcher.Matcher` will describe itself to a description which can later be used for reporting. """ def append_text(self, text): """Appends some plain text to the description. :returns: ``self``, for chaining """ raise NotImplementedError('append_text') def append_description_of(self, value): """Appends description of given value to this description. If the value implements :py:meth:`~hamcrest.core.selfdescribing.SelfDescribing.describe_to`, then it will be used. :returns: ``self``, for chaining """ raise NotImplementedError('append_description_of') def append_value(self, value): """Appends an arbitary value to the description. **Deprecated:** Call :py:meth:`~hamcrest.core.description.Description.append_description_of` instead. :returns: ``self``, for chaining """ raise NotImplementedError('append_value') def append_list(self, start, separator, end, list): """Appends a list of objects to the description. :param start: String that will begin the list description. :param separator: String that will separate each object in the description. :param end: String that will end the list description. :param list: List of objects to be described. :returns: ``self``, for chaining """ raise NotImplementedError('append_list') PyHamcrest-1.8.0/src/hamcrest/core/helpers/0000755000076500000240000000000012230156532021076 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/core/helpers/__init__.py0000644000076500000240000000022211760072653023213 0ustar offby1staff00000000000000"""Utilities for writing Matchers.""" __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/core/helpers/hasmethod.py0000644000076500000240000000050511760072653023434 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def hasmethod(obj, methodname): """Does ``obj`` have a method named ``methodname``?""" if not hasattr(obj, methodname): return False method = getattr(obj, methodname) return callable(method) PyHamcrest-1.8.0/src/hamcrest/core/helpers/wrap_matcher.py0000644000076500000240000000131712101144121024112 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import Matcher from hamcrest.core.core.isequal import equal_to __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" import types def wrap_matcher(x): """Wraps argument in a matcher, if necessary. :returns: the argument as-is if it is already a matcher, otherwise wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. """ if isinstance(x, Matcher): return x else: return equal_to(x) def is_matchable_type(expected_type): if isinstance(expected_type, type): return True if type(expected_type) == types.ClassType: return True return False PyHamcrest-1.8.0/src/hamcrest/core/matcher.py0000644000076500000240000000342311760072653021443 0ustar offby1staff00000000000000from selfdescribing import SelfDescribing __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class Matcher(SelfDescribing): """A matcher over acceptable values. A matcher is able to describe itself to give feedback when it fails. Matcher implementations should *not* directly implement this protocol. Instead, *extend* the :py:class:`~hamcrest.core.base_matcher.BaseMatcher` class, which will ensure that the :py:class:`~hamcrest.core.matcher.Matcher` API can grow to support new features and remain compatible with all :py:class:`~hamcrest.core.matcher.Matcher` implementations. """ def matches(self, item, mismatch_description=None): """Evaluates the matcher for argument item. If a mismatch is detected and argument ``mismatch_description`` is provided, it will generate a description of why the matcher has not accepted the item. :param item: The object against which the matcher is evaluated. :returns: ``True`` if ``item`` matches, otherwise ``False``. """ raise NotImplementedError('matches') def describe_mismatch(self, item, mismatch_description): """Generates a description of why the matcher has not accepted the item. The description will be part of a larger description of why a matching failed, so it should be concise. This method assumes that ``matches(item)`` is ``False``, but will not check this. :param item: The item that the :py:class:`~hamcrest.core.matcher.Matcher` has rejected. :param mismatch_description: The description to be built or appended to. """ raise NotImplementedError('describe_mismatch') PyHamcrest-1.8.0/src/hamcrest/core/selfdescribing.py0000644000076500000240000000107611760072653023005 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class SelfDescribing(object): """The ability of an object to describe itself.""" def describe_to(self, description): """Generates a description of the object. The description may be part of a description of a larger object of which this is just a component, so it should be worded appropriately. :param description: The description to be built or appended to. """ raise NotImplementedError('describe_to') PyHamcrest-1.8.0/src/hamcrest/core/selfdescribingvalue.py0000644000076500000240000000150211760072653024034 0ustar offby1staff00000000000000from hamcrest.core.selfdescribing import SelfDescribing import warnings __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class SelfDescribingValue(SelfDescribing): """Wrap any value in a ``SelfDescribingValue`` to satisfy the :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` interface. **Deprecated:** No need for this class now that :py:meth:`~hamcrest.core.description.Description.append_description_of` handles any type of value. """ def __init__(self, value): warnings.warn('SelfDescribingValue no longer needed', DeprecationWarning) self.value = value def describe_to(self, description): """Generates a description of the value.""" description.append_value(self.value) PyHamcrest-1.8.0/src/hamcrest/core/string_description.py0000644000076500000240000000147211760072653023733 0ustar offby1staff00000000000000from base_description import BaseDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def tostring(selfdescribing): """Returns the description of a :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a string. :param selfdescribing: The object to be described. :returns: The description of the object. """ return str(StringDescription().append_description_of(selfdescribing)) class StringDescription(BaseDescription): """A :py:class:`~hamcrest.core.description.Description` that is stored as a string. """ def __init__(self): self.out = '' def __str__(self): """Returns the description.""" return self.out def append(self, string): self.out += string PyHamcrest-1.8.0/src/hamcrest/library/0000755000076500000240000000000012230156532020150 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/library/__init__.py0000644000076500000240000000157212230143325022262 0ustar offby1staff00000000000000"""Library of Matcher implementations.""" from hamcrest.core import * from collection import * from integration import * from number import * from object import * from text import * __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" __all__ = [ 'has_entry', 'has_entries', 'has_key', 'has_value', 'is_in', 'empty', 'has_item', 'has_items', 'contains_inanyorder', 'contains', 'only_contains', 'match_equality', 'matches_regexp', 'close_to', 'greater_than', 'greater_than_or_equal_to', 'less_than', 'less_than_or_equal_to', 'has_length', 'has_property', 'has_properties', 'has_string', 'equal_to_ignoring_case', 'equal_to_ignoring_whitespace', 'contains_string', 'ends_with', 'starts_with', 'string_contains_in_order', ] PyHamcrest-1.8.0/src/hamcrest/library/collection/0000755000076500000240000000000012230156532022303 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/library/collection/__init__.py0000644000076500000240000000117312230143274024415 0ustar offby1staff00000000000000"""Matchers of collections.""" from __future__ import absolute_import from .isdict_containing import has_entry from .isdict_containingentries import has_entries from .isdict_containingkey import has_key from .isdict_containingvalue import has_value from .isin import is_in from .issequence_containing import has_item, has_items from .issequence_containinginanyorder import contains_inanyorder from .issequence_containinginorder import contains from .issequence_onlycontaining import only_contains from .is_empty import empty __author__ = "Chris Rose" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/library/collection/is_empty.py0000644000076500000240000000162112213003323024474 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Chris Rose" __copyright__ = "Copyright 2012 hamcrest.org" __license__ = "BSD, see License.txt" class IsEmpty(BaseMatcher): def matches(self, item, mismatch_description=None): try: if len(item) == 0: return True if mismatch_description: mismatch_description \ .append_text('has %d item(s)' % len(item)) except TypeError: if mismatch_description: mismatch_description \ .append_text('does not support length') return False def describe_to(self, description): description.append_text('an empty collection') def empty(): """ This matcher matches any collection-like object that responds to the __len__ method, and has a length of 0. """ return IsEmpty() PyHamcrest-1.8.0/src/hamcrest/library/collection/isdict_containing.py0000644000076500000240000000401011760072653026350 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContaining(BaseMatcher): def __init__(self, key_matcher, value_matcher): self.key_matcher = key_matcher self.value_matcher = value_matcher def _matches(self, dictionary): if hasmethod(dictionary, 'items'): for key, value in dictionary.items(): if self.key_matcher.matches(key) and self.value_matcher.matches(value): return True return False def describe_to(self, description): description.append_text('a dictionary containing [') \ .append_description_of(self.key_matcher) \ .append_text(': ') \ .append_description_of(self.value_matcher) \ .append_text(']') def has_entry(key_match, value_match): """Matches if dictionary contains key-value entry satisfying a given pair of matchers. :param key_match: The matcher to satisfy for the key, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. :param value_match: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry that satisfies ``key_match`` and ``value_match``. If a matching entry is found, ``has_entry`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_entry(equal_to('foo'), equal_to(1)) has_entry('foo', 1) """ return IsDictContaining(wrap_matcher(key_match), wrap_matcher(value_match)) PyHamcrest-1.8.0/src/hamcrest/library/collection/isdict_containingentries.py0000644000076500000240000001210611760072653027747 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingEntries(BaseMatcher): def __init__(self, value_matchers): self.value_matchers = value_matchers def _not_a_dictionary(self, dictionary, mismatch_description): if mismatch_description: mismatch_description.append_description_of(dictionary) \ .append_text(' is not a mapping object') return False def matches(self, dictionary, mismatch_description=None): for key in self.value_matchers: try: if not key in dictionary: if mismatch_description: mismatch_description.append_text('no ') \ .append_description_of(key) \ .append_text(' key in ') \ .append_description_of(dictionary) return False except TypeError: return self._not_a_dictionary(dictionary, mismatch_description) value_matcher = self.value_matchers[key] try: actual_value = dictionary[key] except TypeError: return self._not_a_dictionary(dictionary, mismatch_description) if not value_matcher.matches(actual_value): if mismatch_description: mismatch_description.append_text('value for ') \ .append_description_of(key) \ .append_text(' ') value_matcher.describe_mismatch(actual_value, mismatch_description) return False return True def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_keyvalue(self, index, description): """Describes key-value pair at given index.""" description.append_description_of(index) \ .append_text(': ') \ .append_description_of(self.value_matchers[index]) def describe_to(self, description): description.append_text('a dictionary containing {') first = True for key in self.value_matchers: if not first: description.append_text(', ') self.describe_keyvalue(key, description) first = False description.append_text('}') def has_entries(*keys_valuematchers, **kv_args): """Matches if dictionary contains entries satisfying a dictionary of keys and corresponding value matchers. :param matcher_dict: A dictionary mapping keys to associated value matchers, or to expected values for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Note that the keys must be actual keys, not matchers. Any value argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_entries({'foo':equal_to(1), 'bar':equal_to(2)}) has_entries({'foo':1, 'bar':2}) ``has_entries`` also accepts a list of keyword arguments: .. function:: has_entries(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]]) :param keyword1: A keyword to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_entries(foo=equal_to(1), bar=equal_to(2)) has_entries(foo=1, bar=2) Finally, ``has_entries`` also accepts a list of alternating keys and their value matchers: .. function:: has_entries(key1, value_matcher1[, ...]) :param key1: A key (not a matcher) to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_entries('foo', equal_to(1), 'bar', equal_to(2)) has_entries('foo', 1, 'bar', 2) """ if len(keys_valuematchers) == 1: try: base_dict = keys_valuematchers[0].copy() for key in base_dict: base_dict[key] = wrap_matcher(base_dict[key]) except AttributeError: raise ValueError('single-argument calls to has_entries must pass a dict as the argument') else: if len(keys_valuematchers) % 2: raise ValueError('has_entries requires key-value pairs') base_dict = {} for index in range(int(len(keys_valuematchers) / 2)): base_dict[keys_valuematchers[2 * index]] = wrap_matcher(keys_valuematchers[2 * index + 1]) for key, value in kv_args.items(): base_dict[key] = wrap_matcher(value) return IsDictContainingEntries(base_dict) PyHamcrest-1.8.0/src/hamcrest/library/collection/isdict_containingkey.py0000644000076500000240000000277711760072653027103 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingKey(BaseMatcher): def __init__(self, key_matcher): self.key_matcher = key_matcher def _matches(self, dictionary): if hasmethod(dictionary, 'keys'): for key in dictionary.keys(): if self.key_matcher.matches(key): return True return False def describe_to(self, description): description.append_text('a dictionary containing key ') \ .append_description_of(self.key_matcher) def has_key(key_match): """Matches if dictionary contains an entry whose key satisfies a given matcher. :param key_match: The matcher to satisfy for the key, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry whose key satisfies the given matcher. If a matching entry is found, ``has_key`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_key(equal_to('foo')) has_key('foo') """ return IsDictContainingKey(wrap_matcher(key_match)) PyHamcrest-1.8.0/src/hamcrest/library/collection/isdict_containingvalue.py0000644000076500000240000000303511760072653027413 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingValue(BaseMatcher): def __init__(self, value_matcher): self.value_matcher = value_matcher def _matches(self, dictionary): if hasmethod(dictionary, 'values'): for value in dictionary.values(): if self.value_matcher.matches(value): return True return False def describe_to(self, description): description.append_text('a dictionary containing value ') \ .append_description_of(self.value_matcher) def has_value(value): """Matches if dictionary contains an entry whose value satisfies a given matcher. :param value_match: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry whose value satisfies the given matcher. If a matching entry is found, ``has_value`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_value(equal_to('bar')) has_value('bar') """ return IsDictContainingValue(wrap_matcher(value)) PyHamcrest-1.8.0/src/hamcrest/library/collection/isin.py0000644000076500000240000000140611760072653023630 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsIn(BaseMatcher): def __init__(self, sequence): self.sequence = sequence def _matches(self, item): return item in self.sequence def describe_to(self, description): description.append_text('one of ') \ .append_list('(', ', ', ')', self.sequence) def is_in(sequence): """Matches if evaluated object is present in a given sequence. :param sequence: The sequence to search. This matcher invokes the ``in`` membership operator to determine if the evaluated object is a member of the sequence. """ return IsIn(sequence) PyHamcrest-1.8.0/src/hamcrest/library/collection/issequence_containing.py0000644000076500000240000000567112101144121027227 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.core.allof import all_of from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher class IsSequenceContaining(BaseMatcher): def __init__(self, element_matcher): self.element_matcher = element_matcher def _matches(self, sequence): try: for item in sequence: if self.element_matcher.matches(item): return True except TypeError: # not a sequence return False def describe_to(self, description): description.append_text('a sequence containing ') \ .append_description_of(self.element_matcher) # It'd be great to make use of all_of, but we can't be sure we won't # be seeing a one-time sequence here (like a generator); see issue #20 # Instead, we wrap it inside a class that will convert the sequence into # a concrete list and then hand it off to the all_of matcher. class IsSequenceContainingEvery(BaseMatcher): def __init__(self, *element_matchers): delegates = [has_item(e) for e in element_matchers] self.matcher = all_of(*delegates) def _matches(self, sequence): try: return self.matcher.matches(list(sequence)) except TypeError: return False def describe_mismatch(self, item, mismatch_description): self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description): self.matcher.describe_to(description) def has_item(match): """Matches if any element of sequence satisfies a given matcher. :param match: The matcher to satisfy, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated sequence, searching for any element that satisfies a given matcher. If a matching element is found, ``has_item`` is satisfied. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return IsSequenceContaining(wrap_matcher(match)) def has_items(*items): """Matches if all of the given matchers are satisfied by any elements of the sequence. :param match1,...: A comma-separated list of matchers. This matcher iterates the given matchers, searching for any elements in the evaluated sequence that satisfy them. If each matcher is satisfied, then ``has_items`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingEvery(*matchers) PyHamcrest-1.8.0/src/hamcrest/library/collection/issequence_containinginanyorder.py0000644000076500000240000000703512213122554031330 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class MatchInAnyOrder(object): def __init__(self, matchers, mismatch_description): self.matchers = matchers[:] self.mismatch_description = mismatch_description def matches(self, item): return self.isnotsurplus(item) and self.ismatched(item) def isfinished(self, sequence): if not self.matchers: return True if self.mismatch_description: self.mismatch_description.append_text('no item matches: ') \ .append_list('', ', ', '', self.matchers) \ .append_text(' in ') \ .append_list('[', ', ', ']', sequence) return False def isnotsurplus(self, item): if not self.matchers: if self.mismatch_description: self.mismatch_description.append_text('not matched: ') \ .append_description_of(item) return False return True def ismatched(self, item): for index, matcher in enumerate(self.matchers): if matcher.matches(item): del self.matchers[index] return True if self.mismatch_description: self.mismatch_description.append_text('not matched: ') \ .append_description_of(item) return False class IsSequenceContainingInAnyOrder(BaseMatcher): def __init__(self, matchers): self.matchers = matchers def matches(self, sequence, mismatch_description=None): try: sequence = list(sequence) matchsequence = MatchInAnyOrder(self.matchers, mismatch_description) for item in sequence: if not matchsequence.matches(item): return False return matchsequence.isfinished(sequence) except TypeError: if mismatch_description: super(IsSequenceContainingInAnyOrder, self) \ .describe_mismatch(sequence, mismatch_description) return False def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_to(self, description): description.append_text('a sequence over ') \ .append_list('[', ', ', ']', self.matchers) \ .append_text(' in any order') def contains_inanyorder(*items): """Matches if sequences's elements, in any order, satisfy a given list of matchers. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence, seeing if each element satisfies any of the given matchers. The matchers are tried from left to right, and when a satisfied matcher is found, it is no longer a candidate for the remaining elements. If a one-to-one correspondence is established between elements and matchers, ``contains_inanyorder`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingInAnyOrder(matchers) PyHamcrest-1.8.0/src/hamcrest/library/collection/issequence_containinginorder.py0000644000076500000240000000622312101144121030604 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher class MatchingInOrder(object): def __init__(self, matchers, mismatch_description): self.matchers = matchers self.mismatch_description = mismatch_description self.next_match_index = 0 def matches(self, item): return self.isnotsurplus(item) and self.ismatched(item) def isfinished(self): if self.next_match_index < len(self.matchers): if self.mismatch_description: self.mismatch_description.append_text('No item matched: ') \ .append_description_of(self.matchers[self.next_match_index]) return False return True def ismatched(self, item): matcher = self.matchers[self.next_match_index] if not matcher.matches(item): if self.mismatch_description: self.mismatch_description.append_text('item ' + str(self.next_match_index) + ': ') matcher.describe_mismatch(item, self.mismatch_description) return False self.next_match_index += 1 return True def isnotsurplus(self, item): if len(self.matchers) <= self.next_match_index: if self.mismatch_description: self.mismatch_description.append_text('Not matched: ') \ .append_description_of(item) return False return True class IsSequenceContainingInOrder(BaseMatcher): def __init__(self, matchers): self.matchers = matchers def matches(self, sequence, mismatch_description=None): try: matchsequence = MatchingInOrder(self.matchers, mismatch_description) for item in sequence: if not matchsequence.matches(item): return False return matchsequence.isfinished() except TypeError: if mismatch_description: super(IsSequenceContainingInOrder, self) \ .describe_mismatch(sequence, mismatch_description) return False def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_to(self, description): description.append_text('a sequence containing ') \ .append_list('[', ', ', ']', self.matchers) def contains(*items): """Matches if sequence's elements satisfy a given list of matchers, in order. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence and a given list of matchers, seeing if each element satisfies its corresponding matcher. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingInOrder(matchers) PyHamcrest-1.8.0/src/hamcrest/library/collection/issequence_onlycontaining.py0000644000076500000240000000314012101144121030116 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.core.anyof import any_of from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsSequenceOnlyContaining(BaseMatcher): def __init__(self, matcher): self.matcher = matcher def _matches(self, sequence): try: sequence = list(sequence) if len(sequence) == 0: return False for item in sequence: if not self.matcher.matches(item): return False return True except TypeError: return False def describe_to(self, description): description.append_text('a sequence containing items matching ') \ .append_description_of(self.matcher) def only_contains(*items): """Matches if each element of sequence satisfies any of the given matchers. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence, confirming whether each element satisfies any of the given matchers. Example:: only_contains(less_than(4)) will match ``[3,1,2]``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceOnlyContaining(apply(any_of, matchers)) PyHamcrest-1.8.0/src/hamcrest/library/integration/0000755000076500000240000000000012230156532022473 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/library/integration/__init__.py0000644000076500000240000000032611760072653024615 0ustar offby1staff00000000000000"""Utilities for integrating Hamcrest with other libraries.""" from match_equality import match_equality __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/library/integration/match_equality.py0000644000076500000240000000225011760072653026065 0ustar offby1staff00000000000000from hamcrest.core.string_description import tostring from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" __unittest = True class EqualityWrapper(object): def __init__(self, matcher): self.matcher = matcher def __eq__(self, object): return self.matcher.matches(object) def __str__(self): return repr(self) def __repr__(self): return tostring(self.matcher) def match_equality(matcher): """Wraps a matcher to define equality in terms of satisfying the matcher. ``match_equality`` allows Hamcrest matchers to be used in libraries that are not Hamcrest-aware. They might use the equality operator:: assert match_equality(matcher) == object Or they might provide a method that uses equality for its test:: library.method_that_tests_eq(match_equality(matcher)) One concrete example is integrating with the ``assert_called_with`` methods in Michael Foord's `mock `_ library. """ return EqualityWrapper(wrap_matcher(matcher)) PyHamcrest-1.8.0/src/hamcrest/library/number/0000755000076500000240000000000012230156532021440 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/library/number/__init__.py0000644000076500000240000000044611760072653023565 0ustar offby1staff00000000000000"""Matchers that perform numeric comparisons.""" from iscloseto import close_to from ordering_comparison import greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/library/number/iscloseto.py0000644000076500000240000000427712213122554024026 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from math import fabs __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def isnumeric(value): """Confirm that 'value' can be treated numerically; duck-test accordingly """ if isinstance(value, (int, float, complex, long)): return True try: _ = (fabs(value) + 0 - 0) * 1 return True except ArithmeticError: return True except: return False return False class IsCloseTo(BaseMatcher): def __init__(self, value, delta): if not isnumeric(value): raise TypeError('IsCloseTo value must be numeric') if not isnumeric(delta): raise TypeError('IsCloseTo delta must be numeric') self.value = value self.delta = delta def _matches(self, item): if not isnumeric(item): return False return fabs(item - self.value) <= self.delta def describe_mismatch(self, item, mismatch_description): if not isnumeric(item): super(IsCloseTo, self).describe_mismatch(item, mismatch_description) else: actual_delta = fabs(item - self.value) mismatch_description.append_description_of(item) \ .append_text(' differed by ') \ .append_description_of(actual_delta) def describe_to(self, description): description.append_text('a numeric value within ') \ .append_description_of(self.delta) \ .append_text(' of ') \ .append_description_of(self.value) def close_to(value, delta): """Matches if object is a number close to a given value, within a given delta. :param value: The value to compare against as the expected value. :param delta: The maximum delta between the values for which the numbers are considered close. This matcher compares the evaluated object against ``value`` to see if the difference is within a positive ``delta``. Example:: close_to(3.0, 0.25) """ return IsCloseTo(value, delta) PyHamcrest-1.8.0/src/hamcrest/library/number/ordering_comparison.py0000644000076500000240000000324411760072653026070 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher import operator __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class OrderingComparison(BaseMatcher): def __init__(self, value, comparison_function, comparison_description): self.value = value self.comparison_function = comparison_function self.comparison_description = comparison_description def _matches(self, item): return self.comparison_function(item, self.value) def describe_to(self, description): description.append_text('a value ') \ .append_text(self.comparison_description) \ .append_text(' ') \ .append_description_of(self.value) def greater_than(value): """Matches if object is greater than a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.gt, 'greater than') def greater_than_or_equal_to(value): """Matches if object is greater than or equal to a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.ge, 'greater than or equal to') def less_than(value): """Matches if object is less than a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.lt, 'less than') def less_than_or_equal_to(value): """Matches if object is less than or equal to a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.le, 'less than or equal to') PyHamcrest-1.8.0/src/hamcrest/library/object/0000755000076500000240000000000012230156532021416 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/library/object/__init__.py0000644000076500000240000000042512213003323023516 0ustar offby1staff00000000000000"""Matchers that inspect objects and classes.""" from haslength import has_length from hasproperty import has_property, has_properties from hasstring import has_string __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/library/object/haslength.py0000644000076500000240000000322112101144121023727 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class HasLength(BaseMatcher): def __init__(self, len_matcher): self.len_matcher = len_matcher def _matches(self, item): if not hasmethod(item, '__len__'): return False return self.len_matcher.matches(len(item)) def describe_mismatch(self, item, mismatch_description): super(HasLength, self).describe_mismatch(item, mismatch_description) if hasmethod(item, '__len__'): mismatch_description.append_text(' with length of ') \ .append_description_of(len(item)) def describe_to(self, description): description.append_text('an object with length of ') \ .append_description_of(self.len_matcher) def has_length(match): """Matches if ``len(item)`` satisfies a given matcher. :param match: The matcher to satisfy, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher invokes the :py:func:`len` function on the evaluated object to get its length, passing the result to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for :equality. Examples:: has_length(greater_than(6)) has_length(5) """ return HasLength(wrap_matcher(match)) PyHamcrest-1.8.0/src/hamcrest/library/object/hasproperty.py0000644000076500000240000001315412101144121024340 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core import anything from hamcrest.core.core.allof import all_of from hamcrest.core.string_description import StringDescription from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsObjectWithProperty(BaseMatcher): def __init__(self, property_name, value_matcher): self.property_name = property_name self.value_matcher = value_matcher def _matches(self, o): if o is None: return False if not hasattr(o, self.property_name): return False value = getattr(o, self.property_name) return self.value_matcher.matches(value) def describe_to(self, description): description.append_text("an object with a property '") \ .append_text(self.property_name) \ .append_text("' matching ") \ .append_description_of(self.value_matcher) def describe_mismatch(self, item, mismatch_description): if item is None: mismatch_description.append_text('was None') return if not hasattr(item, self.property_name): mismatch_description.append_value(item) \ .append_text(' did not have the ') \ .append_value(self.property_name) \ .append_text(' property') return mismatch_description.append_text('property ').append_value(self.property_name).append_text(' ') value = getattr(item, self.property_name) self.value_matcher.describe_mismatch(value, mismatch_description) def __str__(self): d = StringDescription() self.describe_to(d) return str(d) def has_property(name, match=None): """Matches if object has a property with a given name whose value satisfies a given matcher. :param name: The name of the property. :param match: Optional matcher to satisfy. This matcher determines if the evaluated object has a property with a given name. If no such property is found, ``has_property`` is not satisfied. If the property is found, its value is passed to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. If the ``match`` argument is not provided, the :py:func:`~hamcrest.core.core.isanything.anything` matcher is used so that ``has_property`` is satisfied if a matching property is found. Examples:: has_property('name', starts_with('J')) has_property('name', 'Jon') has_property('name') """ if match is None: match = anything() return IsObjectWithProperty(name, wrap_shortcut(match)) def has_properties(*keys_valuematchers, **kv_args): """Matches if an object has properties satisfying all of a dictionary of string property names and corresponding value matchers. :param matcher_dict: A dictionary mapping keys to associated value matchers, or to expected values for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Note that the keys must be actual keys, not matchers. Any value argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_properties({'foo':equal_to(1), 'bar':equal_to(2)}) has_properties({'foo':1, 'bar':2}) ``has_properties`` also accepts a list of keyword arguments: .. function:: has_properties(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]]) :param keyword1: A keyword to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_properties(foo=equal_to(1), bar=equal_to(2)) has_properties(foo=1, bar=2) Finally, ``has_properties`` also accepts a list of alternating keys and their value matchers: .. function:: has_properties(key1, value_matcher1[, ...]) :param key1: A key (not a matcher) to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_properties('foo', equal_to(1), 'bar', equal_to(2)) has_properties('foo', 1, 'bar', 2) """ if len(keys_valuematchers) == 1: try: base_dict = keys_valuematchers[0].copy() for key in base_dict: base_dict[key] = wrap_shortcut(base_dict[key]) except AttributeError: raise ValueError('single-argument calls to has_properties must pass a dict as the argument') else: if len(keys_valuematchers) % 2: raise ValueError('has_properties requires key-value pairs') base_dict = {} for index in range(int(len(keys_valuematchers) / 2)): base_dict[keys_valuematchers[2 * index]] = wrap_shortcut(keys_valuematchers[2 * index + 1]) for key, value in kv_args.items(): base_dict[key] = wrap_shortcut(value) return all_of(*[has_property(property_name, property_value_matcher) for \ property_name, property_value_matcher in base_dict.items()]) PyHamcrest-1.8.0/src/hamcrest/library/object/hasstring.py0000644000076500000240000000234212101144121023757 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class HasString(BaseMatcher): def __init__(self, str_matcher): self.str_matcher = str_matcher def _matches(self, item): return self.str_matcher.matches(str(item)) def describe_to(self, description): description.append_text('an object with str ') \ .append_description_of(self.str_matcher) def has_string(match): """Matches if ``str(item)`` satisfies a given matcher. :param match: The matcher to satisfy, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher invokes the :py:func:`str` function on the evaluated object to get its length, passing the result to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_string(starts_with('foo')) has_string('bar') """ return HasString(wrap_matcher(match)) PyHamcrest-1.8.0/src/hamcrest/library/text/0000755000076500000240000000000012230156532021134 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/hamcrest/library/text/__init__.py0000644000076500000240000000076612213122554023254 0ustar offby1staff00000000000000"""Matchers that perform text comparisons.""" from isequal_ignoring_case import equal_to_ignoring_case from isequal_ignoring_whitespace import equal_to_ignoring_whitespace from stringcontains import contains_string from stringendswith import ends_with from stringstartswith import starts_with from stringmatches import matches_regexp from stringcontainsinorder import string_contains_in_order __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-1.8.0/src/hamcrest/library/text/isequal_ignoring_case.py0000644000076500000240000000232212101144121026023 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsEqualIgnoringCase(BaseMatcher): def __init__(self, string): if not isinstance(string, basestring): raise TypeError('IsEqualIgnoringCase requires string') self.original_string = string self.lowered_string = string.lower() def _matches(self, item): if not isinstance(item, basestring): return False return self.lowered_string == item.lower() def describe_to(self, description): description.append_description_of(self.original_string) \ .append_text(' ignoring case') def equal_to_ignoring_case(string): """Matches if object is a string equal to a given string, ignoring case differences. :param string: The string to compare against as the expected value. This matcher first checks whether the evaluated object is a string. If so, it compares it with ``string``, ignoring differences of case. Example:: equal_to_ignoring_case("hello world") will match "heLLo WorlD". """ return IsEqualIgnoringCase(string) PyHamcrest-1.8.0/src/hamcrest/library/text/isequal_ignoring_whitespace.py0000644000076500000240000000315412213122554027262 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def stripspace(string): result = '' last_was_space = True for character in string: if character.isspace(): if not last_was_space: result += ' ' last_was_space = True else: result += character last_was_space = False return result.strip() class IsEqualIgnoringWhiteSpace(BaseMatcher): def __init__(self, string): if not isinstance(string, basestring): raise TypeError('IsEqualIgnoringWhiteSpace requires string') self.original_string = string self.stripped_string = stripspace(string) def _matches(self, item): if not isinstance(item, basestring): return False return self.stripped_string == stripspace(item) def describe_to(self, description): description.append_description_of(self.original_string) \ .append_text(' ignoring whitespace') def equal_to_ignoring_whitespace(string): """Matches if object is a string equal to a given string, ignoring differences in whitespace. :param string: The string to compare against as the expected value. This matcher first checks whether the evaluated object is a string. If so, it compares it with ``string``, ignoring differences in runs of whitespace. Example:: equal_to_ignoring_whitespace("hello world") will match ``"hello world"``. """ return IsEqualIgnoringWhiteSpace(string) PyHamcrest-1.8.0/src/hamcrest/library/text/stringcontains.py0000644000076500000240000000167112101144121024544 0ustar offby1staff00000000000000from hamcrest.library.text.substringmatcher import SubstringMatcher from hamcrest.core.helpers.hasmethod import hasmethod __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringContains(SubstringMatcher): def __init__(self, substring): super(StringContains, self).__init__(substring) def _matches(self, item): if not hasmethod(item, 'find'): return False return item.find(self.substring) >= 0 def relationship(self): return 'containing' def contains_string(substring): """Matches if object is a string containing a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks whether it contains ``string``. Example:: contains_string("def") will match "abcdefg". """ return StringContains(substring) PyHamcrest-1.8.0/src/hamcrest/library/text/stringcontainsinorder.py0000644000076500000240000000322711760072653026152 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod __author__ = "Romilly Cocking" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringContainsInOrder(BaseMatcher): def __init__(self, *substrings): for substring in substrings: if not isinstance(substring, basestring): raise TypeError(self.__class__.__name__ + ' requires string arguments') self.substrings = substrings def _matches(self, item): if not hasmethod(item, 'find'): return False from_index = 0 for substring in self.substrings: from_index = item.find(substring, from_index) if from_index == -1: return False return True def describe_to(self, description): description.append_list('a string containing ', ', ', ' in order', self.substrings) def string_contains_in_order(*substrings): """Matches if object is a string containing a given list of substrings in relative order. :param string1,...: A comma-separated list of strings. This matcher first checks whether the evaluated object is a string. If so, it checks whether it contains a given list of strings, in relative order to each other. The searches are performed starting from the beginning of the evaluated string. Example:: string_contains_in_order("bc", "fg", "jkl") will match "abcdefghijklm". """ return StringContainsInOrder(*substrings) PyHamcrest-1.8.0/src/hamcrest/library/text/stringendswith.py0000644000076500000240000000172411760072653024576 0ustar offby1staff00000000000000from hamcrest.library.text.substringmatcher import SubstringMatcher from hamcrest.core.helpers.hasmethod import hasmethod __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringEndsWith(SubstringMatcher): def __init__(self, substring): super(StringEndsWith, self).__init__(substring) def _matches(self, item): if not hasmethod(item, 'endswith'): return False return item.endswith(self.substring) def relationship(self): return 'ending with' def ends_with(string): """Matches if object is a string ending with a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if ``string`` matches the ending characters of the evaluated object. Example:: ends_with("bar") will match "foobar". """ return StringEndsWith(string) PyHamcrest-1.8.0/src/hamcrest/library/text/stringmatches.py0000644000076500000240000000215512101144121024350 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod import re __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringMatchesPattern(BaseMatcher): def __init__(self, pattern): self.pattern = pattern def describe_to(self, description): description.append_text("a string matching '") \ .append_text(self.pattern.pattern) \ .append_text("'") def _matches(self, item): return self.pattern.search(item) is not None def matches_regexp(pattern): """Matches if object is a string containing a match for a given regular expression. :param pattern: The regular expression to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if the regular expression ``pattern`` matches anywhere within the evaluated object. """ if isinstance(pattern, basestring): pattern = re.compile(pattern) return StringMatchesPattern(pattern) PyHamcrest-1.8.0/src/hamcrest/library/text/stringstartswith.py0000644000076500000240000000175711760072653025173 0ustar offby1staff00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.library.text.substringmatcher import SubstringMatcher from hamcrest.core.helpers.hasmethod import hasmethod class StringStartsWith(SubstringMatcher): def __init__(self, substring): super(StringStartsWith, self).__init__(substring) def _matches(self, item): if not hasmethod(item, 'startswith'): return False return item.startswith(self.substring) def relationship(self): return 'starting with' def starts_with(substring): """Matches if object is a string starting with a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if ``string`` matches the beginning characters of the evaluated object. Example:: starts_with("foo") will match "foobar". """ return StringStartsWith(substring) PyHamcrest-1.8.0/src/hamcrest/library/text/substringmatcher.py0000644000076500000240000000124612215764423025104 0ustar offby1staff00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class SubstringMatcher(BaseMatcher): def __init__(self, substring): if not isinstance(substring, basestring): raise TypeError(self.__class__.__name__ + ' requires string') self.substring = substring def describe_to(self, description): description.append_text('a string ') \ .append_text(self.relationship()) \ .append_text(' ') \ .append_description_of(self.substring) PyHamcrest-1.8.0/src/PyHamcrest.egg-info/0000755000076500000240000000000012230156532020447 5ustar offby1staff00000000000000PyHamcrest-1.8.0/src/PyHamcrest.egg-info/dependency_links.txt0000644000076500000240000000000112230156532024515 0ustar offby1staff00000000000000 PyHamcrest-1.8.0/src/PyHamcrest.egg-info/PKG-INFO0000644000076500000240000003172512230156532021554 0ustar offby1staff00000000000000Metadata-Version: 1.1 Name: PyHamcrest Version: 1.8.0 Summary: Hamcrest framework for matcher objects Home-page: https://github.com/hamcrest/PyHamcrest Author: Chris Rose Author-email: offline@offby1.net License: New BSD Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.8.0.tar.gz Description: PyHamcrest ========== .. image:: https://pypip.in/v/PyHamcrest/badge.png :alt: Release Status :target: https://crate.io/packages/PyHamcrest .. image:: https://pypip.in/d/PyHamcrest/badge.png :alt: Downloads :target: https://crate.io/packages/PyHamcrest .. image:: https://travis-ci.org/hamcrest/PyHamcrest.png?branch=master :alt: Build Status :target: https://travis-ci.org/hamcrest/PyHamcrest Introduction ============ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. Installation ============ Hamcrest can be installed using the usual Python packaging tools. It depends on distribute, but as long as you have a network connection when you install, the installation process will take care of that for you. My first PyHamcrest test ======================== We'll start by writing a very simple PyUnit test, but instead of using PyUnit's ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and the standard set of matchers: .. code:: python from hamcrest import * import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit('Ginger') myBiscuit = Biscuit('Ginger') assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == '__main__': unittest.main() The ``assert_that`` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier for the tested value in the assertion: .. code:: python assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips') assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts') As a convenience, assert_that can also be used to verify a boolean condition: .. code:: python assert_that(theBiscuit.isCooked(), 'cooked') This is equivalent to the ``assert_`` method of unittest.TestCase, but because it's a standalone function, it offers greater flexibility in test writing. Predefined matchers =================== PyHamcrest comes with a library of useful matchers: * Object * ``equal_to`` - match equal object * ``has_length`` - match ``len()`` * ``has_property`` - match value of property with given name * ``has_properties`` - match an object that has all of the given properties. * ``has_string`` - match ``str()`` * ``instance_of`` - match object type * ``none``, ``not_none`` - match ``None``, or not ``None`` * ``same_instance`` - match same object * Number * ``close_to`` - match number close to a given value * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``, ``less_than_or_equal_to`` - match numeric ordering * Text * ``contains_string`` - match part of a string * ``ends_with`` - match the end of a string * ``equal_to_ignoring_case`` - match the complete string but ignore case * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace * ``matches_regexp`` - match a regular expression in a string * ``starts_with`` - match the beginning of a string * ``string_contains_in_order`` - match parts of a string, in relative order * Logical * ``all_of`` - ``and`` together all matchers * ``any_of`` - ``or`` together all matchers * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value * ``is_not`` - negate the matcher * Sequence * ``contains`` - exactly match the entire sequence * ``contains_inanyorder`` - match the entire sequence, but in any order * ``has_item`` - match if given item appears in the sequence * ``has_items`` - match if all given items appear in the sequence, in any order * ``is_in`` - match if item appears in the given sequence * ``only_contains`` - match if sequence's items appear in given list * Dictionary * ``has_entries`` - match dictionary with list of key-value pairs * ``has_entry`` - match dictionary containing a key-value pair * ``has_key`` - match dictionary with a key * ``has_value`` - match dictionary with a value * Decorator * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour * ``raises`` - Ensure that a deferred callable raises as expected * ``described_as`` - give the matcher a custom failure description * ``is_`` - decorator to improve readability - see `Syntactic sugar` below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. Syntactic sugar =============== PyHamcrest strives to make your tests as readable as possible. For example, the ``is_`` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent: .. code:: python assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with ``equal_to``. But if the argument is a type, it is wrapped with ``instance_of``, so the following are also equivalent: .. code:: python assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is ``same_instance``.* Writing custom matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write: .. code:: python def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation: .. code:: python from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod class IsGivenDayOfWeek(BaseMatcher): def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): if not hasmethod(item, 'weekday'): return False return item.weekday() == self.day def describe_to(self, description): day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] description.append_text('calendar date falling on ') \ .append_text(day_as_string[self.day]) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the ``_matches`` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the ``describe_to`` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks: .. code:: python assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``: .. code:: python from hamcrest import * import unittest from isgivendayofweek import on_a_saturday class DateTest(unittest.TestCase): def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. More resources ============== * Documentation_ * Package_ * Sources_ * Hamcrest_ .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.7.1/ .. _Package: http://pypi.python.org/pypi/PyHamcrest .. _Sources: https://github.com/hamcrest/PyHamcrest .. _Hamcrest: http://hamcrest.org Keywords: hamcrest matchers pyunit unit test testing unittest unittesting Platform: All Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Testing Provides: hamcrest PyHamcrest-1.8.0/src/PyHamcrest.egg-info/requires.txt0000644000076500000240000000001212230156532023040 0ustar offby1staff00000000000000setuptoolsPyHamcrest-1.8.0/src/PyHamcrest.egg-info/SOURCES.txt0000644000076500000240000000514712230156532022342 0ustar offby1staff00000000000000CHANGES.txt LICENSE.txt MANIFEST.in README.rst setup.cfg setup.py examples/CustomDateMatcher.py examples/ExampleWithAssertThat.py src/PyHamcrest.egg-info/PKG-INFO src/PyHamcrest.egg-info/SOURCES.txt src/PyHamcrest.egg-info/dependency_links.txt src/PyHamcrest.egg-info/requires.txt src/PyHamcrest.egg-info/top_level.txt src/hamcrest/__init__.py src/hamcrest/core/__init__.py src/hamcrest/core/assert_that.py src/hamcrest/core/base_description.py src/hamcrest/core/base_matcher.py src/hamcrest/core/compat.py src/hamcrest/core/description.py src/hamcrest/core/matcher.py src/hamcrest/core/selfdescribing.py src/hamcrest/core/selfdescribingvalue.py src/hamcrest/core/string_description.py src/hamcrest/core/core/__init__.py src/hamcrest/core/core/allof.py src/hamcrest/core/core/anyof.py src/hamcrest/core/core/described_as.py src/hamcrest/core/core/is_.py src/hamcrest/core/core/isanything.py src/hamcrest/core/core/isequal.py src/hamcrest/core/core/isinstanceof.py src/hamcrest/core/core/isnone.py src/hamcrest/core/core/isnot.py src/hamcrest/core/core/issame.py src/hamcrest/core/core/raises.py src/hamcrest/core/helpers/__init__.py src/hamcrest/core/helpers/hasmethod.py src/hamcrest/core/helpers/wrap_matcher.py src/hamcrest/library/__init__.py src/hamcrest/library/collection/__init__.py src/hamcrest/library/collection/is_empty.py src/hamcrest/library/collection/isdict_containing.py src/hamcrest/library/collection/isdict_containingentries.py src/hamcrest/library/collection/isdict_containingkey.py src/hamcrest/library/collection/isdict_containingvalue.py src/hamcrest/library/collection/isin.py src/hamcrest/library/collection/issequence_containing.py src/hamcrest/library/collection/issequence_containinginanyorder.py src/hamcrest/library/collection/issequence_containinginorder.py src/hamcrest/library/collection/issequence_onlycontaining.py src/hamcrest/library/integration/__init__.py src/hamcrest/library/integration/match_equality.py src/hamcrest/library/number/__init__.py src/hamcrest/library/number/iscloseto.py src/hamcrest/library/number/ordering_comparison.py src/hamcrest/library/object/__init__.py src/hamcrest/library/object/haslength.py src/hamcrest/library/object/hasproperty.py src/hamcrest/library/object/hasstring.py src/hamcrest/library/text/__init__.py src/hamcrest/library/text/isequal_ignoring_case.py src/hamcrest/library/text/isequal_ignoring_whitespace.py src/hamcrest/library/text/stringcontains.py src/hamcrest/library/text/stringcontainsinorder.py src/hamcrest/library/text/stringendswith.py src/hamcrest/library/text/stringmatches.py src/hamcrest/library/text/stringstartswith.py src/hamcrest/library/text/substringmatcher.pyPyHamcrest-1.8.0/src/PyHamcrest.egg-info/top_level.txt0000644000076500000240000000001112230156532023171 0ustar offby1staff00000000000000hamcrest