diff --git a/CHANGES.txt b/CHANGES.txt index e5aced9..9450626 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,11 +1,46 @@ -Full documentation: http://packages.python.org/PyHamcrest -Latest package: http://pypi.python.org/pypi/PyHamcrest -Latest sources: https://github.com/jonreid/PyHamcrest -Hamcrest information: http://code.google.com/p/hamcrest +=== Version 1.8 == -See also: -Objective-C version for Cocoa and iOS: https://github.com/jonreid/OCHamcrest -Quality Coding - Tools, tips and techniques for building quality in to your iOS programs: http://jonreid.blogs.com/qualitycoding/ +* 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 == diff --git a/PKG-INFO b/PKG-INFO index 5bfa41e..45963ed 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,24 +1,24 @@ Metadata-Version: 1.1 Name: PyHamcrest -Version: 1.6 +Version: 1.8.0 Summary: Hamcrest framework for matcher objects -Home-page: http://code.google.com/p/hamcrest/ -Author: Jon Reid -Author-email: jon.reid@mac.com +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.6.tar.gz -Description: * [Full documentation](http://packages.python.org/PyHamcrest) - * [Latest package](http://pypi.python.org/pypi/PyHamcrest) - * [Latest sources](https://github.com/jonreid/PyHamcrest) - * [Hamcrest information](http://code.google.com/p/hamcrest) - - See also: - - * [OCHamcrest](https://github.com/jonreid/OCHamcrest) - Objective-C version for - Cocoa and iOS. - * [Quality Coding](http://jonreid.blogs.com/qualitycoding/) - Tools, tips and - techniques for _building quality in_ to your iOS programs. - +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 ============ @@ -51,19 +51,21 @@ 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:: - - 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 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 @@ -73,14 +75,18 @@ 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:: - - 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:: - - assert_that(theBiscuit.isCooked(), 'cooked') + 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. @@ -93,59 +99,60 @@ * Object - * ``equal_to`` - match equal object - * ``has_length`` - match ``len()`` - * ``has_property`` - match value of property with given name - * ``has_string`` - match ``str()`` - * ``instance_of`` - match object type - * ``none``, ``not_none`` - match ``None``, or not ``None`` - * ``same_instance`` - match same 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 + * ``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 - * ``starts_with`` - match the beginning of a string - * ``string_contains_in_order`` - match parts of a string, in relative order + * ``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 + * ``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 + * ``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 + * ``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 - * ``described_as`` - give the matcher a custom failure description - * ``is_`` - decorator to improve readability - see `Syntactic sugar` below + * ``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 @@ -158,19 +165,23 @@ 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:: - - assert_that(theBiscuit, equal_to(myBiscuit)) - assert_that(theBiscuit, is_(equal_to(myBiscuit))) - assert_that(theBiscuit, is_(myBiscuit)) + 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:: - - assert_that(theBiscuit, instance_of(Biscuit)) - assert_that(theBiscuit, is_(instance_of(Biscuit))) - assert_that(theBiscuit, is_(Biscuit)) + ``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``.* @@ -187,69 +198,91 @@ 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:: - - def testDateIsOnASaturday(self): - d = datetime.date(2008, 04, 26) - assert_that(d, is_(on_a_saturday())) - - And here's the implementation:: - - 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) + 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:: - - assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) + 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> + 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``:: - - 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() + 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 @@ -262,8 +295,8 @@ Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.1 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 diff --git a/PyHamcrest.egg-info/PKG-INFO b/PyHamcrest.egg-info/PKG-INFO deleted file mode 100644 index 5bfa41e..0000000 --- a/PyHamcrest.egg-info/PKG-INFO +++ /dev/null @@ -1,270 +0,0 @@ -Metadata-Version: 1.1 -Name: PyHamcrest -Version: 1.6 -Summary: Hamcrest framework for matcher objects -Home-page: http://code.google.com/p/hamcrest/ -Author: Jon Reid -Author-email: jon.reid@mac.com -License: New BSD -Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.6.tar.gz -Description: * [Full documentation](http://packages.python.org/PyHamcrest) - * [Latest package](http://pypi.python.org/pypi/PyHamcrest) - * [Latest sources](https://github.com/jonreid/PyHamcrest) - * [Hamcrest information](http://code.google.com/p/hamcrest) - - See also: - - * [OCHamcrest](https://github.com/jonreid/OCHamcrest) - Objective-C version for - Cocoa and iOS. - * [Quality Coding](http://jonreid.blogs.com/qualitycoding/) - Tools, tips and - techniques for _building quality in_ to your iOS programs. - - - 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:: - - 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:: - - 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:: - - 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_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 - * ``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 - - * ``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:: - - 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:: - - 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:: - - def testDateIsOnASaturday(self): - d = datetime.date(2008, 04, 26) - assert_that(d, is_(on_a_saturday())) - - And here's the implementation:: - - 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:: - - 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``:: - - 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. - -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.1 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Topic :: Software Development -Classifier: Topic :: Software Development :: Quality Assurance -Classifier: Topic :: Software Development :: Testing -Provides: hamcrest diff --git a/PyHamcrest.egg-info/SOURCES.txt b/PyHamcrest.egg-info/SOURCES.txt deleted file mode 100644 index 71a292e..0000000 --- a/PyHamcrest.egg-info/SOURCES.txt +++ /dev/null @@ -1,112 +0,0 @@ -CHANGES.txt -LICENSE.txt -MANIFEST.in -README.md -setup.cfg -setup.py -PyHamcrest.egg-info/PKG-INFO -PyHamcrest.egg-info/SOURCES.txt -PyHamcrest.egg-info/dependency_links.txt -PyHamcrest.egg-info/requires.txt -PyHamcrest.egg-info/top_level.txt -examples/CustomDateMatcher.py -examples/ExampleWithAssertThat.py -hamcrest/__init__.py -hamcrest/core/__init__.py -hamcrest/core/assert_that.py -hamcrest/core/base_description.py -hamcrest/core/base_matcher.py -hamcrest/core/description.py -hamcrest/core/matcher.py -hamcrest/core/selfdescribing.py -hamcrest/core/selfdescribingvalue.py -hamcrest/core/string_description.py -hamcrest/core/core/__init__.py -hamcrest/core/core/allof.py -hamcrest/core/core/anyof.py -hamcrest/core/core/described_as.py -hamcrest/core/core/is_.py -hamcrest/core/core/isanything.py -hamcrest/core/core/isequal.py -hamcrest/core/core/isinstanceof.py -hamcrest/core/core/isnone.py -hamcrest/core/core/isnot.py -hamcrest/core/core/issame.py -hamcrest/core/helpers/__init__.py -hamcrest/core/helpers/hasmethod.py -hamcrest/core/helpers/wrap_matcher.py -hamcrest/library/__init__.py -hamcrest/library/collection/__init__.py -hamcrest/library/collection/isdict_containing.py -hamcrest/library/collection/isdict_containingentries.py -hamcrest/library/collection/isdict_containingkey.py -hamcrest/library/collection/isdict_containingvalue.py -hamcrest/library/collection/isin.py -hamcrest/library/collection/issequence_containing.py -hamcrest/library/collection/issequence_containinginanyorder.py -hamcrest/library/collection/issequence_containinginorder.py -hamcrest/library/collection/issequence_onlycontaining.py -hamcrest/library/integration/__init__.py -hamcrest/library/integration/match_equality.py -hamcrest/library/number/__init__.py -hamcrest/library/number/iscloseto.py -hamcrest/library/number/ordering_comparison.py -hamcrest/library/object/__init__.py -hamcrest/library/object/haslength.py -hamcrest/library/object/hasproperty.py -hamcrest/library/object/hasstring.py -hamcrest/library/text/__init__.py -hamcrest/library/text/isequal_ignoring_case.py -hamcrest/library/text/isequal_ignoring_whitespace.py -hamcrest/library/text/stringcontains.py -hamcrest/library/text/stringcontainsinorder.py -hamcrest/library/text/stringendswith.py -hamcrest/library/text/stringstartswith.py -hamcrest/library/text/substringmatcher.py -hamcrest_unit_test/__init__.py -hamcrest_unit_test/alltests.py -hamcrest_unit_test/assert_that_test.py -hamcrest_unit_test/base_matcher_test.py -hamcrest_unit_test/matcher_test.py -hamcrest_unit_test/object_import.py -hamcrest_unit_test/string_description_test.py -hamcrest_unit_test/collection/__init__.py -hamcrest_unit_test/collection/isdict_containing_test.py -hamcrest_unit_test/collection/isdict_containingentries_test.py -hamcrest_unit_test/collection/isdict_containingkey_test.py -hamcrest_unit_test/collection/isdict_containingvalue_test.py -hamcrest_unit_test/collection/isin_test.py -hamcrest_unit_test/collection/issequence_containing_test.py -hamcrest_unit_test/collection/issequence_containinginanyorder_test.py -hamcrest_unit_test/collection/issequence_containinginorder_test.py -hamcrest_unit_test/collection/issequence_onlycontaining_test.py -hamcrest_unit_test/collection/quasidict.py -hamcrest_unit_test/collection/quasisequence.py -hamcrest_unit_test/core/__init__.py -hamcrest_unit_test/core/allof_test.py -hamcrest_unit_test/core/anyof_test.py -hamcrest_unit_test/core/described_as_test.py -hamcrest_unit_test/core/is_test.py -hamcrest_unit_test/core/isanything_test.py -hamcrest_unit_test/core/isequal_test.py -hamcrest_unit_test/core/isinstanceof_test.py -hamcrest_unit_test/core/isnone_test.py -hamcrest_unit_test/core/isnot_test.py -hamcrest_unit_test/core/issame_test.py -hamcrest_unit_test/core/nevermatch.py -hamcrest_unit_test/integration/__init__.py -hamcrest_unit_test/integration/match_equality_test.py -hamcrest_unit_test/number/__init__.py -hamcrest_unit_test/number/iscloseto_test.py -hamcrest_unit_test/number/ordering_comparison_test.py -hamcrest_unit_test/object/__init__.py -hamcrest_unit_test/object/haslength_test.py -hamcrest_unit_test/object/hasproperty_test.py -hamcrest_unit_test/object/hasstring_test.py -hamcrest_unit_test/text/__init__.py -hamcrest_unit_test/text/isequal_ignoring_case_test.py -hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py -hamcrest_unit_test/text/stringcontains_test.py -hamcrest_unit_test/text/stringcontainsinorder_test.py -hamcrest_unit_test/text/stringendswith_test.py -hamcrest_unit_test/text/stringstartswith_test.py \ No newline at end of file diff --git a/PyHamcrest.egg-info/dependency_links.txt b/PyHamcrest.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/PyHamcrest.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/PyHamcrest.egg-info/requires.txt b/PyHamcrest.egg-info/requires.txt deleted file mode 100644 index a658bb5..0000000 --- a/PyHamcrest.egg-info/requires.txt +++ /dev/null @@ -1 +0,0 @@ -distribute \ No newline at end of file diff --git a/PyHamcrest.egg-info/top_level.txt b/PyHamcrest.egg-info/top_level.txt deleted file mode 100644 index d3b4ecb..0000000 --- a/PyHamcrest.egg-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -hamcrest_unit_test -hamcrest diff --git a/README.md b/README.md deleted file mode 100644 index d1c7a8a..0000000 --- a/README.md +++ /dev/null @@ -1,243 +0,0 @@ -* [Full documentation](http://packages.python.org/PyHamcrest) -* [Latest package](http://pypi.python.org/pypi/PyHamcrest) -* [Latest sources](https://github.com/jonreid/PyHamcrest) -* [Hamcrest information](http://code.google.com/p/hamcrest) - -See also: - -* [OCHamcrest](https://github.com/jonreid/OCHamcrest) - Objective-C version for -Cocoa and iOS. -* [Quality Coding](http://jonreid.blogs.com/qualitycoding/) - Tools, tips and -techniques for _building quality in_ to your iOS programs. - - -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:: - - 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:: - - 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:: - - 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_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 - * ``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 - - * ``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:: - - 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:: - - 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:: - - def testDateIsOnASaturday(self): - d = datetime.date(2008, 04, 26) - assert_that(d, is_(on_a_saturday())) - -And here's the implementation:: - - 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:: - - 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``:: - - 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. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..d8bf5bb --- /dev/null +++ b/README.rst @@ -0,0 +1,276 @@ +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 diff --git a/hamcrest/__init__.py b/hamcrest/__init__.py deleted file mode 100644 index af51953..0000000 --- a/hamcrest/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from core import * -from library import * - -__version__ = "1.6" -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/core/._base_matcher.py b/hamcrest/core/._base_matcher.py deleted file mode 100644 index 9a381a8..0000000 Binary files a/hamcrest/core/._base_matcher.py and /dev/null differ diff --git a/hamcrest/core/__init__.py b/hamcrest/core/__init__.py deleted file mode 100644 index 1357054..0000000 --- a/hamcrest/core/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from assert_that import assert_that -from core import * - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/core/assert_that.py b/hamcrest/core/assert_that.py deleted file mode 100644 index 17d674c..0000000 --- a/hamcrest/core/assert_that.py +++ /dev/null @@ -1,61 +0,0 @@ -from matcher import Matcher -from string_description import StringDescription - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" -__unittest = 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) diff --git a/hamcrest/core/base_description.py b/hamcrest/core/base_description.py deleted file mode 100644 index 1bca6c5..0000000 --- a/hamcrest/core/base_description.py +++ /dev/null @@ -1,89 +0,0 @@ -from 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 diff --git a/hamcrest/core/base_matcher.py b/hamcrest/core/base_matcher.py deleted file mode 100644 index 66bf91d..0000000 --- a/hamcrest/core/base_matcher.py +++ /dev/null @@ -1,33 +0,0 @@ -__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) diff --git a/hamcrest/core/core/__init__.py b/hamcrest/core/core/__init__.py deleted file mode 100644 index 0801c89..0000000 --- a/hamcrest/core/core/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -"""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 - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/core/core/allof.py b/hamcrest/core/core/allof.py deleted file mode 100644 index 35c5d0b..0000000 --- a/hamcrest/core/core/allof.py +++ /dev/null @@ -1,44 +0,0 @@ -from 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]) diff --git a/hamcrest/core/core/anyof.py b/hamcrest/core/core/anyof.py deleted file mode 100644 index 7a2bfc6..0000000 --- a/hamcrest/core/core/anyof.py +++ /dev/null @@ -1,37 +0,0 @@ -from 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]) diff --git a/hamcrest/core/core/described_as.py b/hamcrest/core/core/described_as.py deleted file mode 100644 index 646a9d3..0000000 --- a/hamcrest/core/core/described_as.py +++ /dev/null @@ -1,49 +0,0 @@ -import re - -from hamcrest.core.base_matcher import BaseMatcher - -__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) diff --git a/hamcrest/core/core/is_.py b/hamcrest/core/core/is_.py deleted file mode 100644 index 28a4f32..0000000 --- a/hamcrest/core/core/is_.py +++ /dev/null @@ -1,75 +0,0 @@ -__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 -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 isinstance(x, type): - 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)) diff --git a/hamcrest/core/core/isanything.py b/hamcrest/core/core/isanything.py deleted file mode 100644 index f916811..0000000 --- a/hamcrest/core/core/isanything.py +++ /dev/null @@ -1,31 +0,0 @@ -from 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) diff --git a/hamcrest/core/core/isequal.py b/hamcrest/core/core/isequal.py deleted file mode 100644 index 119fd58..0000000 --- a/hamcrest/core/core/isequal.py +++ /dev/null @@ -1,32 +0,0 @@ -__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) diff --git a/hamcrest/core/core/isinstanceof.py b/hamcrest/core/core/isinstanceof.py deleted file mode 100644 index 867b49b..0000000 --- a/hamcrest/core/core/isinstanceof.py +++ /dev/null @@ -1,36 +0,0 @@ -from hamcrest.core.base_matcher import BaseMatcher - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsInstanceOf(BaseMatcher): - - def __init__(self, expected_type): - if not isinstance(expected_type, 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) diff --git a/hamcrest/core/core/isnone.py b/hamcrest/core/core/isnone.py deleted file mode 100644 index 5ef4f24..0000000 --- a/hamcrest/core/core/isnone.py +++ /dev/null @@ -1,25 +0,0 @@ -__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()) diff --git a/hamcrest/core/core/isnot.py b/hamcrest/core/core/isnot.py deleted file mode 100644 index ba48d2d..0000000 --- a/hamcrest/core/core/isnot.py +++ /dev/null @@ -1,38 +0,0 @@ -__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 -from isequal import equal_to - - -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 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_matcher(match)) diff --git a/hamcrest/core/core/issame.py b/hamcrest/core/core/issame.py deleted file mode 100644 index b1f8542..0000000 --- a/hamcrest/core/core/issame.py +++ /dev/null @@ -1,39 +0,0 @@ -__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) diff --git a/hamcrest/core/description.py b/hamcrest/core/description.py deleted file mode 100644 index 6201b7f..0000000 --- a/hamcrest/core/description.py +++ /dev/null @@ -1,58 +0,0 @@ -__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') diff --git a/hamcrest/core/helpers/__init__.py b/hamcrest/core/helpers/__init__.py deleted file mode 100644 index 61cb82d..0000000 --- a/hamcrest/core/helpers/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Utilities for writing Matchers.""" - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/core/helpers/hasmethod.py b/hamcrest/core/helpers/hasmethod.py deleted file mode 100644 index a1f3bfb..0000000 --- a/hamcrest/core/helpers/hasmethod.py +++ /dev/null @@ -1,12 +0,0 @@ -__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) diff --git a/hamcrest/core/helpers/wrap_matcher.py b/hamcrest/core/helpers/wrap_matcher.py deleted file mode 100644 index d1792d6..0000000 --- a/hamcrest/core/helpers/wrap_matcher.py +++ /dev/null @@ -1,19 +0,0 @@ -from 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" - - -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) diff --git a/hamcrest/core/matcher.py b/hamcrest/core/matcher.py deleted file mode 100644 index f76c7bc..0000000 --- a/hamcrest/core/matcher.py +++ /dev/null @@ -1,51 +0,0 @@ -from 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') diff --git a/hamcrest/core/selfdescribing.py b/hamcrest/core/selfdescribing.py deleted file mode 100644 index e77b0e0..0000000 --- a/hamcrest/core/selfdescribing.py +++ /dev/null @@ -1,18 +0,0 @@ -__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') diff --git a/hamcrest/core/selfdescribingvalue.py b/hamcrest/core/selfdescribingvalue.py deleted file mode 100644 index dfa4e3a..0000000 --- a/hamcrest/core/selfdescribingvalue.py +++ /dev/null @@ -1,27 +0,0 @@ -from 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) diff --git a/hamcrest/core/string_description.py b/hamcrest/core/string_description.py deleted file mode 100644 index 7c97488..0000000 --- a/hamcrest/core/string_description.py +++ /dev/null @@ -1,33 +0,0 @@ -from 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 diff --git a/hamcrest/library/__init__.py b/hamcrest/library/__init__.py deleted file mode 100644 index cab67a0..0000000 --- a/hamcrest/library/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -"""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', - 'has_item', - 'has_items', - 'contains_inanyorder', - 'contains', - 'only_contains', - 'match_equality', - 'close_to', - 'greater_than', - 'greater_than_or_equal_to', - 'less_than', - 'less_than_or_equal_to', - 'has_length', - 'has_property', - 'has_string', - 'equal_to_ignoring_case', - 'equal_to_ignoring_whitespace', - 'contains_string', - 'ends_with', - 'starts_with', -] diff --git a/hamcrest/library/collection/__init__.py b/hamcrest/library/collection/__init__.py deleted file mode 100644 index 5aa4ab8..0000000 --- a/hamcrest/library/collection/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Matchers of collections.""" - -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 - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/library/collection/isdict_containing.py b/hamcrest/library/collection/isdict_containing.py deleted file mode 100644 index 9528197..0000000 --- a/hamcrest/library/collection/isdict_containing.py +++ /dev/null @@ -1,54 +0,0 @@ -from 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)) diff --git a/hamcrest/library/collection/isdict_containingentries.py b/hamcrest/library/collection/isdict_containingentries.py deleted file mode 100644 index 6e15ab7..0000000 --- a/hamcrest/library/collection/isdict_containingentries.py +++ /dev/null @@ -1,134 +0,0 @@ -from 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) diff --git a/hamcrest/library/collection/isdict_containingkey.py b/hamcrest/library/collection/isdict_containingkey.py deleted file mode 100644 index ccb51e6..0000000 --- a/hamcrest/library/collection/isdict_containingkey.py +++ /dev/null @@ -1,48 +0,0 @@ -from 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)) diff --git a/hamcrest/library/collection/isdict_containingvalue.py b/hamcrest/library/collection/isdict_containingvalue.py deleted file mode 100644 index e528884..0000000 --- a/hamcrest/library/collection/isdict_containingvalue.py +++ /dev/null @@ -1,48 +0,0 @@ -from 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)) diff --git a/hamcrest/library/collection/isin.py b/hamcrest/library/collection/isin.py deleted file mode 100644 index 87962a2..0000000 --- a/hamcrest/library/collection/isin.py +++ /dev/null @@ -1,30 +0,0 @@ -from 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) diff --git a/hamcrest/library/collection/issequence_containing.py b/hamcrest/library/collection/issequence_containing.py deleted file mode 100644 index 21bde56..0000000 --- a/hamcrest/library/collection/issequence_containing.py +++ /dev/null @@ -1,64 +0,0 @@ -__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): - if hasmethod(sequence, '__iter__'): - for item in sequence: - if self.element_matcher.matches(item): - return True - return False - - def describe_to(self, description): - description.append_text('a sequence containing ') \ - .append_description_of(self.element_matcher) - - -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(has_item(item)) - return apply(all_of, matchers) diff --git a/hamcrest/library/collection/issequence_containinginanyorder.py b/hamcrest/library/collection/issequence_containinginanyorder.py deleted file mode 100644 index 225bb5d..0000000 --- a/hamcrest/library/collection/issequence_containinginanyorder.py +++ /dev/null @@ -1,96 +0,0 @@ -from 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): - index = 0 - for matcher in self.matchers: - if matcher.matches(item): - del self.matchers[index] - return True - index += 1 - 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): - if not hasmethod(sequence, '__iter__'): - if mismatch_description: - super(IsSequenceContainingInAnyOrder, self) \ - .describe_mismatch(sequence, mismatch_description) - return False - matchsequence = MatchInAnyOrder(self.matchers, mismatch_description) - for item in sequence: - if not matchsequence.matches(item): - return False - return matchsequence.isfinished(sequence) - - 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) diff --git a/hamcrest/library/collection/issequence_containinginorder.py b/hamcrest/library/collection/issequence_containinginorder.py deleted file mode 100644 index 779b4a5..0000000 --- a/hamcrest/library/collection/issequence_containinginorder.py +++ /dev/null @@ -1,87 +0,0 @@ -__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): - if not hasmethod(sequence, '__iter__'): - if mismatch_description: - super(IsSequenceContainingInOrder, self) \ - .describe_mismatch(sequence, mismatch_description) - return False - matchsequence = MatchingInOrder(self.matchers, mismatch_description) - for item in sequence: - if not matchsequence.matches(item): - return False - return matchsequence.isfinished() - - 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) diff --git a/hamcrest/library/collection/issequence_onlycontaining.py b/hamcrest/library/collection/issequence_onlycontaining.py deleted file mode 100644 index dbcb116..0000000 --- a/hamcrest/library/collection/issequence_onlycontaining.py +++ /dev/null @@ -1,55 +0,0 @@ -from 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): - if not hasmethod(sequence, '__len__') \ - or not hasmethod(sequence, '__iter__'): - return False - - if len(sequence) == 0: - return False - for item in sequence: - if not self.matcher.matches(item): - return False - return True - - 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)) diff --git a/hamcrest/library/integration/__init__.py b/hamcrest/library/integration/__init__.py deleted file mode 100644 index 873dc06..0000000 --- a/hamcrest/library/integration/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""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" diff --git a/hamcrest/library/integration/match_equality.py b/hamcrest/library/integration/match_equality.py deleted file mode 100644 index 52da054..0000000 --- a/hamcrest/library/integration/match_equality.py +++ /dev/null @@ -1,42 +0,0 @@ -from 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)) diff --git a/hamcrest/library/number/__init__.py b/hamcrest/library/number/__init__.py deleted file mode 100644 index 722a1eb..0000000 --- a/hamcrest/library/number/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -"""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" diff --git a/hamcrest/library/number/iscloseto.py b/hamcrest/library/number/iscloseto.py deleted file mode 100644 index 5a07bb1..0000000 --- a/hamcrest/library/number/iscloseto.py +++ /dev/null @@ -1,61 +0,0 @@ -from 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): - return isinstance(value, (int, long, float)) - - -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) diff --git a/hamcrest/library/number/ordering_comparison.py b/hamcrest/library/number/ordering_comparison.py deleted file mode 100644 index c3c75f4..0000000 --- a/hamcrest/library/number/ordering_comparison.py +++ /dev/null @@ -1,59 +0,0 @@ -from 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') diff --git a/hamcrest/library/object/__init__.py b/hamcrest/library/object/__init__.py deleted file mode 100644 index 92c73dd..0000000 --- a/hamcrest/library/object/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Matchers that inspect objects and classes.""" - -from haslength import has_length -from hasproperty import has_property -from hasstring import has_string - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/library/object/haslength.py b/hamcrest/library/object/haslength.py deleted file mode 100644 index 81245e9..0000000 --- a/hamcrest/library/object/haslength.py +++ /dev/null @@ -1,50 +0,0 @@ -__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 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)) diff --git a/hamcrest/library/object/hasproperty.py b/hamcrest/library/object/hasproperty.py deleted file mode 100644 index fdb11a4..0000000 --- a/hamcrest/library/object/hasproperty.py +++ /dev/null @@ -1,86 +0,0 @@ -from hamcrest.core.base_matcher import BaseMatcher -from hamcrest.core import anything -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)) diff --git a/hamcrest/library/object/hasstring.py b/hamcrest/library/object/hasstring.py deleted file mode 100644 index 81d5556..0000000 --- a/hamcrest/library/object/hasstring.py +++ /dev/null @@ -1,40 +0,0 @@ -__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 - - -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)) diff --git a/hamcrest/library/text/__init__.py b/hamcrest/library/text/__init__.py deleted file mode 100644 index d8352f9..0000000 --- a/hamcrest/library/text/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""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 - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" diff --git a/hamcrest/library/text/isequal_ignoring_case.py b/hamcrest/library/text/isequal_ignoring_case.py deleted file mode 100644 index 95b3cff..0000000 --- a/hamcrest/library/text/isequal_ignoring_case.py +++ /dev/null @@ -1,42 +0,0 @@ -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - -from hamcrest.core.base_matcher import BaseMatcher - - -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) diff --git a/hamcrest/library/text/isequal_ignoring_whitespace.py b/hamcrest/library/text/isequal_ignoring_whitespace.py deleted file mode 100644 index e7086f5..0000000 --- a/hamcrest/library/text/isequal_ignoring_whitespace.py +++ /dev/null @@ -1,56 +0,0 @@ -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - -from hamcrest.core.base_matcher import BaseMatcher - - -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_case("hello world") - - will match ``"hello world"``. - - """ - return IsEqualIgnoringWhiteSpace(string) diff --git a/hamcrest/library/text/stringcontains.py b/hamcrest/library/text/stringcontains.py deleted file mode 100644 index 8f1d456..0000000 --- a/hamcrest/library/text/stringcontains.py +++ /dev/null @@ -1,38 +0,0 @@ -__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 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) diff --git a/hamcrest/library/text/stringcontainsinorder.py b/hamcrest/library/text/stringcontainsinorder.py deleted file mode 100644 index f2c4da9..0000000 --- a/hamcrest/library/text/stringcontainsinorder.py +++ /dev/null @@ -1,51 +0,0 @@ -from 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) diff --git a/hamcrest/library/text/stringendswith.py b/hamcrest/library/text/stringendswith.py deleted file mode 100644 index 43f9c3d..0000000 --- a/hamcrest/library/text/stringendswith.py +++ /dev/null @@ -1,39 +0,0 @@ -from 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) diff --git a/hamcrest/library/text/stringstartswith.py b/hamcrest/library/text/stringstartswith.py deleted file mode 100644 index a0af49c..0000000 --- a/hamcrest/library/text/stringstartswith.py +++ /dev/null @@ -1,39 +0,0 @@ -__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) diff --git a/hamcrest/library/text/substringmatcher.py b/hamcrest/library/text/substringmatcher.py deleted file mode 100644 index abe6445..0000000 --- a/hamcrest/library/text/substringmatcher.py +++ /dev/null @@ -1,19 +0,0 @@ -from 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) diff --git a/hamcrest_unit_test/__init__.py b/hamcrest_unit_test/__init__.py deleted file mode 100644 index 6a4004f..0000000 --- a/hamcrest_unit_test/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -import logging -logging.basicConfig() - -from alltests import alltests - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -def additional_tests(): - return alltests() diff --git a/hamcrest_unit_test/alltests.py b/hamcrest_unit_test/alltests.py deleted file mode 100644 index 8c84e79..0000000 --- a/hamcrest_unit_test/alltests.py +++ /dev/null @@ -1,32 +0,0 @@ -import os -import sys -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - -if __name__ == "__main__": - sys.path.insert(0, '..') - - -def alltests(): - """Returns suite of all tests in this directory and below.""" - testloader = unittest.defaultTestLoader - suite = testloader.suiteClass() - - fullpath = os.path.abspath(os.path.dirname(sys.argv[0])) - for dirpath, dirnames, filenames in os.walk(fullpath): - sys.path.insert(0, dirpath) - for file in filenames: - if file.endswith('test.py'): - (name, ext) = os.path.splitext(file) - module = __import__(name) - suite.addTest(testloader.loadTestsFromModule(module)) - sys.path.pop(0) - - return suite - - -if __name__ == '__main__': - unittest.main(defaultTest='alltests') diff --git a/hamcrest_unit_test/assert_that_test.py b/hamcrest_unit_test/assert_that_test.py deleted file mode 100644 index 4dc793f..0000000 --- a/hamcrest_unit_test/assert_that_test.py +++ /dev/null @@ -1,69 +0,0 @@ -if __name__ == "__main__": - import sys - sys.path.insert(0, '..') - -from hamcrest.core.assert_that import assert_that -from hamcrest.core.core.isequal import equal_to -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class AssertThatTest(unittest.TestCase): - - def testShouldBeSilentOnSuccessfulMatch(self): - assert_that(1, equal_to(1)) - - def testAssertionErrorShouldDescribeExpectedAndActual(self): - expected = 'EXPECTED' - actual = 'ACTUAL' - - expectedMessage = "\nExpected: 'EXPECTED'\n but: was 'ACTUAL'\n" - - try: - assert_that(actual, equal_to(expected)) - except AssertionError, e: - self.assertEqual(expectedMessage, str(e)) - return - self.fail('should have failed') - - def testAssertionErrorShouldIncludeOptionalReason(self): - expected = 'EXPECTED' - actual = 'ACTUAL' - - expectedMessage = "REASON\nExpected: 'EXPECTED'\n but: was 'ACTUAL'\n" - - try: - assert_that(actual, equal_to(expected), 'REASON') - except AssertionError, e: - self.assertEqual(expectedMessage, str(e)) - return - self.fail('should have failed') - - def testCanTestBoolDirectly(self): - assert_that(True, 'should accept True') - - try: - assert_that(False, 'FAILURE REASON') - except AssertionError, e: - self.assertEqual('FAILURE REASON', str(e)) - return - - self.fail('should have failed') - - def testCanTestBoolDirectlyWithoutReason(self): - assert_that(True) - - try: - assert_that(False) - except AssertionError, e: - self.assertEqual('Assertion failed', str(e)) - return - - self.fail('should have failed') - - -if __name__ == "__main__": - unittest.main() diff --git a/hamcrest_unit_test/base_matcher_test.py b/hamcrest_unit_test/base_matcher_test.py deleted file mode 100644 index 137537e..0000000 --- a/hamcrest_unit_test/base_matcher_test.py +++ /dev/null @@ -1,28 +0,0 @@ -if __name__ == "__main__": - import sys - sys.path.insert(0, '..') - -from hamcrest.core.base_matcher import * - -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class TestingBaseMatcher(BaseMatcher): - - def describe_to(self, description): - description.append_text('SOME DESCRIPTION') - - -class BaseMatcherTest(unittest.TestCase): - - def testStrFunctionShouldDescribeMatcher(self): - matcher = TestingBaseMatcher() - self.assertEqual('SOME DESCRIPTION', str(matcher)) - - -if __name__ == "__main__": - unittest.main() diff --git a/hamcrest_unit_test/collection/__init__.py b/hamcrest_unit_test/collection/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hamcrest_unit_test/collection/isdict_containing_test.py b/hamcrest_unit_test/collection/isdict_containing_test.py deleted file mode 100644 index d6c1503..0000000 --- a/hamcrest_unit_test/collection/isdict_containing_test.py +++ /dev/null @@ -1,52 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.isdict_containing import * - -from hamcrest.core.core.isequal import equal_to - -from hamcrest_unit_test.matcher_test import MatcherTest -from quasidict import QuasiDictionary -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsDictContainingTest(MatcherTest): - - def testMatchesDictionaryContainingMatchingKeyAndValue(self): - dict = {'a': 1, 'b': 2} - self.assert_matches('has a:1', has_entry(equal_to('a'), equal_to(1)), dict) - self.assert_matches('has b:2', has_entry(equal_to('b'), equal_to(2)), dict) - self.assert_does_not_match('no c:3', has_entry(equal_to('c'), equal_to(3)), dict) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - dict = {'a': 1, 'b': 2} - self.assert_matches('has a:1', has_entry('a', equal_to(1)), dict) - self.assert_matches('has b:2', has_entry(equal_to('b'), 2), dict) - self.assert_does_not_match('no c:3', has_entry('c', 3), dict) - - def testMatchesAnyConformingDictionary(self): - self.assert_matches('quasi-dictionary', has_entry(1, '1'), QuasiDictionary()) - self.assert_does_not_match('non-dictionary', has_entry(1, '1'), object()) - - def testHasReadableDescription(self): - self.assert_description("a dictionary containing ['a': <1>]", - has_entry('a', 1)) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_entry('a', 1), {'a': 1}) - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", has_entry('a', 1), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", has_entry('a', 1), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/isdict_containingentries_test.py b/hamcrest_unit_test/collection/isdict_containingentries_test.py deleted file mode 100644 index 81da109..0000000 --- a/hamcrest_unit_test/collection/isdict_containingentries_test.py +++ /dev/null @@ -1,125 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.isdict_containingentries import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsDictContainingEntriesTest(MatcherTest): - - def testMatcherCreationRequiresEvenNumberOfPositionalArgs(self): - self.assertRaises(ValueError, has_entries, 'a', 'b', 'c') - - def testDoesNotMatchNonDictionary(self): - self.assert_does_not_match('non-dictionary', - has_entries('a', equal_to(1)), object()) - - def testMatchesDictLike(self): - class DictLike(object): - def __getitem__(self, key): - return 'value: ' + str(key) - def __contains__(self, key): - return True - self.assert_matches('matches a dictionary-like object', - has_entries('a', equal_to('value: a')), - DictLike()) - - def testMatchesUsingSingleDictionaryArgument(self): - target = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('has a & b', - has_entries({'a':equal_to(1), 'b':equal_to(2)}), target) - self.assert_matches('has c & a', - has_entries({'c':equal_to(3), 'a':equal_to(1)}), target) - self.assert_does_not_match('no d:3', - has_entries({'b':equal_to(2), 'd':equal_to(3)}), target) - - def testMatcheSingleDictionaryArgumentWithImplicitEqualTo(self): - target = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('has a & b', - has_entries({'a':1, 'b':2}), target) - self.assert_matches('has c & a', - has_entries({'c':3, 'a':1}), target) - self.assert_does_not_match('no d:3', - has_entries({'b':2, 'd': 3}), target) - - def testMatchesUsingKwargs(self): - target = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('has a & b', - has_entries(a=equal_to(1), b=equal_to(2)), target) - self.assert_matches('has c & a', - has_entries(c=equal_to(3), a=equal_to(1)), target) - self.assert_does_not_match('no d:3', - has_entries(b=equal_to(2), d=equal_to(3)), target) - - def testMatchesKwargsWithImplicitEqualTo(self): - target = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('has a & b', - has_entries(a=1, b=2), target) - self.assert_matches('has c & a', - has_entries(c=3, a=1), target) - self.assert_does_not_match('no d:3', - has_entries(b=2, d=3), target) - - def testMatchesDictionaryContainingSingleKeyWithMatchingValue(self): - target = {'a': 1, 'b': 2} - self.assert_matches('has a:1', has_entries('a', equal_to(1)), target) - self.assert_matches('has b:2', has_entries('b', equal_to(2)), target) - self.assert_does_not_match('no b:3', has_entries('b', equal_to(3)), target) - self.assert_does_not_match('no c:2', has_entries('c', equal_to(2)), target) - - def testMatchesDictionaryContainingMultipleKeysWithMatchingValues(self): - target = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('has a & b', - has_entries('a', equal_to(1), 'b', equal_to(2)), target) - self.assert_matches('has c & a', - has_entries('c', equal_to(3), 'a', equal_to(1)), target) - self.assert_does_not_match('no d:3', - has_entries('b', equal_to(3), 'd', equal_to(3)), target) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - target = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('has a & b', has_entries('a', 1, 'b', 2), target) - self.assert_matches('has c & a', has_entries('c', 3, 'a', 1), target) - self.assert_does_not_match('no d:4', has_entries('b', 3, 'd', 4), target) - - def testHasReadableDescription(self): - self.assert_description("a dictionary containing {'a': <1>, 'b': <2>}", - has_entries('a', 1, 'b', 2)) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_entries('a', 1), {'a': 1}) - - def testMismatchDescriptionOfNonDictionaryShowsActualArgument(self): - self.assert_mismatch_description("'bad' is not a mapping object", has_entries('a', 1), 'bad') - - def testMismatchDescriptionOfDictionaryWithoutKey(self): - self.assert_mismatch_description("no 'b' key in <{'a': 1, 'c': 3}>", - has_entries('a', 1, 'b', 2), {'a': 1, 'c': 3}) - - def testMismatchDescriptionOfDictionaryWithNonMatchingValue(self): - self.assert_mismatch_description("value for 'a' was <2>", - has_entries('a', 1), {'a': 2}) - - def testDescribeMismatchOfNonDictionaryShowsActualArgument(self): - self.assert_describe_mismatch("'bad' is not a mapping object", has_entries('a', 1), 'bad') - - def testDescribeMismatchOfDictionaryWithoutKey(self): - self.assert_describe_mismatch("no 'b' key in <{'a': 1, 'c': 3}>", - has_entries('a', 1, 'b', 2), {'a': 1, 'c': 3}) - - def testDescribeMismatchOfDictionaryWithNonMatchingValue(self): - self.assert_describe_mismatch("value for 'a' was <2>", - has_entries('a', 1), {'a': 2}) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/isdict_containingkey_test.py b/hamcrest_unit_test/collection/isdict_containingkey_test.py deleted file mode 100644 index 9b729fe..0000000 --- a/hamcrest_unit_test/collection/isdict_containingkey_test.py +++ /dev/null @@ -1,58 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.isdict_containingkey import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -from quasidict import QuasiDictionary -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsDictContainingKeyTest(MatcherTest): - - def testMatchesSingletonDictionaryContainingKey(self): - dict = {'a': 1} - self.assert_matches('same single key', has_key(equal_to('a')), dict) - - def testMatchesDictionaryContainingKey(self): - dict = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('Matches a', has_key(equal_to('a')), dict) - self.assert_matches('Matches c', has_key(equal_to('c')), dict) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - dict = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('Matches c', has_key('c'), dict) - - def testDoesNotMatchEmptyDictionary(self): - self.assert_does_not_match('empty', has_key('foo'), {}); - - def testDoesNotMatchDictionaryMissingKey(self): - dict = {'a': 1, 'b': 2, 'c': 3} - self.assert_does_not_match('no matching key', has_key('d'), dict) - - def testMatchesAnyConformingDictionary(self): - self.assert_matches('quasi-dictionary', has_key(1), QuasiDictionary()) - self.assert_does_not_match('non-dictionary', has_key(1), object()) - - def testHasReadableDescription(self): - self.assert_description("a dictionary containing key 'a'", has_key('a')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_key('a'), {'a': 1}) - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", has_key('a'), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", has_key('a'), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/isdict_containingvalue_test.py b/hamcrest_unit_test/collection/isdict_containingvalue_test.py deleted file mode 100644 index 7788484..0000000 --- a/hamcrest_unit_test/collection/isdict_containingvalue_test.py +++ /dev/null @@ -1,58 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.isdict_containingvalue import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -from quasidict import QuasiDictionary -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsDictContainingValueTest(MatcherTest): - - def testMatchesSingletonDictionaryContainingValue(self): - dict = {'a': 1} - self.assert_matches('same single value', has_value(equal_to(1)), dict) - - def testMatchesDictionaryContainingValue(self): - dict = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('Matches 1', has_value(equal_to(1)), dict) - self.assert_matches('Matches 3', has_value(equal_to(3)), dict) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - dict = {'a': 1, 'b': 2, 'c': 3} - self.assert_matches('Matches 3', has_value(3), dict) - - def testDoesNotMatchEmptyDictionary(self): - self.assert_does_not_match('empty', has_value(1), {}); - - def testDoesNotMatchDictionaryMissingValue(self): - dict = {'a': 1, 'b': 2, 'c': 3} - self.assert_does_not_match('no matching value', has_value(4), dict) - - def testMatchesAnyConformingDictionary(self): - self.assert_matches('quasi-dictionary', has_value('1'), QuasiDictionary()) - self.assert_does_not_match('non-dictionary', has_value('1'), object()) - - def testHasReadableDescription(self): - self.assert_description("a dictionary containing value 'a'", has_value('a')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_value(1), {'a': 1}) - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", has_value(1), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", has_value(1), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/isin_test.py b/hamcrest_unit_test/collection/isin_test.py deleted file mode 100644 index 89b69fa..0000000 --- a/hamcrest_unit_test/collection/isin_test.py +++ /dev/null @@ -1,42 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.isin import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -sequence = ('a', 'b', 'c') - -class IsInTest(MatcherTest): - - def testReturnsTrueIfArgumentIsInSequence(self): - matcher = is_in(sequence) - - self.assert_matches('has a', matcher, 'a') - self.assert_matches('has b', matcher, 'b') - self.assert_matches('has c', matcher, 'c') - self.assert_does_not_match('no d', matcher, 'd') - - def testHasReadableDescription(self): - self.assert_description("one of ('a', 'b', 'c')", is_in(sequence)) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(is_in(sequence), 'a') - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", is_in(sequence), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", is_in(sequence), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/issequence_containing_test.py b/hamcrest_unit_test/collection/issequence_containing_test.py deleted file mode 100644 index 35c1251..0000000 --- a/hamcrest_unit_test/collection/issequence_containing_test.py +++ /dev/null @@ -1,97 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.issequence_containing import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -from quasisequence import QuasiSequence -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsSequenceContainingTest(MatcherTest): - - def testMatchesASequenceThatContainsAnElementMatchingTheGivenMatcher(self): - self.assert_matches("sequence contains 'a'", - has_item(equal_to('a')), ['a', 'b', 'c']) - - def testNoMatchIfSequenceDoesntContainAnElementMatchingTheGivenMatcher(self): - self.assert_does_not_match("sequence without 'a'", - has_item(equal_to('a')), ['b', 'c']) - self.assert_does_not_match('empty', has_item(equal_to('a')), []) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches("sequence contains 'a'", - has_item('a'), ['a', 'b', 'c']) - self.assert_does_not_match("sequence without 'a'", - has_item('a'), ['b', 'c']) - - def testMatchesAnyConformingSequence(self): - self.assert_matches('quasi-sequence', has_item(1), QuasiSequence()) - self.assert_does_not_match('non-sequence', has_item(1), object()) - - def testHasAReadableDescription(self): - self.assert_description("a sequence containing 'a'", has_item('a')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_item('a'), ['a', 'b']) - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was <42>", has_item('a'), 42) - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was <42>", has_item('a'), 42) - - -class IsSequenceContainingItemsTest(MatcherTest): - - def testShouldMatchCollectionContainingAllItems(self): - self.assert_matches('contains all items', - has_items(equal_to('a'), equal_to('b'), equal_to('c')), - ('a', 'b', 'c')) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches('Values automatically wrapped with equal_to', - has_items('a', 'b', 'c'), - ('a', 'b', 'c')) - - def testShouldMatchCollectionContainingAllItemsInDifferentOrder(self): - self.assert_matches('all items in different order', - has_items('a', 'b', 'c'), - ('c', 'b', 'a')) - - def testShouldMatchCollectionContainingAllItemsPlusExtras(self): - self.assert_matches('all items plus extras', - has_items('a', 'b', 'c'), - ('e', 'c', 'b', 'a', 'd')) - - def testNoMatchIfCollectionDoesntSatisfyAllMatchers(self): - self.assert_does_not_match("missing 'a'", - has_items('a', 'b', 'c'), - ('e', 'c', 'b', 'd')) - - def testHasAReadableDescription(self): - self.assert_description( - "(a sequence containing 'a' and a sequence containing 'b')", - has_items('a', 'b')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_items('a', 'b'), ['a', 'b']) - - def testMismatchDescriptionShowsFirstUnmetMatcherAndActualArgument(self): - self.assert_mismatch_description("a sequence containing 'a' was <42>", - has_items('a', 'b'), 42) - - def testDescribeMismatch(self): - self.assert_describe_mismatch("a sequence containing 'a' was <42>", - has_items('a', 'b'), 42) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/issequence_containinginanyorder_test.py b/hamcrest_unit_test/collection/issequence_containinginanyorder_test.py deleted file mode 100644 index 07f4d7e..0000000 --- a/hamcrest_unit_test/collection/issequence_containinginanyorder_test.py +++ /dev/null @@ -1,76 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.issequence_containinginanyorder import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -from quasisequence import QuasiSequence -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsSequenceContainingInAnyOrderTest(MatcherTest): - - def testMatchingSingleItemSequence(self): - self.assert_matches("Single item sequence", - contains_inanyorder(equal_to(1)), [1]) - - def testMatchesSequenceInOrder(self): - self.assert_matches("In order", - contains_inanyorder(equal_to(1), equal_to(2)), [1,2]) - - def testMatchesSequenceOutOfOrder(self): - self.assert_matches("Out of order", - contains_inanyorder(equal_to(1), equal_to(2)), - [2,1]) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches("Values automatically wrapped with equal_to", - contains_inanyorder(1,2), [2,1]) - - def testDoesNotMatchEmptySequence(self): - self.assert_mismatch_description("no item matches: <1>, <2> in []", - contains_inanyorder(1, 2), []) - - def testEmptySequenceMatchesEmptySequence(self): - self.assert_matches("Empty sequence", contains_inanyorder(), []) - - def testDoesNotMatchIfOneOfMultipleItemsMismatch(self): - self.assert_mismatch_description("not matched: <4>", - contains_inanyorder(1,2,3), [1,2,4]) - - def testDoesNotMatchWithMoreElementsThanExpected(self): - self.assert_mismatch_description("not matched: <2>", - contains_inanyorder(1,3), [1,2,3]) - - def testDoesNotMatchWithFewerElementsThanExpected(self): - self.assert_mismatch_description( - "no item matches: <4> in [<1>, <2>, <3>]", - contains_inanyorder(1,2,3,4), [1,2,3]) - - def testMatchesAnyConformingSequence(self): - self.assert_matches('quasi-sequence', contains_inanyorder(1,2), - QuasiSequence()) - self.assert_does_not_match('non-sequence', contains_inanyorder(1,2), - object()) - - def testHasAReadableDescription(self): - self.assert_description("a sequence over [<1>, <2>] in any order", - contains_inanyorder(1,2)) - - def testDescribeMismatch(self): - self.assert_describe_mismatch('not matched: <3>', - contains_inanyorder(1,2), [1,3]) - - def testDescribeMismatchOfNonSequence(self): - self.assert_describe_mismatch("was <3>", contains_inanyorder(1,2), 3) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/issequence_containinginorder_test.py b/hamcrest_unit_test/collection/issequence_containinginorder_test.py deleted file mode 100644 index 7f0fba0..0000000 --- a/hamcrest_unit_test/collection/issequence_containinginorder_test.py +++ /dev/null @@ -1,69 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.issequence_containinginorder import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -from quasisequence import QuasiSequence -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsSequenceContainingInOrderTest(MatcherTest): - - def testMatchingSingleItemSequence(self): - self.assert_matches("Single item sequence", contains(equal_to(1)), [1]) - - def testMatchingMultipleItemSequence(self): - self.assert_matches("Multiple item sequence", - contains(equal_to(1), equal_to(2), equal_to(3)), - [1,2,3]) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches("Values automatically wrapped with equal_to", - contains(1, 2, 3), - [1,2,3]) - - def testDoesNotMatchWithMoreElementsThanExpected(self): - self.assert_mismatch_description("Not matched: <4>", - contains(1,2,3), [1,2,3,4]) - - def testDoesNotMatchWithFewerElementsThanExpected(self): - self.assert_mismatch_description("No item matched: <3>", - contains(1,2,3), [1,2]) - - def testDoesNotMatchIfSingleItemMismatches(self): - self.assert_mismatch_description("item 0: was <3>", contains(4), [3]) - - def testDoesNotMatchIfOneOfMultipleItemsMismatch(self): - self.assert_mismatch_description("item 2: was <4>", - contains(1,2,3), [1,2,4]) - - def testDoesNotMatchEmptySequence(self): - self.assert_mismatch_description("No item matched: <4>", - contains(4), []) - - def testEmptySequenceMatchesEmptySequence(self): - self.assert_matches("Empty sequence", contains(), []) - - def testMatchesAnyConformingSequence(self): - self.assert_matches('quasi-sequence', contains(1,2), QuasiSequence()) - self.assert_does_not_match('non-sequence', contains(1,2), object()) - - def testHasAReadableDescription(self): - self.assert_description("a sequence containing [<1>, <2>]", contains(1,2)) - - def testDescribeMismatch(self): - self.assert_describe_mismatch('item 1: was <3>', contains(1,2), [1,3]) - - def testDescribeMismatchOfNonSequence(self): - self.assert_describe_mismatch("was <3>", contains(1,2), 3) - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/issequence_onlycontaining_test.py b/hamcrest_unit_test/collection/issequence_onlycontaining_test.py deleted file mode 100644 index 6dca48e..0000000 --- a/hamcrest_unit_test/collection/issequence_onlycontaining_test.py +++ /dev/null @@ -1,66 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.collection.issequence_onlycontaining import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest.library.number.ordering_comparison import less_than -from hamcrest_unit_test.matcher_test import MatcherTest -from quasisequence import QuasiSequence -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsSequenceOnlyContainingTest(MatcherTest): - - def testMatchesSingletonList(self): - self.assert_matches('singleton list', only_contains(equal_to(1)), [1]) - - def testMatchesAllItemsWithOneMatcher(self): - self.assert_matches('one matcher', - only_contains(less_than(3)), [0, 1, 2]) - - def testMatchesAllItemsWithMultipleMatchers(self): - self.assert_matches('multiple matchers', - only_contains(less_than(3), equal_to(7)), - [0, 7, 1, 2]) - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches('Values automatically wrapped with equal_to', - only_contains(less_than(3), 7), - [0, 7, 1, 2]) - - def testDoesNotMatchListWithMismatchingItem(self): - self.assert_does_not_match('3 is not less than 3', - only_contains(less_than(3)), [1, 2, 3]) - - def testDoesNotMatchEmptyList(self): - self.assert_does_not_match('empty', only_contains('foo'), []) - - def testMatchesAnyConformingSequence(self): - class ObjectWithLenOnly: - def __len__(self): return 20 - self.assert_matches('quasi-sequence', - only_contains(less_than(3)), QuasiSequence()) - self.assert_does_not_match('non-sequence', only_contains(1), object()) - self.assert_does_not_match('non-sequence with length', - only_contains(1), ObjectWithLenOnly()) - - def testHasAReadableDescription(self): - self.assert_description('a sequence containing items matching (<1> or <2>)', - only_contains(1,2)) - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", only_contains(1,2), 'bad') - - def testDescribeMismatchOfNonSequence(self): - self.assert_describe_mismatch("was <3>", only_contains(1,2), 3) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/collection/quasidict.py b/hamcrest_unit_test/collection/quasidict.py deleted file mode 100644 index 8258e7f..0000000 --- a/hamcrest_unit_test/collection/quasidict.py +++ /dev/null @@ -1,44 +0,0 @@ -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class QuasiDictionary: - def items(self): - return QuasiDictionaryItemIterator() - - def keys(self): - return QuasiDictionaryKeyIterator() - - def values(self): - return QuasiDictionaryValueIterator() - - -class BaseQuasiDictionaryIterator: - def __init__(self): - self.index = 1 - - def __iter__(self): - return self - - def next(self): - if self.index >= 3: - raise StopIteration - result = self.indexToResult() - self.index += 1 - return result - - -class QuasiDictionaryItemIterator(BaseQuasiDictionaryIterator): - def indexToResult(self): - return (self.index, str(self.index)) - - -class QuasiDictionaryKeyIterator(BaseQuasiDictionaryIterator): - def indexToResult(self): - return self.index - - -class QuasiDictionaryValueIterator(BaseQuasiDictionaryIterator): - def indexToResult(self): - return str(self.index) diff --git a/hamcrest_unit_test/collection/quasisequence.py b/hamcrest_unit_test/collection/quasisequence.py deleted file mode 100644 index 36590d6..0000000 --- a/hamcrest_unit_test/collection/quasisequence.py +++ /dev/null @@ -1,26 +0,0 @@ -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class QuasiSequence: - def __iter__(self): - return QuasiSequenceIterator() - - def __len__(self): - return 2 - - -class QuasiSequenceIterator: - def __init__(self): - self.index = 1 - - def __iter__(self): - return self - - def next(self): - if self.index >= 3: - raise StopIteration - result = self.index - self.index += 1 - return result diff --git a/hamcrest_unit_test/core/__init__.py b/hamcrest_unit_test/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hamcrest_unit_test/core/allof_test.py b/hamcrest_unit_test/core/allof_test.py deleted file mode 100644 index 1f9c33d..0000000 --- a/hamcrest_unit_test/core/allof_test.py +++ /dev/null @@ -1,82 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.allof import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class AllOfTest(MatcherTest): - - def testMatchesIfArgumentSatisfiesBothOfTwoOtherMatchers(self): - self.assert_matches('both matchers', - all_of(equal_to('good'), equal_to('good')), - 'good') - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches('both matchers', - all_of('good', 'good'), - 'good') - - def testNoMatchIfArgumentFailsToSatisfyEitherOfTwoOtherMatchers(self): - self.assert_does_not_match('first matcher', - all_of(equal_to('bad'), equal_to('good')), - 'good') - self.assert_does_not_match('second matcher', - all_of(equal_to('good'), equal_to('bad')), - 'good') - self.assert_does_not_match('either matcher', - all_of(equal_to('bad'), equal_to('bad')), - 'good') - - def testMatchesIfArgumentSatisfiesAllOfManyOtherMatchers(self): - self.assert_matches('all matchers', - all_of(equal_to('good'), - equal_to('good'), - equal_to('good'), - equal_to('good'), - equal_to('good')), - 'good') - - def testNoMatchIfArgumentFailsToSatisfyAllOfManyOtherMatchers(self): - self.assert_does_not_match('matcher in the middle', - all_of(equal_to('good'), - equal_to('good'), - equal_to('good'), - equal_to('bad'), - equal_to('good'), - equal_to('good')), - 'good') - - def testHasAReadableDescription(self): - self.assert_description("('good' and 'bad' and 'ugly')", - all_of(equal_to('good'), equal_to('bad'), equal_to('ugly'))) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description( - all_of(equal_to('good'), equal_to('good')), - 'good') - - def testMismatchDescriptionDescribesFirstFailingMatch(self): - self.assert_mismatch_description( - "'good' was 'bad'", - all_of(equal_to('bad'), equal_to('good')), - 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch( - "'good' was 'bad'", - all_of(equal_to('bad'), equal_to('good')), - 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/anyof_test.py b/hamcrest_unit_test/core/anyof_test.py deleted file mode 100644 index b9555eb..0000000 --- a/hamcrest_unit_test/core/anyof_test.py +++ /dev/null @@ -1,87 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.anyof import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class AnyOfTest(MatcherTest): - - def testMatchesIfArgumentSatisfiesEitherOrBothOfTwoOtherMatchers(self): - self.assert_matches('first matcher', - any_of(equal_to('good'), equal_to('bad')), - 'good') - self.assert_matches('second matcher', - any_of(equal_to('bad'), equal_to('good')), - 'good') - self.assert_matches('both matchers', - any_of(equal_to('good'), equal_to('good')), - 'good') - - def testProvidesConvenientShortcutForMatchingWithEqualTo(self): - self.assert_matches('first matcher', - any_of('good', 'bad'), - 'good') - self.assert_matches('second matcher', - any_of('bad', 'good'), - 'good') - self.assert_matches('both matchers', - any_of('good', 'good'), - 'good') - - def testNoMatchIfArgumentFailsToSatisfyEitherOfTwoOtherMatchers(self): - self.assert_does_not_match('either matcher', - any_of(equal_to('bad'), equal_to('bad')), - 'good') - - def testMatchesIfArgumentSatisfiesAnyOfManyOtherMatchers(self): - self.assert_matches('matcher in the middle', - any_of(equal_to('bad'), - equal_to('bad'), - equal_to('good'), - equal_to('bad'), - equal_to('bad')), - 'good') - - def testNoMatchIfArgumentFailsToSatisfyAnyOfManyOtherMatchers(self): - self.assert_does_not_match('all matchers', - any_of(equal_to('bad'), - equal_to('bad'), - equal_to('bad'), - equal_to('bad'), - equal_to('bad')), - 'good') - - def testHasAReadableDescription(self): - self.assert_description("('good' or 'bad' or 'ugly')", - any_of(equal_to('good'), equal_to('bad'), equal_to('ugly'))) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description( - any_of(equal_to('good'), equal_to('bad')), - 'good') - - def testMismatchDescriptionDescribesFirstFailingMatch(self): - self.assert_mismatch_description( - "was 'ugly'", - any_of(equal_to('bad'), equal_to('good')), - 'ugly') - - def testDescribeMismatch(self): - self.assert_describe_mismatch( - "was 'ugly'", - any_of(equal_to('bad'), equal_to('good')), - 'ugly') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/described_as_test.py b/hamcrest_unit_test/core/described_as_test.py deleted file mode 100644 index a43fc8e..0000000 --- a/hamcrest_unit_test/core/described_as_test.py +++ /dev/null @@ -1,58 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.described_as import * - -from hamcrest.core.core.isanything import anything -from hamcrest_unit_test.matcher_test import MatcherTest -from nevermatch import NeverMatch -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class DescribedAsTest(MatcherTest): - - def testOverridesDescriptionOfNestedMatcherWithConstructorArgument(self): - m1 = described_as('m1 description', anything()) - m2 = described_as('m2 description', NeverMatch()) - - self.assert_description('m1 description', m1) - self.assert_description('m2 description', m2) - - def testAppendsValuesToDescription(self): - m = described_as('value 1 = %0, value 2 = %1', anything(), 33, 97) - - self.assert_description('value 1 = <33>, value 2 = <97>', m) - - def testDelegatesMatchingToNestedMatcher(self): - m1 = described_as('irrelevant', anything()) - m2 = described_as('irrelevant', NeverMatch()) - - self.assertTrue(m1.matches(object())) - self.assertTrue(not m2.matches('hi')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description( - described_as('irrelevant', anything()), - object()) - - def testDelegatesMismatchDescriptionToNestedMatcher(self): - self.assert_mismatch_description( - NeverMatch.mismatch_description, - described_as('irrelevant', NeverMatch()), - 'hi') - - def testDelegatesDescribeMismatchToNestedMatcher(self): - self.assert_describe_mismatch( - NeverMatch.mismatch_description, - described_as('irrelevant', NeverMatch()), - 'hi') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/is_test.py b/hamcrest_unit_test/core/is_test.py deleted file mode 100644 index 634e472..0000000 --- a/hamcrest_unit_test/core/is_test.py +++ /dev/null @@ -1,57 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.is_ import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -from nevermatch import NeverMatch -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsTest(MatcherTest): - - def testDelegatesMatchingToNestedMatcher(self): - self.assert_matches('should match', is_(equal_to(True)), True) - self.assert_matches('should match', is_(equal_to(False)), False) - self.assert_does_not_match('should not match', is_(equal_to(True)), False) - self.assert_does_not_match('should not match', is_(equal_to(False)), True) - - def testDescriptionShouldPassThrough(self): - self.assert_description('', is_(equal_to(True))) - - def testProvidesConvenientShortcutForIsEqualTo(self): - self.assert_matches('should match', is_('A'), 'A'); - self.assert_matches('should match', is_('B'), 'B'); - self.assert_does_not_match('should not match', is_('A'), 'B'); - self.assert_does_not_match('should not match', is_('B'), 'A'); - self.assert_description("'A'", is_('A')); - - def testProvidesConvenientShortcutForIsInstanceOf(self): - self.assert_matches('should match', is_(str), 'A'); - self.assert_does_not_match('should not match', is_(int), 'A'); - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(is_('A'), 'A') - - def testDelegatesMismatchDescriptionToNestedMatcher(self): - self.assert_mismatch_description( - NeverMatch.mismatch_description, - is_(NeverMatch()), - 'hi') - - def testDelegatesDescribeMismatchToNestedMatcher(self): - self.assert_describe_mismatch( - NeverMatch.mismatch_description, - is_(NeverMatch()), - 'hi') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/isanything_test.py b/hamcrest_unit_test/core/isanything_test.py deleted file mode 100644 index 9d6f7ad..0000000 --- a/hamcrest_unit_test/core/isanything_test.py +++ /dev/null @@ -1,35 +0,0 @@ -if __name__ == "__main__": - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.isanything import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsAnythingTest(MatcherTest): - - def testAlwaysEvaluatesToTrue(self): - self.assert_matches('None', anything(), None) - self.assert_matches('object', anything(), object()) - self.assert_matches('string', anything(), 'hi') - - def testHasUsefulDefaultDescription(self): - self.assert_description('ANYTHING', anything()) - - def testCanOverrideDescription(self): - description = 'DESCRIPTION' - self.assert_description(description, anything(description)) - - def testMatchAlwaysSucceedsSoShouldNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(anything(), 'hi') - - -if __name__ == "__main__": - unittest.main() diff --git a/hamcrest_unit_test/core/isequal_test.py b/hamcrest_unit_test/core/isequal_test.py deleted file mode 100644 index 8ded988..0000000 --- a/hamcrest_unit_test/core/isequal_test.py +++ /dev/null @@ -1,57 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.isequal import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsEqualTest(MatcherTest): - - def testComparesObjectsUsingEquality(self): - self.assert_matches('equal numbers', equal_to(1), 1) - self.assert_does_not_match('unequal numbers', equal_to(1), 2) - - def testCanCompareNoneValues(self): - self.assert_matches('None equals None', equal_to(None), None) - - self.assert_does_not_match('None as argument', equal_to('hi'), None) - self.assert_does_not_match('None in equal_to', equal_to(None), 'hi') - - def testHonorsArgumentEqImplementationEvenWithNone(self): - class AlwaysEqual: - def __eq__(self, obj): return True - class NeverEqual: - def __eq__(self, obj): return False - self.assert_matches("always equal", equal_to(None), AlwaysEqual()) - self.assert_does_not_match("never equal", equal_to(None), NeverEqual()) - - def testIncludesTheResultOfCallingToStringOnItsArgumentInTheDescription(self): - argument_description = 'ARGUMENT DESCRIPTION' - class Argument: - def __str__(self): return argument_description - self.assert_description('', equal_to(Argument())) - - def testReturnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake(self): - inner_matcher = equal_to('NestedMatcher') - self.assert_description("<'NestedMatcher'>", equal_to(inner_matcher)) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(equal_to('hi'), 'hi') - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", equal_to('good'), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", equal_to('good'), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/isinstanceof_test.py b/hamcrest_unit_test/core/isinstanceof_test.py deleted file mode 100644 index 57601b5..0000000 --- a/hamcrest_unit_test/core/isinstanceof_test.py +++ /dev/null @@ -1,41 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.isinstanceof import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsInstanceOfTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentIsInstanceOfASpecificClass(self): - self.assert_matches('same class', instance_of(int), 1) - - self.assert_does_not_match('different class', instance_of(int), 'hi') - self.assert_does_not_match('None', instance_of(int), None) - - def testMatcherCreationRequiresType(self): - self.assertRaises(TypeError, instance_of, 'not a type') - - def testHasAReadableDescription(self): - self.assert_description('an instance of int', instance_of(int)); - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(instance_of(int), 3) - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", instance_of(int), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", instance_of(int), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/isnone_test.py b/hamcrest_unit_test/core/isnone_test.py deleted file mode 100644 index 1a023a0..0000000 --- a/hamcrest_unit_test/core/isnone_test.py +++ /dev/null @@ -1,59 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.isnone import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsNoneTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentIsNone(self): - self.assert_matches('None', none(), None) - - def testEvaluatesToFalseIfArgumentIsNotNone(self): - self.assert_does_not_match('not None', none(), object()) - - def testHasAReadableDescription(self): - self.assert_description('None', none()); - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(none(), None) - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'bad'", none(), 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", none(), 'bad') - - -class NotNoneTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentIsNotNone(self): - self.assert_matches('not None', not_none(), object()) - - def testEvaluatesToFalseIfArgumentIsNone(self): - self.assert_does_not_match('None', not_none(), None) - - def testHasAReadableDescription(self): - self.assert_description('not None', not_none()); - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(not_none(), 'hi') - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was ", not_none(), None) - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was ", not_none(), None) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/isnot_test.py b/hamcrest_unit_test/core/isnot_test.py deleted file mode 100644 index 5eb633a..0000000 --- a/hamcrest_unit_test/core/isnot_test.py +++ /dev/null @@ -1,41 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.isnot import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsNotTest(MatcherTest): - - def testEvaluatesToTheTheLogicalNegationOfAnotherMatcher(self): - self.assert_matches('invert mismatch', is_not(equal_to('A')), 'B') - self.assert_does_not_match('invert match', is_not(equal_to('A')), 'A') - - def testProvidesConvenientShortcutForNotEqualTo(self): - self.assert_matches('invert mismatch', is_not('A'), 'B'); - self.assert_does_not_match('invert match', is_not('A'), 'A'); - - def testHasAReadableDescription(self): - self.assert_description("not 'A'", is_not('A')); - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(is_not('A'), 'B') - - def testMismatchDescriptionShowsActualArgument(self): - self.assert_mismatch_description("was 'A'", is_not('A'), 'A') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'A'", is_not('A'), 'A') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/issame_test.py b/hamcrest_unit_test/core/issame_test.py deleted file mode 100644 index 26a03b6..0000000 --- a/hamcrest_unit_test/core/issame_test.py +++ /dev/null @@ -1,64 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.core.core.issame import * - -from hamcrest.core.string_description import StringDescription -from hamcrest_unit_test.matcher_test import MatcherTest -import re -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsSameTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentIsReferenceToASpecifiedObject(self): - o1 = object() - o2 = object() - - self.assert_matches('same', same_instance(o1), o1) - self.assert_does_not_match('different', same_instance(o1), o2) - - def testDescriptionIncludesMemoryAddress(self): - description = StringDescription() - expected = re.compile("same instance as 0x[0-9a-fA-F]+ 'abc'") - - description.append_description_of(same_instance('abc')); - self.assertTrue(expected.match(str(description))) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - o1 = object() - self.assert_no_mismatch_description(same_instance(o1), o1) - - def testMismatchDescriptionShowsActualArgumentAddress(self): - matcher = same_instance('foo') - description = StringDescription() - expected = re.compile("was 0x[0-9a-fA-F]+ 'hi'") - - result = matcher.matches('hi', description) - self.assertFalse(result, 'Precondition: Matcher should not match item') - self.assertTrue(expected.match(str(description))) - - def testMismatchDescriptionWithNilShouldNotIncludeAddress(self): - self.assert_mismatch_description("was ", same_instance('foo'), None) - - def testDescribeMismatch(self): - matcher = same_instance('foo') - description = StringDescription() - expected = re.compile("was 0x[0-9a-fA-F]+ 'hi'") - - matcher.describe_mismatch('hi', description) - expected = re.compile("was 0x[0-9a-fA-F]+ 'hi'") - self.assertTrue(expected.match(str(description))) - - def testDescribeMismatchWithNilShouldNotIncludeAddress(self): - self.assert_describe_mismatch("was ", same_instance('foo'), None) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/core/nevermatch.py b/hamcrest_unit_test/core/nevermatch.py deleted file mode 100644 index 8c931a2..0000000 --- a/hamcrest_unit_test/core/nevermatch.py +++ /dev/null @@ -1,18 +0,0 @@ -from hamcrest.core.base_matcher import BaseMatcher - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class NeverMatch(BaseMatcher): - - mismatch_description = 'NEVERMATCH' - - def matches(self, item, mismatch_description=None): - if mismatch_description: - self.describe_mismatch(item, mismatch_description) - return False - - def describe_mismatch(self, item, mismatch_description): - mismatch_description.append_text(NeverMatch.mismatch_description) diff --git a/hamcrest_unit_test/integration/__init__.py b/hamcrest_unit_test/integration/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hamcrest_unit_test/integration/match_equality_test.py b/hamcrest_unit_test/integration/match_equality_test.py deleted file mode 100644 index ed21512..0000000 --- a/hamcrest_unit_test/integration/match_equality_test.py +++ /dev/null @@ -1,40 +0,0 @@ -if __name__ == "__main__": - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.integration.match_equality import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest.core.string_description import tostring -import unittest - -__author__ = "Chris Rose" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class MatchEqualityWrapperTest(unittest.TestCase): - - def testMatcherIsEqualWhenMatchesIsTrue(self): - matcher = equal_to('bar') - assert match_equality(matcher) == 'bar' - - def testMatcherIsNotEqualWhenMatchesIsFalse(self): - matcher = equal_to('bar') - assert match_equality(matcher) != 'foo' - - def testMatcherStringIsMatcherDescription(self): - matcher = equal_to('bar') - assert str(match_equality(matcher)) == tostring(matcher) - - def testMatcherReprIsMatcher(self): - matcher = equal_to('bar') - assert repr(match_equality(matcher)) == tostring(matcher) - - def testMatchesWhenProvidedAnObject(self): - assert match_equality('bar') == 'bar' - - -if __name__ == "__main__": - unittest.main() diff --git a/hamcrest_unit_test/matcher_test.py b/hamcrest_unit_test/matcher_test.py deleted file mode 100644 index a56db4c..0000000 --- a/hamcrest_unit_test/matcher_test.py +++ /dev/null @@ -1,48 +0,0 @@ -from hamcrest.core.string_description import StringDescription - -import unittest -import logging - -log = logging.getLogger(__name__) - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class MatcherTest(unittest.TestCase): - - def assert_matches(self, message, matcher, arg): - try: - self.assertTrue(matcher.matches(arg), message) - except AssertionError: - description = StringDescription() - matcher.describe_mismatch(arg, description) - log.error(str(description)) - raise - - def assert_does_not_match(self, message, matcher, arg): - self.assertFalse(matcher.matches(arg), message) - - def assert_description(self, expected, matcher): - description = StringDescription() - description.append_description_of(matcher); - self.assertEqual(expected, str(description)) - - def assert_no_mismatch_description(self, matcher, arg): - description = StringDescription() - result = matcher.matches(arg, description) - self.assertTrue(result, 'Precondition: Matcher should match item') - self.assertEqual('', str(description), - 'Expected no mismatch description') - - def assert_mismatch_description(self, expected, matcher, arg): - description = StringDescription() - result = matcher.matches(arg, description) - self.assertFalse(result, 'Precondition: Matcher should not match item') - self.assertEqual(expected, str(description)) - - def assert_describe_mismatch(self, expected, matcher, arg): - description = StringDescription() - matcher.describe_mismatch(arg, description) - self.assertEqual(expected, str(description)) diff --git a/hamcrest_unit_test/number/__init__.py b/hamcrest_unit_test/number/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hamcrest_unit_test/number/iscloseto_test.py b/hamcrest_unit_test/number/iscloseto_test.py deleted file mode 100644 index b5b39c6..0000000 --- a/hamcrest_unit_test/number/iscloseto_test.py +++ /dev/null @@ -1,62 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.number.iscloseto import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class IsCloseToTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentIsEqualToAValueWithinSomeError(self): - matcher = close_to(1.0, 0.5) - - self.assert_matches('equal', matcher, 1.0) - self.assert_matches('less but within delta', matcher, 0.5) - self.assert_matches('greater but within delta', matcher, 1.5) - - self.assert_does_not_match('too small', matcher, 0.4) - self.assert_does_not_match('too large', matcher, 1.6) - - def testMatcherCreationAcceptsOtherNumericTypes(self): - close_to(5, 1) - close_to(5L, 1L) - - def testMatcherCreationRequiresNumbers(self): - self.assertRaises(TypeError, close_to, 'a', 0.5) - self.assertRaises(TypeError, close_to, 1.0, 'a') - - def testFailsIfMatchingAgainstNonNumber(self): - self.assert_does_not_match('not a number', close_to(1.0, 0.5), 'a') - - def testHasAReadableDescription(self): - self.assert_description('a numeric value within <0.5> of <1.0>', - close_to(1.0, 0.5)) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(close_to(1.0, 0.5), 1.0) - - def testMismatchDescriptionShowsActualDeltaIfArgumentIsNumeric(self): - self.assert_mismatch_description('<1.7> differed by <0.7>', - close_to(1.0, 0.5), 1.7) - - def testMismatchDescriptionShowsActualArgumentIfNotNumeric(self): - self.assert_mismatch_description("was 'bad'", close_to(1.0, 0.5), 'bad') - - def testDescribeMismatchShowsActualDeltaIfArgumentIsNumeric(self): - self.assert_describe_mismatch('<1.7> differed by <0.7>', - close_to(1.0, 0.5), 1.7) - - def testDescribeMismatchShowsActualArgumentIfNotNumeric(self): - self.assert_describe_mismatch("was 'bad'", close_to(1.0, 0.5), 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/number/ordering_comparison_test.py b/hamcrest_unit_test/number/ordering_comparison_test.py deleted file mode 100644 index fa88605..0000000 --- a/hamcrest_unit_test/number/ordering_comparison_test.py +++ /dev/null @@ -1,72 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.number.ordering_comparison import * - -from datetime import date -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class OrderingComparisonTest(MatcherTest): - - def testComparesObjectsForGreaterThan(self): - self.assert_matches('match', greater_than(1), 2) - self.assert_does_not_match('no match', greater_than(1), 1) - - def testComparesObjectsForLessThan(self): - self.assert_matches('match', less_than(1), 0) - self.assert_does_not_match('no match', less_than(1), 1) - - def testComparesObjectsForGreaterThanOrEqualTo(self): - self.assert_matches('match', greater_than_or_equal_to(1), 2) - self.assert_matches('match', greater_than_or_equal_to(1), 1) - self.assert_does_not_match('no match', greater_than_or_equal_to(1), 0) - - def testComparesObjectsForLessThanOrEqualTo(self): - self.assert_matches('match', less_than_or_equal_to(1), 0) - self.assert_matches('match', less_than_or_equal_to(1), 1) - self.assert_does_not_match('no match', less_than_or_equal_to(1), 2) - - def testSupportsDifferentTypesOfComparableObjects(self): - self.assert_matches('strings', greater_than('bb'), 'cc') - self.assert_matches('dates', less_than(date.today()), date.min) - - def testHasAReadableDescription(self): - self.assert_description('a value greater than <1>', greater_than(1)) - self.assert_description('a value greater than or equal to <1>', - greater_than_or_equal_to(1)) - self.assert_description('a value less than <1>', less_than(1)) - self.assert_description('a value less than or equal to <1>', - less_than_or_equal_to(1)) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(greater_than(1), 2) - self.assert_no_mismatch_description(less_than(1), 0) - self.assert_no_mismatch_description(greater_than_or_equal_to(1), 1) - self.assert_no_mismatch_description(less_than_or_equal_to(1), 1) - - def testMismatchDescription(self): - self.assert_mismatch_description("was <0>", greater_than(1), 0) - self.assert_mismatch_description("was <2>", less_than(1), 2) - self.assert_mismatch_description("was <0>", - greater_than_or_equal_to(1), 0) - self.assert_mismatch_description("was <2>", - less_than_or_equal_to(1), 2) - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was <0>", greater_than(1), 0) - self.assert_describe_mismatch("was <2>", less_than(1), 2) - self.assert_describe_mismatch("was <0>", - greater_than_or_equal_to(1), 0) - self.assert_describe_mismatch("was <2>", less_than_or_equal_to(1), 2) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/object/__init__.py b/hamcrest_unit_test/object/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hamcrest_unit_test/object/haslength_test.py b/hamcrest_unit_test/object/haslength_test.py deleted file mode 100644 index 8ead544..0000000 --- a/hamcrest_unit_test/object/haslength_test.py +++ /dev/null @@ -1,76 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.object.haslength import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest.library.number.ordering_comparison import greater_than -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class FakeWithLen(object): - - def __init__(self, len): - self.len = len - - def __len__(self): - return self.len - - def __str__(self): - return 'FakeWithLen' - - -class FakeWithoutLen(object): - - def __str__(self): - return 'FakeWithoutLen' - - -class HasLengthTest(MatcherTest): - - def testPassesResultOfLenToNestedMatcher(self): - self.assert_matches('equal', has_length(equal_to(42)), FakeWithLen(42)) - self.assert_does_not_match('unequal', - has_length(equal_to(42)), FakeWithLen(1)) - - def testProvidesConvenientShortcutForHasLengthEqualTo(self): - self.assert_matches('equal', has_length(42), FakeWithLen(42)) - self.assert_does_not_match('unequal', has_length(42), FakeWithLen(1)) - - def testDoesNotMatchObjectWithoutLen(self): - self.assert_does_not_match('no length', has_length(42), object()) - - def testHasReadableDescription(self): - self.assert_description('an object with length of a value greater than <5>', - has_length(greater_than(5))) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_length(3), 'foo') - - def testMismatchDescriptionForItemWithWrongLength(self): - self.assert_mismatch_description('was with length of <4>', - has_length(3), FakeWithLen(4)) - - def testMismatchDescriptionForItemWithoutLength(self): - self.assert_mismatch_description("was ", - has_length(3), FakeWithoutLen()) - - def testDescribeMismatchForItemWithWrongLength(self): - self.assert_describe_mismatch('was with length of <4>', - has_length(3), FakeWithLen(4)) - - def testDescribeMismatchForItemWithoutLength(self): - self.assert_describe_mismatch("was ", - has_length(3), FakeWithoutLen()) - - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/object/hasproperty_test.py b/hamcrest_unit_test/object/hasproperty_test.py deleted file mode 100644 index 3e824de..0000000 --- a/hamcrest_unit_test/object/hasproperty_test.py +++ /dev/null @@ -1,127 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') -import sys -print '\n'.join(sys.path) - -from hamcrest.library.object.hasproperty import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Chris Rose" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - -class OnePropertyOldStyle: - - field = 'value' - -class OnePropertyNewStyle(object): - - field = 'value' - - def __repr__(self): - return 'OnePropertyNewStyle' - - def __str__(self): - return repr(self) - -class OverridingOldStyle: - - def __getattr__(self, name): - if name != 'field': - raise AttributeError(name) - return 'value' - -class OverridingNewStyleGetAttr(object): - - def __getattr__(self, name): - if name != 'field': - raise AttributeError(name) - return 'value' - -class OverridingNewStyleGetAttribute(object): - - def __getattr__(self, name): - if name != 'field': - raise AttributeError(name) - return 'value' - -class HasPropertyTest(MatcherTest): - - def testHasPropertyWithoutValueMatcher(self): - self.assert_matches('old-style direct', - has_property('field'), OnePropertyOldStyle()) - self.assert_matches('old-style direct', - has_property('field'), OnePropertyNewStyle()) - self.assert_matches('old-style direct', - has_property('field'), OverridingOldStyle()) - self.assert_matches('old-style direct', - has_property('field'), OverridingNewStyleGetAttr()) - self.assert_matches('old-style direct', - has_property('field'), OverridingNewStyleGetAttribute()) - - def testHasPropertyWithoutValueMatcherNegative(self): - self.assert_does_not_match('old-style direct', - has_property('not_there'), OnePropertyOldStyle()) - self.assert_does_not_match('old-style direct', - has_property('not_there'), OnePropertyNewStyle()) - self.assert_does_not_match('old-style direct', - has_property('not_there'), OverridingOldStyle()) - self.assert_does_not_match('old-style direct', - has_property('not_there'), OverridingNewStyleGetAttr()) - self.assert_does_not_match('old-style direct', - has_property('not_there'), OverridingNewStyleGetAttribute()) - - def testHasPropertyWithValueMatcher(self): - self.assert_matches('old-style direct', - has_property('field', 'value'), OnePropertyOldStyle()) - self.assert_matches('old-style direct', - has_property('field', 'value'), OnePropertyNewStyle()) - self.assert_matches('old-style direct', - has_property('field', 'value'), OverridingOldStyle()) - self.assert_matches('old-style direct', - has_property('field', 'value'), OverridingNewStyleGetAttr()) - self.assert_matches('old-style direct', - has_property('field', 'value'), OverridingNewStyleGetAttribute()) - - def testHasPropertyWithValueMatcherNegative(self): - self.assert_does_not_match('old-style direct', - has_property('field', 'not the value'), OnePropertyOldStyle()) - self.assert_does_not_match('old-style direct', - has_property('field', 'not the value'), OnePropertyNewStyle()) - self.assert_does_not_match('old-style direct', - has_property('field', 'not the value'), OverridingOldStyle()) - self.assert_does_not_match('old-style direct', - has_property('field', 'not the value'), OverridingNewStyleGetAttr()) - self.assert_does_not_match('old-style direct', - has_property('field', 'not the value'), OverridingNewStyleGetAttribute()) - - def testDescription(self): - self.assert_description("an object with a property 'field' matching ANYTHING", - has_property('field')) - self.assert_description("an object with a property 'field' matching 'value'", - has_property('field', 'value')) - - def testDescribeMissingProperty(self): - self.assert_mismatch_description(" did not have the 'not_there' property", - has_property('not_there'), OnePropertyNewStyle()) - - def testDescribePropertyValueMismatch(self): - self.assert_mismatch_description("property 'field' was 'value'", - has_property('field', 'another_value'), OnePropertyNewStyle()) - - def testMismatchDescription(self): - self.assert_describe_mismatch(" did not have the 'not_there' property", - has_property('not_there'), - OnePropertyNewStyle()) - - def testNoMismatchDescriptionOnMatch(self): - self.assert_no_mismatch_description(has_property('field', 'value'), OnePropertyNewStyle()) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/object/hasstring_test.py b/hamcrest_unit_test/object/hasstring_test.py deleted file mode 100644 index 7381cd2..0000000 --- a/hamcrest_unit_test/object/hasstring_test.py +++ /dev/null @@ -1,52 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.object.hasstring import * - -from hamcrest.core.core.isequal import equal_to -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class FakeWithStr(object): - - def __str__(self): - return 'FakeWithStr' - - -class HasStringTest(MatcherTest): - - def testPassesResultOfToStrToNestedMatcher(self): - self.assert_matches('equal', - has_string(equal_to('FakeWithStr')), FakeWithStr()) - self.assert_does_not_match('unequal', - has_string(equal_to('FakeWithStr')), 3) - - def testProvidesConvenientShortcutForHasStringEqualTo(self): - self.assert_matches('equal', has_string('FakeWithStr'), FakeWithStr()) - self.assert_does_not_match('unequal', has_string('FakeWithStr'), 3) - - def testHasReadableDescription(self): - self.assert_description("an object with str 'foo'", has_string('foo')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(has_string('FakeWithStr'), - FakeWithStr()) - - def testMismatchDescription(self): - self.assert_mismatch_description("was ", - has_string('foo'), FakeWithStr()) - - def testDescribeMismatchDescription(self): - self.assert_describe_mismatch("was ", - has_string('foo'), FakeWithStr()) - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/object_import.py b/hamcrest_unit_test/object_import.py deleted file mode 100644 index 31929ae..0000000 --- a/hamcrest_unit_test/object_import.py +++ /dev/null @@ -1,8 +0,0 @@ -from hamcrest import * - -try: - class MyTest(object): - pass -except TypeError: - print 'Object class defined at ' + getattr(object, '__file__', 'NOWHERE') - raise diff --git a/hamcrest_unit_test/string_description_test.py b/hamcrest_unit_test/string_description_test.py deleted file mode 100644 index 1ea9b09..0000000 --- a/hamcrest_unit_test/string_description_test.py +++ /dev/null @@ -1,58 +0,0 @@ -import sys -if __name__ == "__main__": - sys.path.insert(0, '..') - -from hamcrest.core.string_description import * - -from hamcrest.core.selfdescribing import SelfDescribing -import re -try: - import unittest2 as unittest -except ImportError: - import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -class FakeSelfDescribing(SelfDescribing): - - def describe_to(self, description): - description.append_text('DESCRIPTION') - - -class StringDescriptionTest(unittest.TestCase): - - def setUp(self): - self.description = StringDescription() - - def testLetsSelfDescribingObjectDescribeItself(self): - self.description.append_description_of(FakeSelfDescribing()) - self.assertEqual('DESCRIPTION', str(self.description)) - - def testDescribesStringInQuotes(self): - self.description.append_description_of('FOO') - self.assertEqual("'FOO'", str(self.description)) - - def testWrapsNonSelfDescribingObjectInAngleBrackets(self): - self.description.append_description_of(42) - self.assertEqual('<42>', str(self.description)) - - def testShouldNotAddAngleBracketsIfObjectDescriptionAlreadyHasThem(self): - self.description.append_description_of(object()) - expected = re.compile("") - self.assertTrue(expected.match(str(self.description))) - - @unittest.skipIf(sys.version_info >= (3,), "Describe unicode strings doesn't malform in Python 3") - def testDescribeUnicodeStringAsBytes(self): - self.description.append_description_of(u'\u05d0') - self.assertEqual("u'\\u05d0'", str(self.description)) - - @unittest.skipUnless(sys.version_info >= (3,), "Describe unicode strings only malforms in Python 2") - def testDescribeUnicodeStringAsUnicode(self): - self.description.append_description_of(u'\u05d0') - self.assertEqual(u"'\u05d0'", str(self.description)) - -if __name__ == "__main__": - unittest.main() diff --git a/hamcrest_unit_test/text/__init__.py b/hamcrest_unit_test/text/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hamcrest_unit_test/text/isequal_ignoring_case_test.py b/hamcrest_unit_test/text/isequal_ignoring_case_test.py deleted file mode 100644 index 283ca3a..0000000 --- a/hamcrest_unit_test/text/isequal_ignoring_case_test.py +++ /dev/null @@ -1,63 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.text.isequal_ignoring_case import equal_to_ignoring_case - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -matcher = equal_to_ignoring_case('heLLo') - -class IsEqualIgnoringCaseTest(MatcherTest): - - def testIgnoresCaseOfCharsInString(self): - self.assert_matches('all upper', matcher, 'HELLO') - self.assert_matches('all lower', matcher, 'hello') - self.assert_matches('mixed up', matcher, 'HelLo') - - self.assert_does_not_match('no match', matcher, 'bye') - - def testFailsIfAdditionalWhitespaceIsPresent(self): - self.assert_does_not_match('whitespace suffix', matcher, 'heLLo ') - self.assert_does_not_match('whitespace prefix', matcher, ' heLLo') - - def testMatcherCreationRequiresString(self): - self.assertRaises(TypeError, equal_to_ignoring_case, 3) - - def testFailsIfMatchingAgainstNonString(self): - self.assert_does_not_match('non-string', matcher, object()) - - def testCanApplyUnicodeStringToUnicodeMatcher(self): - self.assert_matches('unicode-unicode', - equal_to_ignoring_case(u'heLLo'), u'HelLo') - - def testCanApplyPlainStringToUnicodeMatcher(self): - self.assert_matches('unicode-ascii', - equal_to_ignoring_case(u'heLLo'), 'HelLo') - - def testCanApplyUnicodeStringToPlainMatcher(self): - self.assert_matches('ascii-unicode', - equal_to_ignoring_case('heLLo'), u'HelLo') - - def testHasAReadableDescription(self): - self.assert_description("'heLLo' ignoring case", matcher) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(matcher, 'hello') - - def testMismatchDescription(self): - self.assert_mismatch_description("was 'bad'", matcher, 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", matcher, 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py b/hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py deleted file mode 100644 index bcb2495..0000000 --- a/hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py +++ /dev/null @@ -1,75 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.text.isequal_ignoring_whitespace import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -matcher = equal_to_ignoring_whitespace('Hello World how\n are we? ') - -class IsEqualIgnoringWhiteSpaceTest(MatcherTest): - - def testPassesIfWordsAreSameButWhitespaceDiffers(self): - self.assert_matches('less whitespace', - matcher, 'Hello World how are we?') - self.assert_matches('more whitespace', - matcher, ' Hello World how are \n\n\twe?') - - def testFailsIfTextOtherThanWhitespaceDiffers(self): - self.assert_does_not_match('wrong word', - matcher, 'Hello PLANET how are we?') - self.assert_does_not_match('incomplete', - matcher, 'Hello World how are we') - - def testFailsIfWhitespaceIsAddedOrRemovedInMidWord(self): - self.assert_does_not_match('need whitespace between Hello and World', - matcher, 'HelloWorld how are we?') - self.assert_does_not_match('wrong whitespace within World', - matcher, 'Hello Wo rld how are we?') - - def testMatcherCreationRequiresString(self): - self.assertRaises(TypeError, equal_to_ignoring_whitespace, 3) - - def testFailsIfMatchingAgainstNonString(self): - self.assert_does_not_match('non-string', matcher, object()) - - def testCanApplyUnicodeStringToUnicodeMatcher(self): - self.assert_matches('unicode-unicode', - equal_to_ignoring_whitespace(u'foo\nbar'), - u'foo bar') - - def testCanApplyPlainStringToUnicodeMatcher(self): - self.assert_matches('unicode-ascii', - equal_to_ignoring_whitespace(u'foo\nbar'), - 'foo bar') - - def testCanApplyUnicodeStringToPlainMatcher(self): - self.assert_matches('ascii-unicode', - equal_to_ignoring_whitespace('foo\n bar'), - u'foo bar') - - def testDescribesItselfAsIgnoringWhiteSpace(self): - self.assert_description("'foo\\nbar' ignoring whitespace", - equal_to_ignoring_whitespace('foo\nbar')) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description( - equal_to_ignoring_whitespace('foo\nbar'), 'foo bar') - - def testMismatchDescription(self): - self.assert_mismatch_description("was 'bad'", matcher, 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", matcher, 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/text/stringcontains_test.py b/hamcrest_unit_test/text/stringcontains_test.py deleted file mode 100644 index 63d7f15..0000000 --- a/hamcrest_unit_test/text/stringcontains_test.py +++ /dev/null @@ -1,66 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.text.stringcontains import * -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -EXCERPT = 'EXCERPT' -matcher = contains_string(EXCERPT) - -class StringContainsTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self): - self.assert_matches('excerpt at beginning', matcher, EXCERPT + 'END') - self.assert_matches('excerpt at end', matcher, 'START' + EXCERPT) - self.assert_matches('excerpt in middle', - matcher, 'START' + EXCERPT + 'END') - self.assert_matches('excerpt repeated', matcher, EXCERPT + EXCERPT) - - self.assert_does_not_match('excerpt not in string',matcher, 'whatever') - self.assert_does_not_match('only part of excerpt',matcher, EXCERPT[1:]) - - def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self): - self.assert_matches('excerpt is entire string', matcher, EXCERPT) - - def testMatcherCreationRequiresString(self): - self.assertRaises(TypeError, contains_string, 3) - - def testFailsIfMatchingAgainstNonString(self): - self.assert_does_not_match('non-string', matcher, object()) - - def testCanApplyUnicodeStringToUnicodeMatcher(self): - self.assert_matches('unicode-unicode', - contains_string(u'bar'), u'foo bar baz') - - def testCanApplyPlainStringToUnicodeMatcher(self): - self.assert_matches('unicode-ascii', - contains_string(u'bar'), 'foo bar baz') - - def testCanApplyUnicodeStringToPlainMatcher(self): - self.assert_matches('ascii-unicode', - contains_string('bar'), u'foo bar baz') - - def testHasAReadableDescription(self): - self.assert_description("a string containing 'EXCERPT'", matcher) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(matcher, EXCERPT) - - def testMismatchDescription(self): - self.assert_mismatch_description("was 'bad'", matcher, 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", matcher, 'bad') - - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/text/stringcontainsinorder_test.py b/hamcrest_unit_test/text/stringcontainsinorder_test.py deleted file mode 100644 index 1b1fff1..0000000 --- a/hamcrest_unit_test/text/stringcontainsinorder_test.py +++ /dev/null @@ -1,50 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.text.stringcontainsinorder import * - -from hamcrest.core.string_description import StringDescription -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Romilly Cocking" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -matcher = string_contains_in_order('string one', 'string two', 'string three') - -class StringContainsInOrderTest(MatcherTest): - - def testMatchesIfOrderIsCorrect(self): - self.assert_matches('correct order', matcher, - 'string one then string two followed by string three') - - def testDoesNotMatchIfOrderIsIncorrect(self): - self.assert_does_not_match('incorrect order', matcher, - 'string two then string one followed by string three') - - def testDoesNotMatchIfExpectedSubstringsAreMissing(self): - self.assert_does_not_match('missing string one', matcher, 'string two then string three') - self.assert_does_not_match('missing string two', matcher, 'string one then string three') - self.assert_does_not_match('missing string three', matcher, 'string one then string two') - - def testMatcherCreationRequiresString(self): - self.assertRaises(TypeError, string_contains_in_order, 3) - - def testFailsIfMatchingAgainstNonString(self): - self.assert_does_not_match('non-string', matcher, object()) - - def testHasAReadableDescription(self): - self.assert_description("a string containing 'string one', 'string two', 'string three' in order", matcher) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(matcher, 'string one then string two followed by string three') - - def testMismatchDescription(self): - self.assert_mismatch_description("was 'bad'", matcher, 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", matcher, 'bad') diff --git a/hamcrest_unit_test/text/stringendswith_test.py b/hamcrest_unit_test/text/stringendswith_test.py deleted file mode 100644 index ef2403b..0000000 --- a/hamcrest_unit_test/text/stringendswith_test.py +++ /dev/null @@ -1,69 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.text.stringendswith import * - -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -EXCERPT = 'EXCERPT' -matcher = ends_with(EXCERPT) - -class StringEndsWithTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self): - self.assert_does_not_match('excerpt at beginning', - matcher, EXCERPT + 'END') - self.assert_matches('excerpt at end', matcher, 'START' + EXCERPT) - self.assert_does_not_match('excerpt in middle', - matcher, 'START' + EXCERPT + 'END') - self.assert_matches('excerpt repeated', matcher, EXCERPT + EXCERPT) - - self.assert_does_not_match('excerpt not in string', - matcher, 'whatever') - self.assert_does_not_match('only part of excerpt is at end of string', - matcher, EXCERPT[1:]) - - def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self): - self.assert_matches('excerpt is entire string', matcher, EXCERPT) - - def testMatcherCreationRequiresString(self): - self.assertRaises(TypeError, ends_with, 3) - - def testFailsIfMatchingAgainstNonString(self): - self.assert_does_not_match('non-string', matcher, object()) - - def testCanApplyUnicodeStringToUnicodeMatcher(self): - self.assert_matches('unicode-unicode', - ends_with(u'baz'), u'foo bar baz') - - def testCanApplyPlainStringToUnicodeMatcher(self): - self.assert_matches('unicode-ascii', - ends_with(u'baz'), 'foo bar baz') - - def testCanApplyUnicodeStringToPlainMatcher(self): - self.assert_matches('ascii-unicode', - ends_with(u'baz'), u'foo bar baz') - - def testHasAReadableDescription(self): - self.assert_description("a string ending with 'EXCERPT'", matcher) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(matcher, EXCERPT) - - def testMismatchDescription(self): - self.assert_mismatch_description("was 'bad'", matcher, 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", matcher, 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/hamcrest_unit_test/text/stringstartswith_test.py b/hamcrest_unit_test/text/stringstartswith_test.py deleted file mode 100644 index a11b8f5..0000000 --- a/hamcrest_unit_test/text/stringstartswith_test.py +++ /dev/null @@ -1,70 +0,0 @@ -if __name__ == '__main__': - import sys - sys.path.insert(0, '..') - sys.path.insert(0, '../..') - -from hamcrest.library.text.stringstartswith import * - -from hamcrest.core.assert_that import assert_that -from hamcrest.core.core.isnot import is_not -from hamcrest_unit_test.matcher_test import MatcherTest -import unittest - -__author__ = "Jon Reid" -__copyright__ = "Copyright 2011 hamcrest.org" -__license__ = "BSD, see License.txt" - - -EXCERPT = 'EXCERPT' -matcher = starts_with(EXCERPT) -stringstartswith = starts_with(EXCERPT) - -class StringStartsWithTest(MatcherTest): - - def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self): - self.assert_matches('excerpt at beginning', matcher, EXCERPT + 'END') - self.assert_does_not_match('excerpt at end', - matcher, 'START' + EXCERPT) - self.assert_does_not_match('excerpt in middle', - matcher, 'START' + EXCERPT + 'END') - self.assert_matches('excerpt repeated', matcher, EXCERPT + EXCERPT) - - self.assert_does_not_match('excerpt not in string',matcher, 'whatever') - self.assert_does_not_match('only part of excerpt',matcher, EXCERPT[1:]) - - def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self): - self.assert_matches('excerpt is entire string', matcher, EXCERPT) - - def testMatcherCreationRequiresString(self): - self.assertRaises(TypeError, starts_with, 3) - - def testFailsIfMatchingAgainstNonString(self): - self.assert_does_not_match('non-string', matcher, object()) - - def testCanApplyUnicodeStringToUnicodeMatcher(self): - self.assert_matches('unicode-unicode', - starts_with(u'foo'), u'foo bar baz') - - def testCanApplyPlainStringToUnicodeMatcher(self): - self.assert_matches('unicode-ascii', - starts_with(u'foo'), 'foo bar baz') - - def testCanApplyUnicodeStringToPlainMatcher(self): - self.assert_matches('ascii-unicode', - starts_with(u'foo'), u'foo bar baz') - - def testHasAReadableDescription(self): - self.assert_description("a string starting with 'EXCERPT'", matcher) - - def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): - self.assert_no_mismatch_description(matcher, EXCERPT) - - def testMismatchDescription(self): - self.assert_mismatch_description("was 'bad'", matcher, 'bad') - - def testDescribeMismatch(self): - self.assert_describe_mismatch("was 'bad'", matcher, 'bad') - - -if __name__ == '__main__': - unittest.main() diff --git a/setup.py b/setup.py index 03d08a8..ff3fb81 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ # 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('hamcrest/__init__.py')) +fh = open(local('src/hamcrest/__init__.py')) try: for line in fh: if re.match('__version__.*', line): @@ -31,22 +31,22 @@ extra_attributes['use_2to3'] = True params = dict( - name = 'PyHamcrest', - version = __version__, - author = 'Jon Reid', - author_email = 'jon.reid@mac.com', - description = 'Hamcrest framework for matcher objects', - license = 'New BSD', + 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 = 'http://code.google.com/p/hamcrest/', - download_url = 'http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-%s.tar.gz' % __version__, - packages = find_packages(), - test_suite = 'hamcrest-unit-test.alltests', - provides = ['hamcrest'], - long_description=read('README.md'), - install_requires=['distribute'], - classifiers = [ + 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', @@ -56,8 +56,8 @@ 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.1', 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', 'Topic :: Software Development', 'Topic :: Software Development :: Quality Assurance', 'Topic :: Software Development :: Testing', diff --git a/src/PyHamcrest.egg-info/PKG-INFO b/src/PyHamcrest.egg-info/PKG-INFO new file mode 100644 index 0000000..45963ed --- /dev/null +++ b/src/PyHamcrest.egg-info/PKG-INFO @@ -0,0 +1,303 @@ +Metadata-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 diff --git a/src/PyHamcrest.egg-info/SOURCES.txt b/src/PyHamcrest.egg-info/SOURCES.txt new file mode 100644 index 0000000..56cef97 --- /dev/null +++ b/src/PyHamcrest.egg-info/SOURCES.txt @@ -0,0 +1,69 @@ +CHANGES.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.py \ No newline at end of file diff --git a/src/PyHamcrest.egg-info/dependency_links.txt b/src/PyHamcrest.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/PyHamcrest.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/PyHamcrest.egg-info/requires.txt b/src/PyHamcrest.egg-info/requires.txt new file mode 100644 index 0000000..8b6d003 --- /dev/null +++ b/src/PyHamcrest.egg-info/requires.txt @@ -0,0 +1 @@ +setuptools \ No newline at end of file diff --git a/src/PyHamcrest.egg-info/top_level.txt b/src/PyHamcrest.egg-info/top_level.txt new file mode 100644 index 0000000..c5f2ee4 --- /dev/null +++ b/src/PyHamcrest.egg-info/top_level.txt @@ -0,0 +1 @@ +hamcrest diff --git a/src/hamcrest/__init__.py b/src/hamcrest/__init__.py new file mode 100644 index 0000000..8d33888 --- /dev/null +++ b/src/hamcrest/__init__.py @@ -0,0 +1,7 @@ +from core import * +from library import * + +__version__ = "1.8.0" +__author__ = "Chris Rose" +__copyright__ = "Copyright 2013 hamcrest.org" +__license__ = "BSD, see License.txt" diff --git a/src/hamcrest/core/__init__.py b/src/hamcrest/core/__init__.py new file mode 100644 index 0000000..1357054 --- /dev/null +++ b/src/hamcrest/core/__init__.py @@ -0,0 +1,6 @@ +from assert_that import assert_that +from core import * + +__author__ = "Jon Reid" +__copyright__ = "Copyright 2011 hamcrest.org" +__license__ = "BSD, see License.txt" diff --git a/src/hamcrest/core/assert_that.py b/src/hamcrest/core/assert_that.py new file mode 100644 index 0000000..7bbfa97 --- /dev/null +++ b/src/hamcrest/core/assert_that.py @@ -0,0 +1,63 @@ +from 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) diff --git a/src/hamcrest/core/base_description.py b/src/hamcrest/core/base_description.py new file mode 100644 index 0000000..1bca6c5 --- /dev/null +++ b/src/hamcrest/core/base_description.py @@ -0,0 +1,89 @@ +from 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 diff --git a/src/hamcrest/core/base_matcher.py b/src/hamcrest/core/base_matcher.py new file mode 100644 index 0000000..66bf91d --- /dev/null +++ b/src/hamcrest/core/base_matcher.py @@ -0,0 +1,33 @@ +__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) diff --git a/src/hamcrest/core/compat.py b/src/hamcrest/core/compat.py new file mode 100644 index 0000000..2c6d1fa --- /dev/null +++ b/src/hamcrest/core/compat.py @@ -0,0 +1,19 @@ +__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 diff --git a/src/hamcrest/core/core/__init__.py b/src/hamcrest/core/core/__init__.py new file mode 100644 index 0000000..03f3ec3 --- /dev/null +++ b/src/hamcrest/core/core/__init__.py @@ -0,0 +1,17 @@ +"""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" diff --git a/src/hamcrest/core/core/allof.py b/src/hamcrest/core/core/allof.py new file mode 100644 index 0000000..35c5d0b --- /dev/null +++ b/src/hamcrest/core/core/allof.py @@ -0,0 +1,44 @@ +from 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]) diff --git a/src/hamcrest/core/core/anyof.py b/src/hamcrest/core/core/anyof.py new file mode 100644 index 0000000..7a2bfc6 --- /dev/null +++ b/src/hamcrest/core/core/anyof.py @@ -0,0 +1,37 @@ +from 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]) diff --git a/src/hamcrest/core/core/described_as.py b/src/hamcrest/core/core/described_as.py new file mode 100644 index 0000000..93b4d6a --- /dev/null +++ b/src/hamcrest/core/core/described_as.py @@ -0,0 +1,48 @@ +from 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) diff --git a/src/hamcrest/core/core/is_.py b/src/hamcrest/core/core/is_.py new file mode 100644 index 0000000..8e24a6e --- /dev/null +++ b/src/hamcrest/core/core/is_.py @@ -0,0 +1,75 @@ +__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)) diff --git a/src/hamcrest/core/core/isanything.py b/src/hamcrest/core/core/isanything.py new file mode 100644 index 0000000..f916811 --- /dev/null +++ b/src/hamcrest/core/core/isanything.py @@ -0,0 +1,31 @@ +from 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) diff --git a/src/hamcrest/core/core/isequal.py b/src/hamcrest/core/core/isequal.py new file mode 100644 index 0000000..119fd58 --- /dev/null +++ b/src/hamcrest/core/core/isequal.py @@ -0,0 +1,32 @@ +__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) diff --git a/src/hamcrest/core/core/isinstanceof.py b/src/hamcrest/core/core/isinstanceof.py new file mode 100644 index 0000000..c96fdf3 --- /dev/null +++ b/src/hamcrest/core/core/isinstanceof.py @@ -0,0 +1,38 @@ +from 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) diff --git a/src/hamcrest/core/core/isnone.py b/src/hamcrest/core/core/isnone.py new file mode 100644 index 0000000..5ef4f24 --- /dev/null +++ b/src/hamcrest/core/core/isnone.py @@ -0,0 +1,25 @@ +__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()) diff --git a/src/hamcrest/core/core/isnot.py b/src/hamcrest/core/core/isnot.py new file mode 100644 index 0000000..9f458b5 --- /dev/null +++ b/src/hamcrest/core/core/isnot.py @@ -0,0 +1,46 @@ +__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)) diff --git a/src/hamcrest/core/core/issame.py b/src/hamcrest/core/core/issame.py new file mode 100644 index 0000000..b1f8542 --- /dev/null +++ b/src/hamcrest/core/core/issame.py @@ -0,0 +1,39 @@ +__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) diff --git a/src/hamcrest/core/core/raises.py b/src/hamcrest/core/core/raises.py new file mode 100644 index 0000000..191f1df --- /dev/null +++ b/src/hamcrest/core/core/raises.py @@ -0,0 +1,108 @@ +from 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) diff --git a/src/hamcrest/core/description.py b/src/hamcrest/core/description.py new file mode 100644 index 0000000..6201b7f --- /dev/null +++ b/src/hamcrest/core/description.py @@ -0,0 +1,58 @@ +__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') diff --git a/src/hamcrest/core/helpers/__init__.py b/src/hamcrest/core/helpers/__init__.py new file mode 100644 index 0000000..61cb82d --- /dev/null +++ b/src/hamcrest/core/helpers/__init__.py @@ -0,0 +1,5 @@ +"""Utilities for writing Matchers.""" + +__author__ = "Jon Reid" +__copyright__ = "Copyright 2011 hamcrest.org" +__license__ = "BSD, see License.txt" diff --git a/src/hamcrest/core/helpers/hasmethod.py b/src/hamcrest/core/helpers/hasmethod.py new file mode 100644 index 0000000..a1f3bfb --- /dev/null +++ b/src/hamcrest/core/helpers/hasmethod.py @@ -0,0 +1,12 @@ +__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) diff --git a/src/hamcrest/core/helpers/wrap_matcher.py b/src/hamcrest/core/helpers/wrap_matcher.py new file mode 100644 index 0000000..84322a4 --- /dev/null +++ b/src/hamcrest/core/helpers/wrap_matcher.py @@ -0,0 +1,29 @@ +from 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 diff --git a/src/hamcrest/core/matcher.py b/src/hamcrest/core/matcher.py new file mode 100644 index 0000000..f76c7bc --- /dev/null +++ b/src/hamcrest/core/matcher.py @@ -0,0 +1,51 @@ +from 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') diff --git a/src/hamcrest/core/selfdescribing.py b/src/hamcrest/core/selfdescribing.py new file mode 100644 index 0000000..e77b0e0 --- /dev/null +++ b/src/hamcrest/core/selfdescribing.py @@ -0,0 +1,18 @@ +__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') diff --git a/src/hamcrest/core/selfdescribingvalue.py b/src/hamcrest/core/selfdescribingvalue.py new file mode 100644 index 0000000..dfa4e3a --- /dev/null +++ b/src/hamcrest/core/selfdescribingvalue.py @@ -0,0 +1,27 @@ +from 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) diff --git a/src/hamcrest/core/string_description.py b/src/hamcrest/core/string_description.py new file mode 100644 index 0000000..7c97488 --- /dev/null +++ b/src/hamcrest/core/string_description.py @@ -0,0 +1,33 @@ +from 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 diff --git a/src/hamcrest/library/__init__.py b/src/hamcrest/library/__init__.py new file mode 100644 index 0000000..2d3984f --- /dev/null +++ b/src/hamcrest/library/__init__.py @@ -0,0 +1,43 @@ +"""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', +] diff --git a/src/hamcrest/library/collection/__init__.py b/src/hamcrest/library/collection/__init__.py new file mode 100644 index 0000000..2f89987 --- /dev/null +++ b/src/hamcrest/library/collection/__init__.py @@ -0,0 +1,16 @@ +"""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" diff --git a/src/hamcrest/library/collection/is_empty.py b/src/hamcrest/library/collection/is_empty.py new file mode 100644 index 0000000..bc99b63 --- /dev/null +++ b/src/hamcrest/library/collection/is_empty.py @@ -0,0 +1,35 @@ +from 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() diff --git a/src/hamcrest/library/collection/isdict_containing.py b/src/hamcrest/library/collection/isdict_containing.py new file mode 100644 index 0000000..9528197 --- /dev/null +++ b/src/hamcrest/library/collection/isdict_containing.py @@ -0,0 +1,54 @@ +from 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)) diff --git a/src/hamcrest/library/collection/isdict_containingentries.py b/src/hamcrest/library/collection/isdict_containingentries.py new file mode 100644 index 0000000..6e15ab7 --- /dev/null +++ b/src/hamcrest/library/collection/isdict_containingentries.py @@ -0,0 +1,134 @@ +from 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) diff --git a/src/hamcrest/library/collection/isdict_containingkey.py b/src/hamcrest/library/collection/isdict_containingkey.py new file mode 100644 index 0000000..ccb51e6 --- /dev/null +++ b/src/hamcrest/library/collection/isdict_containingkey.py @@ -0,0 +1,48 @@ +from 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)) diff --git a/src/hamcrest/library/collection/isdict_containingvalue.py b/src/hamcrest/library/collection/isdict_containingvalue.py new file mode 100644 index 0000000..e528884 --- /dev/null +++ b/src/hamcrest/library/collection/isdict_containingvalue.py @@ -0,0 +1,48 @@ +from 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)) diff --git a/src/hamcrest/library/collection/isin.py b/src/hamcrest/library/collection/isin.py new file mode 100644 index 0000000..87962a2 --- /dev/null +++ b/src/hamcrest/library/collection/isin.py @@ -0,0 +1,30 @@ +from 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) diff --git a/src/hamcrest/library/collection/issequence_containing.py b/src/hamcrest/library/collection/issequence_containing.py new file mode 100644 index 0000000..21939b3 --- /dev/null +++ b/src/hamcrest/library/collection/issequence_containing.py @@ -0,0 +1,89 @@ +__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) diff --git a/src/hamcrest/library/collection/issequence_containinginanyorder.py b/src/hamcrest/library/collection/issequence_containinginanyorder.py new file mode 100644 index 0000000..78e2b00 --- /dev/null +++ b/src/hamcrest/library/collection/issequence_containinginanyorder.py @@ -0,0 +1,97 @@ +from 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) diff --git a/src/hamcrest/library/collection/issequence_containinginorder.py b/src/hamcrest/library/collection/issequence_containinginorder.py new file mode 100644 index 0000000..3fd91a6 --- /dev/null +++ b/src/hamcrest/library/collection/issequence_containinginorder.py @@ -0,0 +1,88 @@ +__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) diff --git a/src/hamcrest/library/collection/issequence_onlycontaining.py b/src/hamcrest/library/collection/issequence_onlycontaining.py new file mode 100644 index 0000000..0db4546 --- /dev/null +++ b/src/hamcrest/library/collection/issequence_onlycontaining.py @@ -0,0 +1,55 @@ +from 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)) diff --git a/src/hamcrest/library/integration/__init__.py b/src/hamcrest/library/integration/__init__.py new file mode 100644 index 0000000..873dc06 --- /dev/null +++ b/src/hamcrest/library/integration/__init__.py @@ -0,0 +1,7 @@ +"""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" diff --git a/src/hamcrest/library/integration/match_equality.py b/src/hamcrest/library/integration/match_equality.py new file mode 100644 index 0000000..52da054 --- /dev/null +++ b/src/hamcrest/library/integration/match_equality.py @@ -0,0 +1,42 @@ +from 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)) diff --git a/src/hamcrest/library/number/__init__.py b/src/hamcrest/library/number/__init__.py new file mode 100644 index 0000000..722a1eb --- /dev/null +++ b/src/hamcrest/library/number/__init__.py @@ -0,0 +1,8 @@ +"""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" diff --git a/src/hamcrest/library/number/iscloseto.py b/src/hamcrest/library/number/iscloseto.py new file mode 100644 index 0000000..b6bbab5 --- /dev/null +++ b/src/hamcrest/library/number/iscloseto.py @@ -0,0 +1,73 @@ +from 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) diff --git a/src/hamcrest/library/number/ordering_comparison.py b/src/hamcrest/library/number/ordering_comparison.py new file mode 100644 index 0000000..c3c75f4 --- /dev/null +++ b/src/hamcrest/library/number/ordering_comparison.py @@ -0,0 +1,59 @@ +from 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') diff --git a/src/hamcrest/library/object/__init__.py b/src/hamcrest/library/object/__init__.py new file mode 100644 index 0000000..fdc73c4 --- /dev/null +++ b/src/hamcrest/library/object/__init__.py @@ -0,0 +1,9 @@ +"""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" diff --git a/src/hamcrest/library/object/haslength.py b/src/hamcrest/library/object/haslength.py new file mode 100644 index 0000000..3ef0ab5 --- /dev/null +++ b/src/hamcrest/library/object/haslength.py @@ -0,0 +1,50 @@ +from 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)) diff --git a/src/hamcrest/library/object/hasproperty.py b/src/hamcrest/library/object/hasproperty.py new file mode 100644 index 0000000..d2536d6 --- /dev/null +++ b/src/hamcrest/library/object/hasproperty.py @@ -0,0 +1,154 @@ +from 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()]) diff --git a/src/hamcrest/library/object/hasstring.py b/src/hamcrest/library/object/hasstring.py new file mode 100644 index 0000000..8b50547 --- /dev/null +++ b/src/hamcrest/library/object/hasstring.py @@ -0,0 +1,40 @@ +from 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)) diff --git a/src/hamcrest/library/text/__init__.py b/src/hamcrest/library/text/__init__.py new file mode 100644 index 0000000..167fcbe --- /dev/null +++ b/src/hamcrest/library/text/__init__.py @@ -0,0 +1,13 @@ +"""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" diff --git a/src/hamcrest/library/text/isequal_ignoring_case.py b/src/hamcrest/library/text/isequal_ignoring_case.py new file mode 100644 index 0000000..5e2b679 --- /dev/null +++ b/src/hamcrest/library/text/isequal_ignoring_case.py @@ -0,0 +1,42 @@ +from 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) diff --git a/src/hamcrest/library/text/isequal_ignoring_whitespace.py b/src/hamcrest/library/text/isequal_ignoring_whitespace.py new file mode 100644 index 0000000..8925598 --- /dev/null +++ b/src/hamcrest/library/text/isequal_ignoring_whitespace.py @@ -0,0 +1,56 @@ +from 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) diff --git a/src/hamcrest/library/text/stringcontains.py b/src/hamcrest/library/text/stringcontains.py new file mode 100644 index 0000000..58ffd28 --- /dev/null +++ b/src/hamcrest/library/text/stringcontains.py @@ -0,0 +1,38 @@ +from 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) diff --git a/src/hamcrest/library/text/stringcontainsinorder.py b/src/hamcrest/library/text/stringcontainsinorder.py new file mode 100644 index 0000000..f2c4da9 --- /dev/null +++ b/src/hamcrest/library/text/stringcontainsinorder.py @@ -0,0 +1,51 @@ +from 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) diff --git a/src/hamcrest/library/text/stringendswith.py b/src/hamcrest/library/text/stringendswith.py new file mode 100644 index 0000000..43f9c3d --- /dev/null +++ b/src/hamcrest/library/text/stringendswith.py @@ -0,0 +1,39 @@ +from 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) diff --git a/src/hamcrest/library/text/stringmatches.py b/src/hamcrest/library/text/stringmatches.py new file mode 100644 index 0000000..28dd62f --- /dev/null +++ b/src/hamcrest/library/text/stringmatches.py @@ -0,0 +1,38 @@ +from 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) diff --git a/src/hamcrest/library/text/stringstartswith.py b/src/hamcrest/library/text/stringstartswith.py new file mode 100644 index 0000000..a0af49c --- /dev/null +++ b/src/hamcrest/library/text/stringstartswith.py @@ -0,0 +1,39 @@ +__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) diff --git a/src/hamcrest/library/text/substringmatcher.py b/src/hamcrest/library/text/substringmatcher.py new file mode 100644 index 0000000..abe6445 --- /dev/null +++ b/src/hamcrest/library/text/substringmatcher.py @@ -0,0 +1,19 @@ +from 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)